태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

 

* Closure는 자바스크립트에서 수 많은 응용들을 할 수 있는 정말로 중요한 개념이나 자바스크립트라는 언어를 더욱더 빛내줄 수 있는 특징이다. Closure를 모르고 자바스크립트를 개발하는 것은 10년전의 웹 언어 중심의 개발 방법론에 머무르고 있는 것과 같은 것이기 때문에 10년전 웹개발자에서 진정한 자바스크립트 개발자로 나아가기 위한 기본을 이제부터 들여다보자.

 

- 이전 글

 

2012/12/10 - [속깊은 자바스크립트 강좌] 시작 (예고편)

2012/12/17 - [속깊은 자바스크립트 강좌] 자바스크립트의 Scope와 Closure 기초

2013/01/07 - [속깊은 자바스크립트 강좌] function declaration vs function expression 차이점

2013/01/10 - [속깊은 자바스크립트 강좌] 함수를 호출하는 방법과 this의 이해

2013/01/21 - [속깊은 자바스크립트 강좌] Closure의 이해 / 오버로딩 구현하기

 

* Closure?

: 이전글에서 Closure에 대하여 이해를 할 수 있는 여러 가지 예들을 들여다 봤지만 실제적으로 이해는 약간 힘들었을 것이다. Closure는 자바스크립트에 있어서 C로 치자면 C에서 포인터를 바라보는 관점하고 똑같다. C에서 포인터를 이해하기를 포기하고 돌아서게 되면 진정으로 깊이 있는 C 개발자가 못 되듯이 자바스크립트에서도 Closure를 이해하지 못하면 깊이 있는 자바스크립트 개발자, 또는 웹 개발자가 되지 못하게 되는 것이다. 하지만 중요한 것은 "Closure는 뛰어난 기술이 아니다"라는 것이다. 포인터의 개념을 주소라는 개념으로 받아들이기 시작하면 아주 쉽게 이해하듯이 closure 또한 scope chain에서 하나의 scope를 생성해준다는 개념으로 이해한다면 아주 쉽게 이해가 가능할 것이다. 그렇다면 먼저 scope chain에 대해서 알아봐야할 것이다.

 

 

* Scope chain

: Scope chain은 이전 글에서 이미 다뤘던 내용이다. 하지만 이 개념과 closure를 반드시 연결해서 생각해야만 closure를 이해할 수 있다. Scope chain에 대해서 설명을 다시 하겠지만, 이전 글을 다시 훑어보고 와도 괜찮을 것이다.

 

- 참고

2012/12/17 - [속깊은 자바스크립트 강좌] 자바스크립트의 Scope와 Closure 기초

 

: 여기서 들었던 예는 다음과 같았다.

<div id="divScope0">Click me! DIV 0</div>
<div id="divScope1">Click me! DIV 1</div>
<div id="divScope2">Click me! DIV 2</div>
<script>
    function setDivClick(index) {
        document.getElementById("divScope" + index).addEventListener("click", function () {  // #1
            alert("You clicked div #" + index);
        }, false);
    }
    var i, len = 3;
    for (i = 0; i < len; i++) {
        setDivClick(i);
    }
</script>

 

: 여기서 이전글에서 말했던 closure가 생성되는 규칙을 발견할 수 있을 것이다. function 키워드를 따라가면서 확인해보면 위의 setDivClick 함수가 선언된 부분 안에 #1의 부분에 함수가 하나 선언 되어 addEventListener 함수의 인자로 넘어가고 있다. 바로 function 안에 function을 넣은 것이다. 그리고 이전 글 중에서 [속깊은 자바스크립트 강좌] 자바스크립트의 Scope와 Closure 기초의 글에서 Scope는 function을 기반으로 생성된다는 말을 했다. 그렇다면 function 안에 다른 function을 다시 선언한다는 것은 다른 말로 하나의 scope안에 다른 scope를 선언한다고도 볼 수 있다. 이것이 바로 scope 안에 scope를 만들어서 scope chain을 생성하는 과정이다. 위의 글에 있었던 그림도 다시 한번 보자.

 

위의 예에서 scope chain이 형성된 그림

 

