MooTools 의 bind 와 클로저(Closure)
MooTools 를 사용하다보면 bind 라는 말이 종종 등장하고 documents 를 보다봐도 인자로 bind 가 자주 등장합니다. 처음 MooTools 를 접해 사용하면 이 bind 의 개념을 잡지 못해 헷갈리곤 합니다. 저도 첨엔 그랬습니다. 이 글에서는 이 bind 에 대해 가능한 최대한 아는대로 설명해 보겠습니다.
그리고, 이 글은 방명록에 펑크테디 님께서 남겨주신 질문에 대한 답이기도 합니다.
bind
MooTools 의 주요 함수들에 함수가 인자로 넘어갈때는 대부분 bind 인자가 함께 따라오는데요, 그 bind 인자에 대해 이렇게 설명하고 있습니다.
bind – (object) The object that the “this” of the function will refer to.
즉, bind 인자는 “해당 함수에서 this 로 참조할 객체” 정도 되겠네요. 예를 하나 보겠습니다.
// 사랑을 고백할 Lover 객체를 만듭니다.
// 인자로 넘어온 lover 가 해당 객체의 this.lover 에 저장됩니다.
var Lover = function(lover) {
this.lover = lover;
};
// 고백할 함수를 추가합니다.
// 인자로 넘어온 who 에게 this.lover 가 고백 하는 함수입니다.
Lover.prototype.confess = function(who) {
alert(this.lover + ' loves ' + who);
};
// 사랑을 고백할 gun이를 만듭니다. gun 의 this.lover 는 '건이' 가 될겁니다.
var gun = new Lover('건이');
// 이제 MooTools 의 Array.each 를 사용해 엄마, 아빠에게 고백합니다.
// 함수 인자로는 익명의 Lover 의 confess를 전달합니다.
// 이 new Lover().confess 에는 this.lover 가 없는 상태입니다.
// bind 인자로는 gun 을 할당합니다.
['아빠', '엄마'].each( new Lover().confess, gun );
마지막 인자로 넘어간 new Lover().confess 를 그냥 실행하면 누가 고백을 하는지 모를겁니다. new Lover() 의 this.lover에 아무 값도 할당 하지 않았으니까요. 하지만 두번째 bind 인자로 gun 을 넘겨서 new Lover().confess 의 this.lover 는 gun의 this.lover 가 사용되서 다음과 같이 이쁘게 고백할겁니다.
건이 loves 아빠.
건이 loves 엄마.
앞에서 언급한 “해당 함수에서 this 로 참조할 객체” 를 다시 보자면, “new Lover().confess 함수에서 사용할 this 가 참조할 객체가 gun 이 되는것” 입니다. 즉, new Lover().confess 의 this.lover 가 gun 의 this.lover 인 ‘건이’ 가 되는 겁니다.
예가 좀 억지스럽긴 하지만 이런 모습은 주로 DOM 객체에 이벤트를 할당할 때 자주 보게 되는 모습입니다. 이정도 이해로도 MooTools 를 사용하는데는 지장이 없을거라고 생각합니다만 … 사실 MooTools 의 bind 는 javascript 의 closure 와 깊게 관련이 있습니다. 즉, 정확히 이해하기 위해서는 closure 에 대한 이해가 선행 되야 합니다.
클로저(Closure)
클로저(Closure) 에 대한 설명은 아래 문서 링크들로 대신 하겠습니다.
closure 에 대한 이해가 없으신 분들은 일독을 권합니다.
- JavaScript Closures for Dummies (영문) – 추천
더미 시리즈의 일부 처럼 꾸며서 아주 쉽게 설명된 영문 문서입니다. - Javascript Closures (영문)
클로저에 대해 아주 상세하게 설명하고 있는 영문 문서입니다. 클로저로 할 수 있는 3가지 예제도 함께 제공하고 있습니다. - 클로저 (Closure) – 마틴 파울러 (한글)
closure 에 대해 설명하고, 이를 C#, Java, C 등에서 보이는 유사한 기법들과의 차이점을 설명하는 마틴 파울러의 closure 에 대한 번역문 입니다. Javascript 에 대한 언급은 없습니다. - Closure in javascript (자바스크립트에서 클로져는 무엇인가?) – 추천
클로저에 대해 그림과 함께 명쾌하게 설명하고 있으며 클로저 사용에 따른 메모리 누수도 언급하고 있는 가장 추천하는 문서입니다. 사실은, closure 에 대해서 설명을 해보려다가 이 문서를 찾고 포기했습니다. 하하. - Java theory and practice: 클로저(closure) 논의 (한글)
Java 에 Closure를 추가하는 문제에 대한 논의입니다. 거의 1년이나 지난 문서네요.
이해 하셨나요 ?
Closure & MooTools bind
그렇다면 MooTools 에서 클로저가 적용되는 부분을 보겠습니다.
// 새로운 클래스를 만듭니다.
// id 와 name 을 인자로 받습니다.
// ID 가 id 인 Element 를 클릭했을 때 name 을 출력합니다.
var Alert = new Class({
initialize: function(id, name) {
this.name = name;
this.initButton(id);
},
initButton: function(id) {
$(id).addEvent('click', function() { alert(this.name); });
}
});
// DOM 이 준비되면
// id 가 button 인 element 를 클릭했을 때 '양군' 이 출력되도록합니다.
window.addEvent('domready', function(){
new Alert('button', '양군');
});
어떻겠습니까 ? 위의 코드는 잘 동작할까요 ?
위의 코드는 원하는대로 동작하지 않습니다. 바로 addEvent 에 전달된 function() {alert(this.name);} 이 문제가 되는데요. 이 부분이 closure 가 됩니다.
우리가 원하는것은 alert(this.name); 이 Alert 내에서 쓰였으므로 this 가 Alert 이길 바라지만 실제 이 closure 가 평가되는 부분은 DOM Element 에서입니다. 그래서 실제로 수행하게 되면 this 는 Alert 가 아니라 $(‘button’)이 됩니다.
var Alert = new Class({
initialize: function(id, name) {
this.name = name;
this.initButton(id);
},
initButton: function(id) {
// this.get('id') 를 출력해 해당 element의 id를 출력하도록 변경.
$(id).addEvent('click', function() { alert(this.get('id')); });
}
});
window.addEvent('domready', function(){
new Alert('button', '양군');
});
이렇게 수정해서 실행하면 ‘button’이 출력됩니다. alert(this.get(‘id’)); 에서 this 가 $(id) 가 되기 때문에 문제 없습니다. 그렇다면 처음의 코드를 어떻게 수정해야 원하는대로 동작할까요.
바로 MooTools 에서 제공하는 Function::bind 를 사용하면 됩니다. 수정된 코드는 아래와 같습니다.
var Alert = new Class({
initialize: function(id, name) {
this.name = name;
this.initButton(id);
},
initButton: function(id) {
// this 를 bind 로 넘겨 closure 를 생성합니다.
$(id).addEvent('click', (function() { alert(this.name); }).bind(this));
}
});
window.addEvent('domready', function(){
new Alert('button', '양군');
});
Function::bind 는 해당 함수내에서 this 가 참조할 객체를 설정하면서 closure 를 생성합니다.
Function::bind 의 인자에 대한 설명입니다.
1. bind – (object, optional) The object that the “this” of the function will refer to.
2. args – (mixed, optional) The arguments to pass to the function (must be an array if passing more than one argument).
Conclusion
보시면 알겠지만 MooTools 의 bind 를 사용하는데 Closure 의 이해는 사실 필요 없습니다, 다만 필요한 인자의 타입이 함수인 경우에 Function::bind, Function::bindWithEvent, Function::pass 등의 함수를 이용해 함수를 만들어주면 됩니다. 그리고 bind 인자에 대한 이해 정도만 있으면 됩니다. 이는 closure에 대한 이해가 필요한 부분을 MooTools 가 내부에서 감쇠시키고 있기 때문입니다. 즉, 그런거 잘 몰라도 MooTools만 쓸 줄 알면 되도록 해주고 있는겁니다.
하지만, Closure 에 대한 이해가 선행된다면 MooTools 혹은 다른 JavaScript 라이브러리의 사용이 더욱 자유롭고 유연해질 수 있을거라고 믿습니다. 그리고 우리에게 언제나 MooTools를 사용할 수 있는 환경이 제공되지는 않을거라는 걸 잘 알고 있기 때문에라도 Closure에 대한 이해는 필요합니다.
May the force be with you.

정말 감사합니다. 엄청 자세하게 설명해주셨네요
열심히 읽어보고 이해하는 일만 남았군요..
펑크테디 님
아닙니다. 마침 포스팅 꺼리도 없었는데 잘됐다 싶어 달렸봤습니다. ^^
부디 도움이 되었길 바랍니다.