프린스 알리 2025. 1. 24. 21:20

내일배움캠프 Node.js 트랙 60일차

자바스크립트의 함수 바인딩

자바스크립트에서 함수는 객체로 취급되며, 따라서 변수에 저장되거나 다른 객체의 속성으로 할당될 수 있다. 그러나 함수가 일반 변수처럼 동작할 수 있다는 점에서, 호출 시 컨텍스트(context)가 변경될 수 있다는 점은 주의가 필요하다. 이때, 원하는 컨텍스트로 함수를 호출할 수 있도록 도와주는 개념이 "바인딩(binding)"이다.

자바스크립트의 함수 바인딩은 평소엔 존재감이 없는 듯하다가 잊을만하면 발목을 붙잡는 개념이다. 특히 객체 메서드를 콜백으로 전달할 때 발생하는 'this' 정보 손실 문제를 해결하는 데 핵심적인 역할을 한다.

'this' 컨텍스트 손실 문제

객체 메서드가 객체 외부에서 호출될 때 'this' 컨텍스트가 손실되는 문제가 발생한다. this는 함수 호출 방식에 따라 값이 결정된다. 객체의 메서드로 호출된 함수는 해당 객체를 this로 참조하지만, 독립적으로 호출된 함수는 thisundefined가 되거나 전역 객체를 참조한다. 예를 들어 setTimeout 사용할 땐 콜백 함수가 필요한데, 이 인자로 객체 메서드를 전달하려 했을 때 이런 현상이 일어난다.

let user = {
  firstName: "John",
  sayHi() {
    alert(`Hello, ${this.firstName}!`);
  }
};

setTimeout(user.sayHi, 1000); 
// 실행 결과 : Hello, undefined!

해결 방법

래퍼 함수 사용

가장 간단한 해결책은 래퍼 함수를 사용하는 것이다. 이 방법은 외부 렉시컬 환경에서 객체를 가져와 메서드를 호출한다.

let user = {
  firstName: "John",
  sayHi() {
    alert(`Hello, ${this.firstName}!`);
  }
};

setTimeout(function() {
  user.sayHi(); // Hello, John!
}, 1000);

bind 메서드 사용

함수의 bind 메서드는 새로운 함수를 생성하면서, this의 값을 고정시키는 역할을 한다. 이를 통해 함수 호출 방식에 상관없이 지정된 this 값을 유지할 수 있다.

기본 사용법

let user = {
  firstName: "John",
  sayHi() {
    console.log(`Hello, ${this.firstName}!`);
  }
};

let sayHi = user.sayHi.bind(user);
sayHi(); // "Hello, John!"

위 예제에서 user.sayHi 메서드는 bind를 사용하여 user 객체를 this로 고정했다. 이제 sayHi를 호출할 때마다 this는 항상 user를 가리킨다

인자 바인딩

bindthis 뿐만 아니라 함수의 인수도 고정할 수 있다. 이를 "부분 적용(partial application)"이라고 한다.

function multiply(a, b) {
  return a * b;
}

let double = multiply.bind(null, 2);
console.log(double(3)); // 6
console.log(double(5)); // 10

multiply.bind(null, 2)multiply 함수의 첫 번째 인수를 2로 고정한 새로운 함수를 반환한다.

바인딩이 필요한 상황

콜백에서의 컨텍스트 문제

콜백 함수에서 this가 예상치 못한 값을 참조하는 경우가 자주 발생한다. 이를 해결하기 위해 바인딩이 필요하다.

let user = {
  firstName: "Alice",
  sayHi() {
    console.log(`Hi, ${this.firstName}!`);
  }
};

setTimeout(user.sayHi.bind(user), 1000); // "Hi, Alice!"

만약 bind를 사용하지 않는다면 setTimeout에 전달된 함수는 this가 전역 객체나 undefined를 참조하게 된다.

메서드 전달

객체의 메서드를 다른 변수에 할당하거나, 인자로 전달할 때도 bind를 사용하여 this를 고정해야 한다.

let user = {
  firstName: "Bob",
  sayHi() {
    console.log(`Hi, ${this.firstName}!`);
  }
};

let sayHi = user.sayHi;
sayHi(); // 에러 또는 예상치 못한 동작

let boundSayHi = user.sayHi.bind(user);
boundSayHi(); // "Hi, Bob!"

 

 

출처 : 함수 바인딩