: 여기서 setDivClick으로 생성된 scope의 안에 각 addEventListener의 인자로 선언된 함수들의 scope가 하위에서 setDivClick 함수의 scope를 참조하는 것을 알 수 있다. 이렇게 여러 개의 함수 안에 함수가 호출되면 하위 scope를 생성하여 상위 scope의 변수들을 접근할 수 있는 것을 scope chain이라고 하는 것이다. 여기서 중요한 것은 하위 scope에 해당하는 function이 살아있다면 상위의 scope들은 죽지 않고 계속 살아있게 된다는 것이고 이것이 closure의 가장 기본적인 개념이다. 즉, 위의 div0.onclick 이라는 함수가 살아있는 동안 setDivClick을 통해 생성되었던 scope는 계속 살아있게 된다.

 

 

* 기본적인 예

: Closure를 이해하기 쉽게 sum 이라는 함수를 선언해보자.

function sum(base) {
    var inClosure = base; // #1
    return function (adder) {   // #2
        return inClosure + adder;
    };
};    // #3
var fiveAdder = sum(5); // #4: inClosure를 5로 설정하고 #2의 함수 리턴
fiveAdder(3); // === inClosure(5) + adder(3) === 8
var threeAdder = sum(3); // #5: inClosure를 3으로 설정하고 #2의 함수 리턴

 

: 위의 예에서도 보면 function 안에 function이 선언되고 내부의 function이 리턴 되는 것을 볼 수 있고 외부 함수에서 base 인자가 넘어오면 내부의 함수에서는 inClosure 변수를 설정하게 된다. 이렇게 소스코드를 통해서 scope가 생성되는 것을 한번 살펴보면 아래와 같이 된다.

  

 

: 이것은 scope의 뼈대, 또는 template이라고 보면 된다. 중요한 것은 위의 scope가 실제로 생성 된것이 아니라는 점이다. 그냥 만약에 scope가 생성된다면 위의 구조를 가지게 된다는 것을 그림으로 표현해본 것이다. 만약 sum 함수의 내부 함수를 받아서 사용하게 된다면 위의 scope를 따르게 된다. 그럼 위의 뼈대를 토대로 하나씩 실행되는 과정을 한줄씩 살펴보자.


var fiveAdder = sum(5);

 

: 위의 구문을 통해 function sum이 호출 되고 base는 5로 넘어오고 inClosure 변수도 5로 설정한다. 그리고 inClosure 변수를 참조하는 내부 함수를 리턴하여 fiveAdder에 대입한다. 현재 fiveAdder의 scope 상황은 다음과 같을 것이다.



: 위의 scope 뼈대에서 fiveAdder는 실제로 사용하게 되는 함수 A를 할당 받게 되어 위의 scope 뼈대를 통해 하나의 scope chain을 생성하여 가지고 있게 된다. fiveAdder는 오른쪽의 A 함수를 받아 가지고 있게 된다. 여기서 fiveAdder에서 할당 받는 함수 A는 어디서 온것인가 보면, 바로 #2에서 리턴한 그 함수가 바로 A인 것이다.

 

: 이제부터 fiveAdder를 통해 함수를 접근하게 되면 위의 scope chain을 따르게 된다. 여기서 하나 짚고 넘어가자면, 그림상으로 왠지 순환 구조를 가지고 있는 듯 하지만 모든 scope는 global scope에서 끝나게 된다. 그리고 global scope에 있는 fiveAdder는 scope chain이 이어진 것이 아니라 오른쪽 함수 A의 레퍼런스, C에서 말하자면 포인터를 가지고 있는 것이고, 나중에 fiveAdder를 실제로 '호출'하게 될 때에 위의 오른쪽 A는 해당하는 scope chain을 사용하게 된다는 것이다. 이 scope chain은 fiveAdder가 또 다른 함수의 인자로 넘어가든 fiveAdder가 메모리에서 사라질때까지 계속 유지하게 된다. 이것이 이전 글에서 말했던 '퍼포먼스의 문제'에 대하여 조금 더 깊게 이해할 수 있을 것이다. 이제 fiveAdder(3)을 호출하게 되면 오른쪽 A의 adder 인자에 3이 들어가게 되고, 내부 함수에서 inClosure + adder를 하게 되면 바로 위의 scope에 있는 inClosure = 5와 인자인 adder = 3을 이용하여 8이라는 값을 리턴하게 된다. 여기까지는 그렇게 특별할 것이 없다. 이제 다음으로 넘어가면,

var threeAdder = sum(3);

: 그렇다면 이번에는 다시 threeAdder를 호출하게 되면 어떻게 될까. 이번에는 상당히 생각이 많아질지도 모른다. 기분상 fiveAdder의 inClosure까지 변환되어 버릴 것 같지만 그렇지 않다.



