power-girl0-0

[함수지향] 클로저 본문

언어/Javascript

[함수지향] 클로저

power-girl0-0 2021. 2. 5. 12:00
728x90

생활코딩 javascript를 참고하여 공부하였습니다.

스스로 공부한 것을 정리하고 복습하기 위한 목적으로 작성하였습니다.

( 출처 :  https://opentutorials.org/course/743)


 클로저 (closure) 

내부 함수가 외부 함수의 맥락에 접근할 수 있는 것을 말한다. 

클로저는 자바스크립트를 이용한 고난이도의 테크닉을 구사하는데 필수적인 개념으로 활용된다.


 내부함수와 외부함수 

예제를 통해서 알아보자.

 

자바스크립트는 함수 안에서 또 다른 함수를 선언할 수 있다.

위 소스코드와 같이 inner함수를 내부함수라고 할 수 있으며, 그 밖에 있는 outter함수를 외부함수라고 한다.

 

어떤 경우에 내부함수를 사용할까?

어떤 함수가 있는데, 그 함수 안에서만 사용해야하는 경우에 사용한다.

그래서 함수 밖에 선언하면 편집성이 떨어지기 때문에 내부함수를 사용한다.

 

내부함수는 외부함수의 지역변수에 접근이 가능하다.

예제를 통해서 알아보자.

위 소스코드에서 내부함수 inner에서 title을 호출했을 때, 외부함수인 outter의 지역변수에 접근이 가능하여서 결과값은 coding everybody가 출력된다.

 

이러한 것을 '클로저'라고 한다. 아래에서 좀 더 자세히 공부해보자.


 외부함수가 소멸된 이후에도, 내부함수는 외부함수의 변수에 접근이 가능하다.  

내부함수는 외부함수의 지역변수에 접근 할 수 있는데 외부함수의 실행이 끝나서 외부함수가 소멸된 이후에도 내부함수가 외부함수의 변수에 접근 할 수 있다.

위 예제의 결과는 coding everybody를 출력한다.

return을 하면서 outter 함수는 실행이 끝났기 때문에, 이 함수의 지역변수는 소멸되는 것이 자연스럽다.

하지만 함수 inner를 실행했을 때 coding everybody가 출력된 것은 외부함수의 지역변수 title이 소멸되지 않았다는 것을 의미한다.

 

즉, 클로저란 내부함수가 외부함수의 지역변수에 접근 할 수 있고, 외부함수는 외부함수의 지역변수를 사용하는 내부함수가 소멸될 때까지 소멸되지 않는 특성이 있다는 것을 알 수 있다.


 private variable 

소프트웨어가 커지는 과정에서 어떠한 정보가 있을 때, 그 정보를 아무나 수정하지 못하도록 방지하는 것이다.

 

예제를 통해서 알아보도록 하자.

 

아래 예제는 클로저를 이용해서 영화 제목을 저장하고 있는 객체를 정의하고 있다.

실행 결과는 Ghost in the shell , Matrix , 공각기동대 , Matrix 가 순서대로 출력된다.

function factory_movie(title){
    return {
        get_title : function (){
            return title;
        },
        set_title : function(_title){
            title = _title
        }
    }
}
ghost = factory_movie('Ghost in the shell');	
matrix = factory_movie('Matrix');				
 
alert(ghost.get_title());			//Ghost in the shell 출력
alert(matrix.get_title());			//Matrix 출력
 
ghost.set_title('공각기동대');
 
alert(ghost.get_title());			//공각기동대 출력
alert(matrix.get_title());			//Matrix 출력

위의 예제를 통해서 알 수 있는 것들을 정리해보면 아래와 같다.

1. 클로저는 객체의 메소드에서도 사용할 수 있다. 위의 예제는 함수의 리턴값으로 객체를 반환하고 있다.

이 객체는 메소드 get_title과 set_title을 가지고 있다. 이 메소드들은 외부함수인 factory_movie의 인자값으로 전달된 지역변수 title을 사용하고 있다.

 

2. 동일한 외부함수 안에서 만들어진 내부함수나 메소드는 외부함수의 지역변수를 공유한다.

ghost.set_title은 외부함수 factory_movie의 지역변수 title의 값을 '공각기동대'로 변경하였다.

변경후, ghost.get_title();의 값이 '공각기동대'인 것은 set_title와 get_title 함수가 title의 값을 공유하고 있다는 의미다.

 

3. 그런데 똑같은 외부함수 factory_movie를 공유하고 있는 ghost와 matrix의 get_title의 결과는 서로 각각 다르다.

그것은 외부함수가 실행될 때마다 새로운 지역변수를 포함하는 클로저가 생성되기 때문에 ghost와 matrix는 서로 완전히 독립된 객체가 된다.

 

4. factory_movie의 지역변수 title은 2행에서 정의된 객체의 메소드에서만 접근 할 수 있는 값이다.

title의 값을 읽고 수정 할 수 있는 것은 factory_movie 메소드를 통해서 만들어진 객체 뿐이라는 의미다.
즉, 해당 예제에서 private한 속성은 지역변수인 title이다.
return을 하면, 사라지는 변수였으나 내부함수를 통해서 사용하고 있기 때문이다.
JavaScript는 기본적으로 Private한 속성을 지원하지 않는데, 클로저의 이러한 특성을 이용해서 Private한 속성을 사용할 수 있게된다.

※ 참고
Private 속성은 객체의 외부에서는 접근할 수 없는 외부에 감춰진 속성이나 메소드를 의미한다.
이를 통해, 객체 내부에서만 사용해야 하는 값이 노출됨으로서 생길 수 있는 오류를 줄일 수 있다.

클로저를 구현하는 과정에서 발생할 수 있는 실수

예제를 통해서 알아보자.

var arr = []
for(var i = 0; i < 5; i++){
    arr[i] = function(){
        return i;
    }
}
for(var index in arr) {
    console.log(arr[index]());
}

위 소스 코드의 출력 결과는 5 5 5 5 5 이다.

왜냐하면, 함수가 함수 외부의 컨텍스트에 접근할 수 없기 때문이다.

즉, 현재의 i값은 전역변수를 바라보고 있기 때문에 최종 i의 값인 5가 출력되고 있는 것이다.

 

이를 해결하기 위해서는 외부함수를 정의하고, 외부함수의 지역변수 값을 내부함수가 참조하도록 하면 된다.

var arr = []
for(var i = 0; i < 5; i++){
    arr[i] = function(id) {
        return function(){
            return id;
        }
    }(i);
}
for(var index in arr) {
    console.log(arr[index]());
}

 

위 예제의 결과값은 0 1 2 3 4 가 출력된다.

 

그것은 내부함수가 외부함수의 지역변수에 접근이 가능하기 때문이다.

함수가 만들어지는 시점에서의 i값을 외부함수의 id변수가 가지고 있었기 때문에 0 1 2 3 4를 출력할 수 있다.

728x90

'언어 > Javascript' 카테고리의 다른 글

[함수지향] 함수의 호출  (0) 2021.02.05
[함수지향] arguments  (0) 2021.02.05
[함수지향] 콜백 & 비동기 처리  (0) 2021.02.05
[함수지향] 유효범위 - 전역변수, 지역변수  (0) 2021.02.04
정규표현식  (0) 2021.02.04
Comments