closure - 해당되는 글 1건
앞장의 글을 쓰고보니 시간이 남는군요... 언제 포스트가 될지 모르겠지만.. 시간날때 미리미리 써둡니다..ㅎㅎ
앞장에서 미리 예고해드렸듯이 이번 강좌는 굉장히 중요한 부분이라고 할 수 있습니다. 과거 Javascript를
그냥 폼의 형식이나 체크하고, 값을 체크할때나 써먹던 상황에서는 몸소 느끼지 못했지만 Ajax붐이 불면서
클라이언트의 개발또한 서버쪽 개발 못지않게 복잡도를 자랑하게 되었습니다. PrototypeJS니 DoJo니,
Yahoo UI ToolKit 등 많은 Javascript 라이브러리들이 등장하고 발전하고 있습니다.
이런것들의 등장으로 과거 소외받던 Javascript가 이제서야 비로소 프로그램의 언어로서
인정받기 시작했다고 해야할까?
그런 느낌입니다. --; 또 이상한 이야기를 하고 있었네요. 각설하고 본론으로 들어가겠습니다.

앞절에서 이미 언급한 부분입니다. Scope에 관한거죠. 못읽어 보신분이라면 언능가서 먼저 읽으시길 바랍니다. 이 강좌를 하면서 Scope의 개념이 없이는 절대 안되는 부분이거든요. 물론 깊게 설명하지는 않았습니다만,
이번 강좌를 이해하는데 많은 도움이 되리라 생각합니다.

//중첩함수
function A(){
var a = "1";
  function B(){
    var b = "2";
  }
}


이러한 함수가 정의되어 있다고 가정합시다. 함수 A는 a라는 지역변수를 가지고 있고 함수 B는 함수 A안에서
존재하고 b라는 지역변수도 가지고 있습니다.
깜짝 질문, 함수 B에서 a라는 변수를 참조할 수 있을까요? 없을까요? 앞장에서 했던 강좌를 유심히 보신분
이라면 쉽게 알 수 있을 겁니다. 답은 "참조할 수 있다" 입니다. 답은 앞장의 강좌를 다시 읽어서 확인하시기 바랍니다.

참고로 위의 구문은 "중첩함수"라고 부르며 Javascript에서의 private을 만들때 사용하는 방법중에 하나입니다. 실제로 해보시면 아시겠지만, 함수 B는 함수 A안에서밖에 호출할 수 없으며 밖에서 함수 A를 가지고 함수 B를 참조하려 해도 안되는걸 아실 수 있습니다. A.B() <- 이런식으로 절대 호출 할 수 없습니다.

그럼 다음 함수를 보시죠.

<html>
<script>
 function OutFunc(){
   var out = "i'm a out"
   function InFunc(){
     var inner = "i'm a in "+"-----"+ out;
     return inner;
   }
   return InFunc;
 }

 var test_1 = OutFunc();
 var test_2 = test_1();
 alert(test_2);
</script>
<body></body>
</html>

이 스크립트의 결과가 어찌 될거라고 예상이 됩니까? 사실 이 함수 자체를 이해 못하시는 분도 있으리라
생각합니다. 절대 무시하는게 아닙니다. 다만 우리는 알게모르게 쉬운 스크립트만을 접하고 이렇게 구조적으로 파헤친적이 없기때문에 어려울 수 밖에 없었던겁니다. 처음부터 Java 나 C#처럼 배웠다면 이렇게 Javascript가 우리를 힘들게 하지 않았을거라고 전 생각합니다. 일단 실행부터 시켜보세요. 어떻습니까? 여러분이 예상했던 답하고 일치합니까? 일치하다면 자신있게 설명을 하실 수 있습니까? 없다면 아래를 봐주세요 ^^ㅋ

먼저 정리부터 해보죠.
1. Javascript에서의 단위는 함수이다.
2. 함수의 지역변수는 함수밖에서는 절대 호출 할 수 없고, 함수내부에서는 전역변수보다 지역변수가 우선한다.
3. 변수는 각각의 Scope를 가지며 자신의 Scope를 벗어날 수 없다.


이제 소스를 해석해보겠습니다. 다들 청심환 하나씩 드세요. ^^
OutFunc는 자신의 지역변수 out을 가지고 있고 중첩함수인 InFunc를 가지고 있습니다. InFunc는 자신의
지역변수인 inner를 가지고 있고 중첩된 함수(nested function이라고 표현합니다) InFunc는 지역변수 inner를 리턴하는군요. OutFunc는 중첩함수인 InFunc를 리턴하구요. 여기까지 이해하셨죠?

그리고 OutFunc를 실행하고 test_1에 담습니다..여기엔 뭐가 담길까요? 그렇습니다. 함수 InFunc가 담깁니다. 그리고 test_2에는 test_1에 담긴 함수를 실행하고 그결과를 담습니다.

그럼 답을 발표하겠습니다. 답은 "i'm a in -------- i'm a out" 입니다.

제가 묻겠습니다. 변수 inner는 어디에 속해이어야 하는 거죠? 네. 함수 InFunc에 속해서 그 Scope안에서만
존재 해야하며 그함수가 종료되었을때, 같이 사라져야할 변수입니다. 그런데 지금의 모습은 어떻습니까?
alert()을 통해서 inner의 값을 찍고 있습니다. 도대체 어떻게 된 것일까요? 위에 정리한 1,2,3은 도대체
어쩌라고 이렇게 결과가 나오는 겁니까?

눈치가 빠르신분은 이미 알고 계셨을 겁니다. 그렇습니다. 이것이 바로 "클로져(Closure)" 입니다.
클로져의 정의는 "다른 함수내에서 내부객체로 생성된 함수 리터럴을 반환하여 호출 프로그램에서 이를 변수로 배정한 것" 이라고 정의하고 있으며 부연설명으로는 "함수가 동작하는데 필요한 데이터 영역 확장"이라고 하고 있습니다.[o'relly - Javascript for web 2.0 5장]

제가 더 덧붙여 설명하면 첫번째  OutFunc()를 실행함으로써 InFunc()함수를 OutFunc()의 안에서 바깥쪽으로
끄집어내어 영역을 변경(확장)하고 두번째 test_1()을 다시 한번 실행함으로써 inner의 값을 직접 호출 할 수 있도록 호출 프로그램으로 영역을 변경(확장)한 것입니다. 이로써 inner라는 변수는 더이상 OutFunc의
InFunc안에 갇혀있지 않고 어디서든지 호출 될 수 있는 전역변수화가 되어버린 것이죠.
여기까지 이해하셨다면 당신은 이미 중급의 문턱까지 온것입니다.
사실 클로져란것을 정확하게 알고 있는 사람은 드물뿐 아니라 "의도하지 않은 클로져의 생성"으로 고통받고
있는 개발자들도 많습니다. 그만큼 어렵고 이해하기 힘든 개념인 것입니다.

결과적으로만 보면 상당히 훌륭해보이고 멋져 보이지만, 사실 내면엔 "메모리 누수"라는 문제점을 안고
있습니다. 메모리 누수에 대해서는 다음 강좌인 "함수-3"에서 자세히 다뤄보도록 합시다.
오늘은 이만 접어야 겠네요..ㅋ 퇴근시간이 가까워 져서리..ㅋㅋ
그럼 다음 강좌까지 다들 건강조심세요.. 더위가 심하네요..

posted by blankus
Javascript_base  |  2007/05/31 17:46