: 위와 같이 함수 B가 사용하는 하나의 새로운 scope chain이 생성되어 threeAdder에서 사용하도록 된다. 같은 함수를 통해서 받은 리턴 값의 함수가 A와 B 2개로 각각 생성되어 이제 fiveAdder(3)을 하게 되면 8의 결과 값이, threeAdder(3)을 하게 되면 6의 결과 값이 나오게 된다. 이렇게 closure를 통해서 각 함수들은 자기만의 고유의 값을 가지고 scope chain을 유지하면서 그 chain 안에 있는 모든 변수의 값을 유지하게 된다.



* Scope chain의 생성

: 단순히 보면 왜 그때그때 scope chain이 생성될까 이해하기 힘들지도 모르지만 속에 돌아가는 구조를 자세하게 살펴보면 이해를 할 수 있을 것이다. Closure에 대해서 더 깊어지기 전에 위의 현상에 대해서 이해하고 넘어가자. 위의 예에서 '익명 함수'를 이용하고 있다. 익명 함수는 함수의 이름을 지정 안하고 사용하는 경우를 뜻하고 위의 예에서는 다음의 부분이다.


    return function (adder) {   // #2
        return inClosure + adder;
    };


: 이 부분에서 #2는 익명 함수가 선언되어 리턴되는 부분으로 내부에서는 이것은 새로운 Function 객체를 만들어 리턴을 하게 되는 과정과 같다. 다르게 표현하면 내부적으로는 아래와 '비슷한' 프로세스가 일어나게 된다.


return new Function("adder", "return inClosure + adder;");


: 자바스크립트에서 {}는 object literal, []는 array literal이라고 하고 위의 function () {} 는 function literal이라고 하는 것은 내부적으로 각각 {}는 Object 객체, []는 Array 객체, function () {}는 Function 객체를 만들기 때문이다. 이렇게 sum 함수를 호출함으로써 내부에서 #2를 거치게 될 때마다 매번 새로운 함수를 생성하여 리턴하는 것이라고 보면 되고, 이럴 때마다 각 함수의 scope chain은 새롭게 할당되어 저장하게 된다. 따라서 위의 예에서 fiveAdder = sum(5)를 호출 할 때 new Function과 비슷한 과정을 통해 함수 A가 생성되어 리턴되고, threeAdder = sum(3)을 호출 할 때 또 new Function을 통해 함수 B가 생성 된 것이다. 이렇게 보면 매번 sum을 호출할 때마다 새로운 함수와 그 함수의 scope chain이 따로따로 생성된 것을 이해할 수 있을 것이다. 여기서 재밌는 것은 fiveAdder와 threeAdder의 외부 표현식은 같다는 것이다. toString() 함수를 통하여 호출해보면 둘다 아래와 같이 나오게 된다.



: 하지만 fiveAdder !== threeAdder이다. 이렇게 똑같은 모양의 함수들이 매번 새롭게 나오고 있는 것이다. 이렇게 두 함수는 일치한 모양을 가지고 있지만 둘의 동작이 달라지는 것은 바로 숨겨져 있는 closure 때문이다.


- 덧: 위에서 new Function과 '비슷한' 프로세스가 일어난다고 말한 것은 new Function을 이용해서 생성한 함수는 로컬 변수만 이용 가능하지만 function literal로 생성한 함수는 Closure를 생성하여 외부의 scope에 있는 변수들을 접근 가능하다는 점이다. 따라서 closure를 생성할 때에는 new Function을 이용하면 안되고 function () {} 으로 함수를 생성해야한다.

 

- 덧2: 위의 그림에서 보면 base와 inClosure의 값은 항상 같고 같은 scope에 자리하고 있다. 따라서 inClosure 변수는 사실상 필요없지만 closure 내부의 로컬 변수도 유지 된다는 것을 보여주고자 추가적으로 선언했다.

 


 

* Closure를 쓰는 실제 예

