관련글 : 자바스크립트(1-1) - 클로저(closure) 에 대한 이해

 
더 많은 예제코드가 필요하다면 아래 링크를 참조하자
(링크 : http://www.javascriptkit.com/javatutors/closures2.shtml)


클로저에 대한 설명은 어렵다. 어렵기 때문에 명확하게 이건 이거다 라고 이야기 하기 힘들다. 이야기 한다 해도 이해하기 위해서는 수많은 배경지식이 필요하다. 아무리 설명을 해봐야 사람들이 이미 알고 있던 부분들이 모두 다르기 때문에 설득을 해야 하는 수준이다. 인터넷에서 클로저에 대한 글들을 찾아봐도 모두 마찬가지이다.

모두가 이건 이거다 라고 설명을 하고 있지만 이해는 쉽지 않다. 자바스크립트에 이 클로저라는 녀석은 C언어에서 포인터를 배울때 만큼이나 날 혼란스럽게 한다. 이건가 싶으면 저거고, 저건가 싶으면 또 이것인 클로저를 잊지 않기 위해서라도 잠시 정리를 해둔다.

짧으면서도 설명하기 쉬운 아래 코드조각을 보자.

2011:04:16 18:50:58

sayAlice() 를 실행하고, 리턴받은 함수를 또 바로 실행하고 있다. Step by Step 으로 확인해보자.

2011:04:16 19:13:122011:04:16 19:13:312011:04:16 19:13:45
 
2011:04:16 19:14:302011:04:16 19:14:512011:04:16 19:15:36
 

아래 단계를 따라가면서 조사식의 saylAlert 과 alice가 어떻게 변하는지 살펴보자. 

1. sayAlice() 실행
2. sayAlert 변수에 함수 할당 [function () { alert(alice); } ]
3. alice 변수에 문자열 할당 [Hello Alice]
4. sayAlert 함수 실행
5. alert(alice) 구문 실행
6. Hello Alice 출력


4번 단계가 실행 될 때, 내부의 alice 변수를 참조한다.
sayAlert 변수에 할당된 익명 함수가 선언된 다음에서야 alice 변수에 문자열이 할당 되었다. 이건 함수 내부에 선언된 함수 내부에서 부모함수(?)의 변수에 접근(참조) 할 수 있다는 것을 의미한다. 그리고 이 부분이 클로저가 만들어졌다고 볼 수 있다. 그리고 함수가 끝나서 지역변수들은 사라져야 함에도 불구하고 alice 지역변수는 계속하여 살아있는다. 클로저 때문이다.

2011:04:17 13:10:41

좀 더 긴 예제인데, 간략하게 줄였다. 브라우저에서 실행하여 Step by Step 으로 보자.

2011:04:17 13:14:562011:04:17 13:15:292011:04:17 13:15:49

2011:04:17 13:16:062011:04:17 13:16:282011:04:17 13:16:43

2011:04:17 13:17:002011:04:17 13:17:142011:04:17 13:17:30


1. newClosure(40); 을 호출함
2. num 지역변수에 40을 할당
3. newClosure() 종료로 함수의 생명주기는 끝나고, 리턴된 익명함수를 closure1 변수에 저장
4. 리턴받은 closure1(5) 함수를 실행
5. 익명함수이 진입 전 이므로 num 값 확인 불가
6. 익명함수에 진입하여 num 값이 생성되어 있음을 확인
7.8.9. 인자값 5를 더함으로 해서 num 값이 45가 됨을 확인


여기서 6번이 중요포인트인데, 익명함수에 진입 할 때, num의 값이 40으로 확인 할 수 있다는 것이다. 기본적으로 num은 newClosure의 지역변수 이기 때문에 함수의 생명주기가 끝남과 동시에 소멸되어야 하는 변수이다. 하지만 클로저가 생성됨으로 인해서 이 변수는 그대로 살아있게 된다. 불필요한 메모리 릭을 방지하기 위하여, 이 변수를 사용한 뒤에 더이상 필요 없다는 판단이 들면 alert('num: ' + num); 문장 뒤에 num = null; 을 추가 시켜주자. 

이런 부분들은 굳이 몰라도 충분히 프론트 개발이 가능하다. 그리고 이해하지 못해도 그냥 쓰면 된다. 하지만 우리가 클로저를 잘 이해해야 하는 이유는 이 클로저가 생성될 때, 메모리 릭이라는 무시무시한 사이드이펙트를 데리고 오기 때문이다.

IE7 이하의 브라우저가 아직도 세상에 존재 하는한, 우리는 메모리릭을 신경쓰지 않을 수 없다. 이유를 알 수 없는 상태에서 브라우저가 자주 죽는다면 메모리릭을 의심해 봐야 한다. 

위의 예제에서 굳이 이야기를 해보자면, 변수 alice를 전부 사용한 뒤에 alice = null 로 초기화를 시켜주도록 하자. 그리고 jquery 를 사용중이라면 오브젝트에 접근 할 때에는 $().data() 메소드를 사용하자.

신고
Posted by onionmen

댓글을 달아 주세요


클로저는 실무에서 자바스크립트로 개발을 하다보면 자신도 모르게 사용했던 개념이다. 클로저는 몰라도 예제코드를 보면 "아하, 그게 클로저야?" 라고 되묻는 사람들이 꽤 많을 것이다.

아래 코드를 보자.

var closureTest = function() {
	var closureVar = "closure test";

	return function() {
		alert(closureVar);
	}
}

closureTest 라는 함수는 closure test 라는 문자열을 출력하는 익명함수를 리턴한다. 그리고 위 코드를 수행하면 정상적으로 closure test 메시지가 alert창으로 뜬다.

위 코드가 왜 이상한지 모르겠는 사람은 클로저에 대한 이해가 충분하거나, 아니면 자바스크립트에 대한 이해가 불충분한 사람일 것이다.

기본적으로 closureVar 변수는 closureTest 에 속한 지역변수 이기 때문에 다른 외부함수에서 호출하는 것이 불가능하다. 변수를 호출하기 위한 방법으로는 지역변수로 선언된 closureVar 변수를 전역변수로 바꿔 선언하는 방법이 있다. 

그런데 자바스크립트에서는 굳이 이렇게 하지 않아도, 함수에 속한 지역변수를 다른 함수가 호출하게 하는 것이 가능하다. 이게 바로 클로저다. 좀 더 정확하게 이야기 하면, 클로저란 자신이 생성된 함수의 context에 직접 접근(참조) 할 수 있는 것이다.

위 코드를 좀 더 쉽게 풀어보면 아래와 같다.

var closureTest = function() {
	var closureVar = "closure test";

	return closureTest2();
}

var closureTest2 = function() {
	alert(closureVar);
}

하지만 위 코드는 제대로 동작을 하지 않는다. closureVar 변수가 closureTest 함수에 선언되었기 때문에, closureTest2 함수에서 접근할 수 없기 때문이다. 

위 코드를 동작시키기 위해선 closureVar 변수를 전역변수로 새로 선언해야 한다.

var closureVar = "";
var closureTest = function() {
	closureVar = "closure test";

	return closureTest2();
}

var closureTest2 = function() {
	alert(closureVar);
}
하지만 변수가 많아진다면 이 모든 변수를 전역변수로 할당해야 하는데, 코드도 어려워지고(지저분해지고) 개발자도 힘이 든다. 변수를 모두 전역변수로 선언하지 말고, 클로저를 잘 이해하여 써먹어보자.


신고
Posted by onionmen

댓글을 달아 주세요

  1. Favicon of http://coolmoo.net BlogIcon 나비오 2010.07.21 23:24 신고  댓글주소  수정/삭제  댓글쓰기

    이해하고 싶지만 당췌 봐도 모르겠다는...
    제가 정말로 무식하죠ㅜㅜ
    저도 오늘 자바 책 하나 사긴 했는데 걱정이 앞서네요

  2. Favicon of http://pam.ncity.net/wp BlogIcon pam 2010.10.24 12:42 신고  댓글주소  수정/삭제  댓글쓰기

    큰 깨닫음 얻고 갑니다. 크..

  3. 지나가던이 2010.12.02 11:21 신고  댓글주소  수정/삭제  댓글쓰기

    "함수에 속한 지역변수를 다른 함수가 호출하게 하는 것이 가능하다. 이게 바로 클로저다."
    라는 설명은 그냥 내부함수에서 외부함수의 변수를 접근할수 있다. 즉 scope, 유효범위에 대한것 같네요 ^^;
    "클로져는 자신의 외부에 선언된 변수를 참조가 아닌, 복사본으로 가지는 함수"라고 봄이 맞지않나 싶네요
    http://asrada2001.tistory.com/201 여기를 참고하시면 더 이해가 빠를듯합니다

  4. 느네 2011.04.24 10:32 신고  댓글주소  수정/삭제  댓글쓰기

    좋은정보 얻고 갑니다~
    출처 밝히고 내용좀 퍼갈께요 ㅎㅎ

이전버튼 1 이전버튼

블로그 이미지
손을 따뜻하게 만들어 주고 싶은 애인이 있습니다.
onionmen

달력

 « |  » 2017.12
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31            
DNS Powered by DNSEver.com

최근에 올라온 글

Yesterday140
Today105
Total1,625,740

티스토리 툴바