관련글 : 자바스크립트(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

댓글을 달아 주세요
















 

2010/08/31 - [Review/IT] - jquery 플러그인 만들기 (1)
jquery 플러그인 만들기 (1) 편에 이은 연재글입니다.

이전에 만들었던 플러그인에는 작은 단점이 있다. 바로 범용성이 떨어진다는 것인데, 플러그인은 어떤 환경에서 쓰일지 모르기 때문에 보편적으로 만들어야 한다.

간혹 jquery와 prototype.js 등의 프레임워크를 동시에 사용하는 환경이 있는데, 이런 경우 jquery의 $ 를 다른 표현으로 사용하기도 한다. 하지만 우리가 만들어놓은 플러그인은 $ 를 사용하기 때문에 충돌이 날 수 있다.

해결책으로 자신이 만든 플러그인 메소드를 래핑하는 방법이 있다.

우선 형식은 다음과 같다. (function() { statement })() 
자신이 만든 메소드를 유효범위로 감싸면서 내부의 변수와 함수들을 private 하게 만드는 것이다.

(function() { statement })()  빨간색으로 되어 있는 부분을 하나의 함수명 이라고 생각하면 좀 더 쉽다.
function() 이 될텐데, 이는 마찬가지로 인자를 넘길 수 있다는 뜻이 된다.
(function() { statement }) == function 

우리는 일전에 아래와 같은 플러그인을 만들었다.
$.fn.Alert = function() {
	return alert(this[0].id);
}
이걸 유효범위로 만들기 위해 아래와 같이 수정한다.
(function($) {
    $.fn.Alert = function() {
	return alert(this[0].id);
    }
})(jQuery);
이렇게 되면 $ (여기서는 jQuery) 변수를 익명함수의 인자값으로 넘기고, 익명함수는 jQuery 를 $로 받아서 플러그인에서는 계속 $를 사용할 수 있다.


신고
Posted by onionmen

댓글을 달아 주세요
















 
jQuery 에 대한 기본적인 문법적 이해가 있다는 가정하에 문서를 작성합니다.

약 1년간 jQuery를 사용하면서 jQuery가 제공하는 자바스크립트 사용의 편의성에도 매우 감탄했지만, 정말 매력적이었던 부분은 플러그인에 대한 지원이었다.

한동안 남들이 만들어놓은 플러그인 들을 고맙게 가져다 썼지만, 어느 시점에서 부터 요구사항에 맞는 플러그인을 찾기가 쉽지 않았다. (이는 우리 사이트에서 jQuery를 필요로 하는 부분이 그만큼 많아졌다는 것에 대한 반증이기도 하다.) 

요구사항에 맞춰서 UI를 만들다 보니 기존에 사용하던 플러그인을 대충 수정하면서 사용했지만, 점점 더 높아지는 요구사항에 아예 플러그인을 새로 만드는게 더 나아보였다.

겸사겸사 간단하게 플러그인을 만드는 방법을 작성해볼까 한다.

기본적으로 jQuery를 사용함에 있어서 사용하는 플러그인의 타입은 크게 아래 두 종류 이다.
  1. $('div').plugin_name();
  2. $.plugin_name();
1번은 셀렉터를 이용하여 메소드체인을 생성할 수 있고, 2번은 그냥 function 이다.


1. $('div').plugin_name(); 를 만들어보자.
jquery.test-plugin.js
$.fn.Alert = function() {
	return alert(this[0].id);
}





div tag를 셀렉터로 하여 정보를 출력하는 간단한 플러그인이다.
위와 같이 작성하면 간단하게 끝난다.

위 메소드에서 두가지를 살펴볼 수 있는데, 하나는 this 이고, 나머지 하나는 그 this를 리턴하는 것이다.
this는 예상하는대로 div 엘리먼트에 대한 참조이고, this를 리턴하는 이유는 메소드체인을 사용하기 위함이다.


this 에 대한 프로퍼티를 확인해보면, 할당된 Method 들이 있고, 이 div 엘리먼트에 대한 프로퍼티를 담고있는 배열( [0] )이 있다. 
div 엘리먼트가 하나라고 가정할 수 없으니, 배열로 엘리먼트를 구분하는 것이다. (현재는 html 상의 div가 한개 뿐이므로, 배열도 한개만 나온다. div 엘리먼트가 여러개라면 배열 또한 그에 상응하게 나타난다.)

jquery의 강점중 하나는 메소드 체인을 사용할 수 있다는 것인데, 예를 들어서 $("div").Alert().fadeOut(); 과 같은 코드를 사용할 수 있다는 것이다.

메소드 체인이 끊어지지 않게 하기 위해서는 jquery 객체 (여기서는 this) 가 리턴되어 유지되는 것이 중요하다.

$.fn.Alert = function() {
	return this.each(function(i,k) {
		alert(k.id);
	});
}
그리고 div 와 같은 엘리먼트들은 배열(오브젝트) 이기 때문에 each 와 같은 순환문을 통하여 "사용하고 리턴될 수" 있어야 한다.


2. $.plugin_name(); 를 만들어보자.
jquery.test-plugin2.js
$.Alert = function() {
	alert("plugin-test");
}

1번과 비교해서 fn 부분이 제거되고, return 되는 부분도 없다. 그냥 일반적인 함수 작성하듯 만들면 된다.(함수니까!) 하나의 기능만을 담당하는 것이라면 문제는 없다.

이는 아래와 같이 사용된다.



신고
Posted by onionmen

댓글을 달아 주세요

이전버튼 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

최근에 올라온 글

Yesterday173
Today88
Total1,625,433

티스토리 툴바