: 이전 글에서 closure의 이용 방법에 대하여 몇가지를 이야기하기도 했지만 '어디서' '언제' 사용할지에 대해서는 감을 잡기가 어려울 것이다. closure를 가장 많이 사용하는 것은 이전 글에서 말했던 경우들, 라이브러리에서 private이나 나의 변수를 보호하고 싶을때라던가 self-defining function인 경우, static으로 변수를 이용하고 싶은 경우에도 있지만 가장 일상적으로는 closure를 활용하는 경우는 콜백함수에 추가적인 값들을 넘겨주거나 처음에 초기화 시켰던 값을 계속 유지하고 싶을 때일 것이다. 사실 이렇게 글로 실컷 읽어봤자 위의 fiveAdder 등과 같이 실용적이지도 않은 곳에만 쓰이는 탁상공론에 불과한 개념이라고 느낄 수 있을 것이다. 따라서 실제 상황에서도 사용할 수 있는 간단한 예를 한번 보자.


- 목적: 특정 div에 버튼1에 대한 콜백으로 div를 추가/버튼 2에 대한 콜백으로 img를 계속 추가


<div id="wrapper">
    <button data-cb="1">Add div</button>
    <button data-cb="2">Add img</button>
    <button data-cb="delete">Clear</button>
    아래에 추가<br/>
    <div id="appendDiv"></div>
</div>
<script>
(function () {
    var appendDiv = document.getElementById("appendDiv");   // #1
    document.getElementById("wrapper").addEventListener("click", append);

    function append(e) {
        var target = e.target || e.srcElement || event.srcElement;
        var callbackFunction = callback[target.getAttribute("data-cb")];
        appendDiv.appendChild(callbackFunction());
    };
    var callback = {
        "1":(function () {
            var div = document.createElement("div");    // #2
            div.innerHTML = "1번";
            return function () {
                return div.cloneNode(true);    // #3
            }
        }()),
        "2":(function () {
            var img = document.createElement("img");
            img.src = "http://www.google.co.kr/images/srpr/logo3w.png";
            return function () {
                return img.cloneNode(true);
            }
        }()),
        "delete":function () {
            appendDiv.innerHTML = "";
            return document.createTextNode("Cleared");
        }
    };
}());
</script>



아래에 추가



: 여기서 Closure를 활용한 곳을 보면 크게 2가지로 볼 수 있다. 바로 #1 부분에서 전체 함수들이 공통적으로 접근하고자하는 변수(appendDiv)를 선언하여 한번의 초기화 만으로 이후에 함수들이(여기서는 append(e) 함수) 지속적으로 접근 가능하도록 한 부분과 #2에서 현재 화면에 안 보이는 가상의 노드를 만들어 보관하고 있는 #2 부분이다. 나중에 콜백 함수에서는 append 함수를 호출하여 클릭한 버튼에 따라 변수 callback에 선언되어있는 다른 내부 함수를 호출하게 되고, 이벤트가 발생하게 되면 해당 콜백 함수가 호출되어 #3에서 #2의 가상 노드의 복제 노드를 생성하여 리턴하여 appendDiv에 추가하게 된다. 이렇게 콜백 함수를 동적으로 생성할 때 초기화 되어있는 값들을 유지하는 것이 퍼포먼스상 유리한 경우, 특히 DOM을 생성하거나 탐색하여 가져오는 경우 한번 로드했던 DOM 객체를 보관하고 있는 것이 여러 모로 유리하기 때문에 이렇게 DOM을 적극적으로 활용할 때야말로 Closure를 진정으로 효과적으로 사용할 수 있을 것이다.

 

: 그렇다고 위의 예제에서 closure는 필수적인 요소가 아니다. 이렇게 closure는 언제든 사용할수도 있고 안 할수도 있지만, 위에서 말했듯 중복된 DOM 탐색이나 DOM 생성을 할 때에 효과적으로 closure를 이용한다면 월등한 퍼포먼스를 가져올 수 있을 것이다. 이렇게 실용에서 closure를 가장 많이 활용할 수 있는 부분을 살펴보면, 다음과 같이 말할 수 있을 것이다.

  • 반복적으로 같은 작업을 할 때 같은 초기화 작업이 지속적으로 필요할 때, 콜백 함수에 동적인 데이터를 넘겨주고 싶을 때 Closure를 사용하자!


