46. 함수 바인딩
2026년 4월 15일
객체 메서드를 콜백으로 전달할 때, 마치 손에 쥔 모래처럼 this가 빠져나가는 경험을 해보셨을 겁니다. 자바스크립트의 함수는 호출되는 방식에 따라 this가 결정되는 '유연함'을 가졌지만, 때로는 이 유연함이 독이 되기도 하죠.
🕵️ 1. 왜 this가 사라질까?
setTimeout 같은 내장 함수에 객체의 메서드를 넘기면, 객체와의 연결고리가 끊어지고 함수 그 자체만 전달됩니다.
- 현상:
setTimeout(user.sayHi, 1000)을 호출하면, 1초 뒤에user.sayHi가 실행되지만this는 더 이상user가 아닌 전역 객체(브라우저에선window)를 바라보게 됩니다. - 결과:
this.firstName은window.firstName이 되어undefined를 반환하게 되죠.
🛠️ 2. 해결책 1: 래퍼(Wrapper) 함수
가장 직관적인 방법은 메서드를 직접 호출하는 짧은 함수로 감싸는 것입니다.
setTimeout(() => user.sayHi(), 1000);
- 원리: 외부 렉시컬 환경에서
user객체를 가져와서 일반적인 방식으로 호출하므로this가 유지됩니다. - 리스크: 만약 1초가 지나기 전에
user변수가 다른 객체로 바뀌어버리면, 바뀐 객체의 메서드를 호출하게 되는 취약점이 있습니다.
⚓ 3. 해결책 2: bind 메서드
모든 함수가 가진 내장 메서드 bind는 this를 특정 객체로 영구히 고정시킨 특수 객체를 반환합니다.
let sayHi = user.sayHi.bind(user); setTimeout(sayHi, 1000); // 이제 user가 바뀌어도 안전합니다!
- 특징:
bind로 생성된 '묶인 함수(bound function)'는 한 번 고정되면call이나apply를 써도this를 바꿀 수 없습니다. - 안정성: 함수가 어디서 어떻게 호출되든 우리가 지정한
context를 끝까지 기억합니다.
🧮 4. 보너스: 부분 적용 (Partial Application)
bind는 this 뿐만 아니라 **인수(arguments)**도 미리 고정할 수 있습니다.
function mul(a, b) { return a * b; } // 'this'는 null로 두고, 첫 번째 인수를 2로 고정한 새로운 함수 생성 let double = mul.bind(null, 2); alert( double(3) ); // mul(2, 3) = 6
- 유용성: 아주 포괄적인 함수를 기반으로 더 구체적인 변형 함수(예:
double,triple)를 만들 때 가독성을 획기적으로 높여줍니다.
🎙️ 기술 면접 대비 (Interview Questions)
Q1. bind를 두 번 연속해서 사용하면(f.bind(obj1).bind(obj2)) this는 어떻게 되나요? (중급)
답변: 첫 번째 바인딩인 **
obj1**이 유지됩니다.bind가 반환하는 객체는 생성 시점의 컨텍스트만 기억하며, 이미 바인딩된 함수를 다시bind하더라도 내부의this를 변경할 수 없도록 설계되어 있습니다.
Q2. 화살표 함수에서 bind를 사용할 수 있나요? (심화)
답변: 문법적으로 호출은 가능하지만
this를 바인딩하는 효과는 없습니다. 화살표 함수는 자신만의this를 가지지 않고 외부 스코프의this를 결정적으로 사용하기 때문입니다. 따라서 화살표 함수에bind를 쓰는 것은 의미가 없으며, 주로 일반 함수 표현식에서 사용됩니다.
💡 Tech Lead의 한 줄 인사이트
"리액트의 클래스형 컴포넌트 시절에는 생성자에서 메서드들을 일일이
bind(this)해주는 게 일상이었죠. 지금은 화살표 함수를 클래스 필드로 써서 이 문제를 우아하게 넘기곤 합니다. 하지만 라이브러리 개발이나 로우레벨 로직을 짤 때bind를 활용한 부분 적용 기법은 여전히 코드의 재사용성을 높여주는 강력한 무기입니다."