클로저를 열어보자

이윤준·2021년 8월 27일
9

JavaScript

목록 보기
2/3

자바스크립트에는 아주 특이한 현상이 일어난다. 죽어야할 컨텍스트의 지역변수가 계속 살아있는 무서운 현상이다. 그것을 우린 Closure라고 부른다.

클로저는 무엇인가?

사전적인 의미는 '폐쇄'이다. 자바스크립트에서 말하는 클로저를 정의하자면, 지역변수로 있던 익명함수가 리턴되면서 참조되고 있던 다른 지역변수가 컨텍스트가 소멸됨에도 불구하고 사라지지 못하고 남아있는 현상이라고 할 수 있다. 이렇게 보면 굉장히 말이 어렵다.

개발자답게 코드로 봐보자

 function func(){
            let a = 10;
            let f = function(){
                console.log(a);
            }
            a += 10;
            f();
        }
        func();
        func();

아래 내용을 보기 전에, 위 코드의 결과를 출력결과를 예상해보자.
일반적으로 생각하면, func()코드가 실행될 때, 지역변수로 내부에 변수 a를 선언하기 때문에, 결과로 10 10이 출력될 것이라고 생각할 수 있다.

20
20

하지만 출력결과는 위와 같다. 이러한 현상이 일어나는 이유는 자바스크립트의 어휘적 범위 지정(Lexical scoping)과정에서 함수 내부에서 외부 함수의 변수에 접근 할 수 있도록 설정하기 때문이다.

아래 코드의 출력도 예상해보자

       function func(){
            let a = 10;
            let f = function(){
                console.log(a);
                a+=10;
            }
            return f;
        }
        let f1 = func();
        let f2 = func();
        f1();
        f2();

정답은

10
10

이다. 여기서 조금 어리둥절할 수 있다. 클로저를 더 그림으로 표현해 보면 아래와 같다.

func영역이 소멸되면, f 함수가 참조하는 변수를 복제해서 메모리 어딘가에 생성한다. 이때 생성된 데이터가 클로저이다. 이때 func영역이 소멸되는 순간에 저장되어 있는 값을 저장한다. 생성된 f함수가 여러개여도, 클로저는 하나의 영역만을 생성하기 때문에, 싱글톤패턴의 특성도 보인다.

소멸되는 순간에 a의 값이 10이었기 때문에, 10을 참조해서 출력이 10 10이 된 것이다. 마찬가지로 첫 번째 코드의 경우 func()가 소멸될 때 a의 값이 20이였기 때문에 20 20이 출력된다.

클로저의 활용

이렇게 복잡한 클로저를 어디서 활용할 수 있을까? 바로 배열에 함수를 할당할 때 사용할 수 있다.

아래 코드의 출력결과로 다들 0 1 2를 생각하겠지만, 클로저 때문에 아래함수의 출력결과는 3 3 3이다.

        let i = 0;
        for( i = 0; i < 3; i++){
            arr[i] = function(){
                console.log(i);
            }
        }
        for( let j = 0; j < 3; j++)
            arr[j]();
        

이러한 문제를 해결하기 위해서는 코드를 아래와 같이 변경하면

        let arr = [];
        let i = 0;
        for( i = 0; i < 3; i++){
            let idx = i;
            arr[idx] = function(){
                console.log(idx);
            }
        }

        for( let j = 0; j < 3; j++)
            arr[j]();
        

출력결과가

0
1
2

으로 나오는 것을 볼 수 있다.

클로저때문에 발생한 에러와 싸우면 굉장히 힘들 수 있기 때문에 이번 기회에 정리해둔다.

profile
욕심쟁이 개발자

1개의 댓글

comment-user-thumbnail
2021년 8월 28일

이해가 정말 잘 됐어용 감사합니다!!♥️

답글 달기