- 덧: 이 예제에서는 실제로 활용 가능한 다양한 예들이 같이 포함되어 있다. 

    • closure로 appendDiv를 한 번만 검색하고 조회하여 초기화하고 계속 보관하는 활용 방법
    • div, img 등 가상 노드를 만들어놓고 필요할 때마다 복제하여 생성할 수 있는 활용 방법
    • appendDiv에만 이벤트 핸들러를 추가하여 관리할 수 있는 event delegation 활용 방법
    • 이벤트가 발생한 target element를 크로스 브라우져에서 가져올 수 있는 방법
    • var callback = {...}를 활용하여 대상에 따라 동적으로 콜백 함수를 변화 시키는 활용 방법
    • HTML5의 스펙에 맞게 사용자 정의 속성을 "data-*" 여기서는 "data-cb"로 설정한 것
    • 만약 callback 함수에 인자를 넣어주게 되면 div를 추가하되, 안의 내용 또한 동적으로 설정할 수 있는 위의 예 응용 방법 등

: 나중에 어느 정도 강좌를 진행하고 나면 이 예제를 다시 가져와서 더 자세하게 세부적으로 들어가서 정말로 실용에서 사용할 자바스크립트 개발 방법론에 대하여 공부해보도록 하자. 이 간단한 예제는 자바스크립트 개발에서 사용할 수 있는 기본적인 틀을 하나 제시하고 있고, 지금이라도 천천히 하나씩 뜯어보면 이해할 수 있는 자바스크립트만의 독특한 개발 방법들이다. 이 방법들을 제대로 이해하고 활용할 줄 안다면 자바스크립트를 더욱더 깊이 있게 다룰 수 있게 될 것이다.



*  정리

    • Closure는 function 안에 function이 있게 되면 기본적으로 생성된다.
    • Closure는 scope chain이 생성됐을 때의 변수 값들을 보존하고 기억하게 된다.
      • 함수가 메모리에서 없어질 때까지 따라다니게 된다.
    • 같은 모양의 함수이더라도 다른 closure를 가지고 있을 수 있다.
    • 함수가 다른 곳에서 사용되더라도 처음에 생성되었던 scope chain이 끝가지 따라다니게 된다.
      • 다른 곳에서 사용되는 대표적인 경우: 함수를 리턴하여 사용, 다른 함수의 인자로 넘겨줘서 사용, 콜백으로 사용
    • Closure는 아주 쉽다!


[속깊은 자바스크립트 강좌] Closure 쉽게 이해하기/실용 예제 소스 끝.

 

- 다음 편

2013/02/13 - [속깊은 자바스크립트 강좌] 쉬어가기: 웹 개발 방법론의 변화/자바스크립트의 재발견

2013/02/22 - [속깊은 자바스크립트 강좌] 객체지향의 기본: prototype

2013/10/04 - [속깊은 가바스크립트 강좌] 상속, new와 Object.create의 차이

2013/10/29 - [속깊은 자바스크립트 강좌] 글로벌(전역) 변수와 window 객체

2013/11/06 - [속깊은 자바스크립트 강좌] 변수 선언 방법에 대하여

2016/11/13 - [속깊은 자바스크립트 강좌] 마무리(는 책으로!)


 

저작자 표시 비영리 동일 조건 변경 허락
신고

