728x90

    귀찮아-[이모티콘]어밴드

    자바스크립트 클로저란(javascript Closure)?

    지난 포스트에서 함수선언과 함수표현식 그리고 익명함수에 대해 정리하였습니다.

    함수선언과 함수표현식 그리고 익명함수에 대해 

    잘모르시는 분들은 아래 링크를 클릭하세요

    바로가기


    클로저는 간단하게 생각하면 내부함수가 외부함수의 값을 변경 할 수 있는 것을 말합니다.

    이렇게만 정리하면 이해가 가지 않으므로 코드를 통해서 설명하겠습니다.

    일단 아래는 클로저를 이해할 수 있는 코드로 만들어진

    간단한 프로그램입니다.



    위에는 텍스트 박스와 버튼이 있습니다. 

    숫자를 넣으신 후 실행버튼을 클릭하세요.

    위의 프로그램은 html코드와 script를 

    밑에 공유하겠습니다.


    <input type="text" id="test" />

    <input type="button" id="start" value="실행" />

    위에는 html코드입니다.


    var text = document.getElementById("text");
    var start = document.getElementById("start");
    
    function outerFunc(obj){
      
      return function(_obj){
    //	alert(typeof(_obj));
      
        if(typeof(_obj) === "number"){
    	  //NaN도 typeof는 number이므로 따로 처리해야한다.
          return obj += _obj;
        }else{
          alert("숫자만 가능합니다.");
          return obj;
        }
      };
    }
    
    var innerFunc = outerFunc(1);
    
    start.onclick = function(){
    	//alert("클릭했습니다.")
      
      var num = Number(text.value);
      if(!isNaN(num)){
        text.value = innerFunc(num);
      }
    }
    

    위에는 스크립트 코드입니다.


    스크립트 코드 설명


    var text = document.getElementById("text");
    var start = document.getElementById("start");
    

    document.getElementById를 통해서

    input text와 input button을 객체로 받아와

    각각 text와 start에 참조했습니다.


    function outerFunc(obj){
      
      return function(_obj){
    //	alert(typeof(_obj));
      
        if(typeof(_obj) === "number"){
    	  //NaN도 typeof는 number이므로 따로 처리해야한다.
          return obj += _obj;
        }else{
          alert("숫자만 가능합니다.");
          return obj;
        }
      };
    }

    위의 코드는 함수선언을 통해 outerFunc를 정의했습니다.

    그리고 return을 익명함수를 리턴하였고 

    익명함수의 인자가 타입이 number라면

    내부함수의 지역변수 _obj와 

    외부함수의 obj에 +=연산자를 통하여

    obj에 대입하고 있습니다.


    var innerFunc = outerFunc(1);

    함수선언한 outerfunc의 return한 익명함수를

    innerFunc에 참조하였습니다.


    start.onclick = function(){
    	 
      var num = Number(text.value);
      if(!isNaN(num)){
        text.value = innerFunc(num);
      }
    }

    버튼 객체를 받아온 start에 onclick 리스너에

    익명함수를 넣은 후 

    input 태그의 value를 가져와 

    숫자타입이라면 

    innerFunc함수에 인자값으로 넘기고 있습니다.


    위의 코드를 통해 클로저에 대한 이해

    다시 위로 올라가면

    숫자 1을 입력하신 후 실행버튼을 클릭하시면 2가 출력되고

    다시 실행버튼을 클릭하면 4,

    다시 실행버튼을 클릭하면 8,

    다시 실행버튼을 클릭하면 16,

    그리고 실행버튼을 누르기 전 16의 값을 1로 바꾼 후

    실행버튼을 클릭하면 17이 출력되는 것을 알 수 있습니다.


    위의 예재로 보았을때 이상한 점을 발견 하실 수 있을 것 같습니다.

    도대체 4에서 클릭하면 8이

    8에서 실행버튼을 클릭하면 16이라는 값이

    어떻게 나오는 걸까요?

    버튼을 클릭하면 innerFunc이라는 함수를 실행합니다.

    innerFunc에는 타입이 number라면

    obj와 _obj를 더한 후 리턴합니다.

    그렇다면 innerFunc에 있는 익명함수는 

    obj라는 값을 어디에 저장하고 있을까요?

    클로저는 익명함수로 참조한 내부함수(innerFunc)가

    참조하지 않은 외부함수(outerFunc)를 Control할 수 있는 것을 말합니다.


    단순한 이론으로 지역변수는 메서드가 종료하면 값이 사라집니다.

    그런데 외부함수인 outerFunc의 지역변수 obj를 

    innerFunc에서 가져와 자신의 지역변수인 _obj와 값을 증가 한 후 

    리턴한다는 것은

    외부함수의 obj가 전역변수로 관리가 된다는 것을 알 수 있습니다.

    이렇게 이루어진 함수를 클로저라고 부릅니다.


    클로저를 통한 자바스크립트 캡슐화

    위의 설명을 통해 outerFunc의 지역변수는

    익명함수를 참조한 innerFunc가 변경 할 수 있다는 것을 알게되었습니다.

    그렇다면 자바스크립트는 따로

    자바처럼 접근제한자가 없는데 어떻게 은닉화를 할 수 있는 것일까요?

    위의 설명을 이해하신 분들은 캡슐화에 대한 내용도 쉽게 이해 할 수 있을 것입니다.

    outerFunc의 리턴은 익명함수를 리턴하고

    outerFunc의 obj는 처음 정의할 때만 

    값을 초기화할 수 있습니다.

    그렇다면 outerFunc의 지역변수인 obj는 처음 정의할때만 값을 초기화 할 수 있고

    innerFunc를 통해서만 obj를 변경 할 수 있습니다.

    그렇다면 자바에서 흔히 쓰이는 캡슐화와 동일하게

    전역변수는 private로 설정하고

    setter, getter메서드를 public으로 선언해 전연변수를 관리하는 것처럼

    innserFunc에 setter, getter와 같은 함수를 만든다면

    자바의 같이 전역변수 obj를 캡슐화 할 수 있습니다.


    마치며

    지금까지 자바스크립트 클로저와 클로저를 통한 캡슐화에 대한 설명이었습니다.

    감사합니다.


    '공감' 및 '좋아요'는 글쓴이에게 큰 힘이 됩니다!

    블로그 구독도 부탁드립니다.(네이버이웃 추가)





    Posted by 천상나타