이 글을 공유하세요.

  • 뎁퍼니 2013.01.31 12:30 신고  댓글주소  수정/삭제  댓글쓰기

    unikys님 안녕하세요
    이번글도 많은 도움이 되네요
    제가 실제예를 따라해보고 있는데 버튼을 클릭해도 아무런 반응이 없어서.. 흑흑
    일단 버튼에 id를 직접 주고 실행해보고 있답니다

    //document.getElementById("wrapper").addEventListener('click', append);

    document.getElementById("advdivbtn").addEventListener('click', append);
    document.getElementById("advimagebtn").addEventListener('click', append);
    document.getElementById("clearbtn").addEventListener('click', append);

    매번 좋은글 감사합니다 ^^

    • Unikys 2013.02.01 09:09 신고  댓글주소  수정/삭제

      네~ 그렇게도 가능합니다^^
      저는 IE8/크롬/파폭/사파리에서 테스트를 해봤는데 잘되는데 이상하군요. 다른 element 가져오고 addEventListener를 사용하신 것을 보니 구버전 IE는 아니고 wrapper가 다른 버튼들의 부모 element로 잘 감싸져있는지, html 과 자바스크립트의 순서도 중요하니까 스크립트를 아래에다가 해보시는 것도 좋을 것 같습니다.

      암튼 위의 예제에서 wrapper 하나에 리스너를 추가한것에 대해 짧게 이야기하자면~ event delegation 이라는 디자인 패턴의 가장 기초적인 모습을 보여주고 있는 형태입니다. 자바스크립트 최적화 기법으로도 많이 이용하고 있고요, 위의 예제랑 댓글에 적어주신 버튼마다 이벤트를 추가하는 것을 비교해보면 소스의 양/DOM 탐색 횟수/그리고 이벤트 리스너의 할당 횟수에서 차이가 나는 것을 바로 확인할 수 있습니다. 이런 간단한 예에서는 그다지 효과가 커보이지 않는데, 링크나 버튼이 50여개에 달하고 그것들이 한 페이지에서 동적으로 보였다 없어졌다 할 때에는 그것들에 불필요하게 이벤트 리스너를 할당해주기 보다는 그것들의 부모 element (여기서는 id="wrapper"인 div 태그죠)에다가 리스너를 추가한 다음에 어디에서 이벤트가 일어났는데 e.target을 통해서 알아내는 패턴이지요. 언젠가는 이것에 대해 쓰긴 할건데, 이벤트 bubble을 이용한 이해하기 쉬운 디자인 패턴이니 한번 검색해보시고 공부하는 것도 많은 도움이 될 겁니다^^

  • 뎁퍼니 2013.02.01 09:38 신고  댓글주소  수정/삭제  댓글쓰기

    unikys님 죄송합니다
    제가 실수를....
    id가 wrapper 인 div가 소스에 또 있었네요...

    • Unikys 2013.02.01 10:53 신고  댓글주소  수정/삭제

      실수야 할수도 있죠~ 보통 실수를 하면 이해가 더 잘 되게 되죠. 그러니 event delegation 패턴에 대해서는 딱~ 이해가 잘 되실거라 생각합니다^^ㅎㅎ 그냥 쉽게 부모에서 event를 처리한다고 생각하시면 됩니다 ㅎㅎ

  • 김진달 2013.02.02 18:32 신고  댓글주소  수정/삭제  댓글쓰기

    Closure 개념 이해를 위해 여러 사이트를 찾아가며 읽고 있었습니다.
    영문이든 국문이든 쓰여진 글만으로는 이해가 되지 않아 포기하고 있었죠.
    즉, Closure 개념을 이해하기 전에 글쓴이들의 문장 해석을 먼저해야 하는 고충. ^^;
    그런데, unikys님의 설명은 정말 저에게 맞춤이듯 이해에 많은 도움이 되었습니다.
    특히, 예제가 현 제 수준과 너무 잘 맞는 것 같아서 그런가 봅니다.
    그래서 "속깊은 자바스크립트 강좌"가 더욱 기대됩니다.
    정말 감사드립니다. ^^

    • Unikys 2013.02.04 12:44 신고  댓글주소  수정/삭제

      잘 이해되셔서 다행이네요. 최대한 누구나 이해할 수 있도록 쉬운 예제와 쉽게 설명하고 실제 활용 가능한 예제를 만들어봤는데 closure에 대해서 한번 더 쓴게 보람이 있네요^^ 감사합니다~ 자주 방문해주시고 모르는거나 제가 틀리게 설명한게 있으면 언제든 알려주세요!

  • 이덕우 2013.03.22 20:08 신고  댓글주소  수정/삭제  댓글쓰기

    안녕하세요.
    Closure에 대한 설명이 다른 어디 보다 자세하고 이해하기 쉽게 되어있어서 많은 도움이 되었습니다. 감사합니다.
    closure의 사용법이나 어떤것이 closure인줄은 이제 좀 알겠습니다.
    그러나 closure를 명확하게 정의한 부분이 없는데요. 대부분 '이 예제가 closure다' 정도로 설명을 하고 있었습니다. 다른 어느 사이트나 책에도 closure를 이론적으로 정의한 곳은 있지만 명확하게 설명을 해준곳이 없어서 염치 불문하고 질문을 올립니다.

    closure를 한마디로 정의하면 무엇입니까?

    이것을 물어보는 이유는 scope 과 closure를 정확하게 구분하지 못하고 있어서 입니다.
    (closure는 javascript의 scope으로 인하여 생기는 결과물?)

    scope 과 closure의 차이(구분)는 무엇입니까?
    (더러 혼용해서 사용하는 곳도 있고 둘 간의 관계를 명확히 한 곳이 많이 없습니다.)

    현재 이해하기로는 scope chain 하나의 묶음이 closure라고 이해하고 있는데 이것이 맞는 개념인지요?

    쉽게 정리를 해주셨는데 제가 이해를 잘 못하여 죄송합니다.

    • Unikys 2013.04.01 21:54 신고  댓글주소  수정/삭제

      안녕하세요! 요즘 너무 바빠서 오랜만에 들어왔는데 재미난 질문을 해주셨네요^^ scope와 closure의 차이라면 쉽게 말씀드리자면 밀가루와 칼국수의 차이랄까요?

      일단 기본적으로 의미하는 범위가 다릅니다. 말씀하신대로 scope의 유산물로 closure가 나왔다는 것은 맞는 말이고요, 자바스크립트의 scope는 function을 따라가기 때문에 그러한 scope를 통해서 발생하게 되는, function이 다른 곳으로 인자나 콜백 등으로 보내졌을 때 해당 scope를 외부에서 접근하지 못하고 function 내부에서만 접근할 수 있기 때문에 closure라는 이름이 붙여진 것이고요, 이것은 function 기반의 scope로 인해서 발생하게 된 결과물 입니다.

      조금 더 쉽게 딱 설명드리자면 scope라 하면 자바나 C에서도 동일한 의미로 현재 위치에서 접근할 수 있는 변수의 집합을 설명하는 것이죠. 하지만 closure는 여러 가지 scope를 결정하는 방법 중에서 자바스크립트에서 사용하는 scope의 특성 때문에 접근할 수 있는 변수의 집합이 function이 선언된 위치의 상위에서 가져오는 것, 이 scope 자체를 closure라고 하는 것입니다. 그리고 closure라는 이름 자체는 외부에서 접근이 안된다는 나름 private스러운 특성을 대면해주고 있는 이름입니다.

  • 니똥원샷 2013.09.01 22:04 신고  댓글주소  수정/삭제  댓글쓰기

    혹시 책도 내시나요?ㅎ

  • 별똥별2 2014.06.27 14:16 신고  댓글주소  수정/삭제  댓글쓰기

    책내셔도되겠어요.

  • 이윤구 2016.08.09 18:41 신고  댓글주소  수정/삭제  댓글쓰기

    #3 부분에서 이해가 부족해서 계쏙 보게 되네요 ㅠ
    그래도 참 예제가 정말 좋습니다. ^^

  • 이윤구 2016.08.30 20:43 신고  댓글주소  수정/삭제  댓글쓰기

    http://m.book.naver.com/bookdb/book_detail.nhn?biblio.bid=11005485. 책 출간하셨나요? ㅎ

    • Unikys 2016.09.23 05:03 신고  댓글주소  수정/삭제

      제가 쓴책은 아닙니다만, 제가 출판하려는 출판사에서 "속 깊은" 제목을 쓰고 싶다고 하여 시리즈처럼 나오게 되었네요. "속 깊은 자바스크립트"는 이제 편집 중이니 조금 있으면 나오리라 생각합니다.

  • Engineer135 2016.12.22 14:50 신고  댓글주소  수정/삭제  댓글쓰기

    여기까지 보니까 클로져가 그나마 좀 이해가 가네요.

    그런데 예제에서 delete 부분에서 appendChild 오류가 나는데...

    appendDiv.appendChild(callbackFunction()); 를
    callbackFunction() === undefined ? callbackFunction() : appendDiv.appendChild(callbackFunction());
    이런식으로 수정해줘야하지 않을까요. 예제에서 그렇게 중요한 부분은 아니지만 ^^;;;;

    아무튼 감사합니다. 설명이 너무 좋아요 ㅠㅠ

    • Unikys 2016.12.23 04:01 신고  댓글주소  수정/삭제

      네, 확인 감사드립니다. 제가 책에서는 이 부분의 delete 함수쪽에서 "Cleared"로 노드가 리턴되도록 수정해놔서, 책과의 일관성을 위해서 그렇게 수정하도록 하겠습니다. 감사합니다.

  • 적외선 2017.01.04 16:46 신고  댓글주소  수정/삭제  댓글쓰기

    Closure에 대한 자료를 여기저기 찾아 보던중에 우연하게 "속깊은 자바스크립트 강좌"를 보게되었습니다.
    타 강의나 자료는 Closure의 단순한 정의와 샘플 코드 또는 애매모호한 설명이 주를 이루었는데요.
    Closure의 원리와 이해, 목적, 활용까지 일목요연하게 설명해주셨네요.
    감사하고 책도 구입하도록 하겠습니다.

질문이나 의견을 댓글로 달아 주세요

티스토리 툴바