본문 바로가기

개발자는 알아야될 지식/[Javascrpit] 클로져(Closure)란 ?

클로져(Closure)는 무엇이며, 어떻게/왜 사용하는가?

클로져를 제대로 이해하기 위해서는 javascript 의 scope, scope chain, context 에 대한 이해가 선행 되어야 한다.

 

[scope]

: 우리말로 번역하면 ‘범위’라는 뜻을 가지고 있습니다. 즉, 스코프(Scope)란 ‘변수에 접근할 수 있는 범위’라고 할 수 있다

 

자바스크립트에선 2가지의 스코프가 있다

1. global (전역) : 어느 곳에서든지 해당 변수에 접근가능. 

2. local (지역) : 해당 지역에서만 접근 가능

 

자바스크립트는 함수를 선언할 때마다 새로운 스코프를 생성한다. 함수 안에서 선언한 변수는 해당 함수 안에서만 접근할 수 있는데 이걸 함수 스코프(function-scoped)라고 한다.(함수스코프는 local scope의 예라고 할 수 있다.)

 

EX)

 

print() 함수는 자신의 영역안에 a 변수를 찾아내어 출력합니다.

 

print() 다음 console.log(a)는 전역에 있는 변수 a를 찾아내어 출력합니다.

 

근데 만약 print() 안에 변수 a를 지운다면 ??

 

 

 

 

 

 

 

 

 

EX) print() 안에 변수 a를 지운다면??

 

 

결과는 print() 함수에서도 전역으로 선언된 변수가 출력됩니다. 

 

이는 Scope Chain에 의해 일어나는 현상인데 

 

현재 자신의 scope에서 사용하고자 하는 변수가 없다면 Scope Chain을 통해 해당 변수를 찾게됩니다.

 

 

 

 

 

 

 

 

[Scope chain]

: Identifiers(식별자)를 찾는 일련의 과정

 

자바스크립트는 실행시점에 Excecution Context(EC)가 생성이되고, 그 시점에 온갖 잡다한 행위들이 이뤄집니다.

Scope Chain 예시

a(), b() 가 실행되면서 생성된 EC에 의해서 b() 함수내 변수 a를 탐색하기 시작하는데, 만약 함수 b()에 변수 a 가 없다면 함수 b()를 감싸고 있는 외부함수 a() 를 탐색하게 됩니다. 이때 변수 a가 존재하면 a를 참조하게 되고, 혹시 없다면 계속적으로 감싸고 있는 상위 함수를 탐색하는 과정을 거칩니다.
결국 찾지 못하고 root 인 Global Object EC까지 오게 되고 탐색하는 a가 없다고 VM500:1 Uncaught ReferenceError: a is not defined라는 자주보는 에러를 뿜어내게 됩니다.

한마디로 scope chain 은 dentifiers(식별자)를 찾는 일련의 과정이다

 

참고 : tyle.io/blog/54

[Execution Context]

: 실행 가능한 코드를 형상화하고 구분하는 추상적인 개념이라고 정의하면 된다.
쉽게 말하자면 코드들이 실행되기 위한 환경이라고 이해하면 될 것 같다.
(코드가 실행된다면 Execution Context 내부에서 실행되고 있는 것이다.)

 

  • Execution Context 종류
    1.  Global Context (전역 컨텍스트) : 함수 안에서 실행되는 코드가 아니라면 모든 스크립트는 Global Context에서 실행된다.
      • 동작과정 : 스택 구조를 가지는 형태로 Excution Context 가 생성된 후 -> Global Object 로 window가 this로 할당되고 스택에 쌓인다. Global Context 안에 포함되는 모든 코드들의 실행 가능한 코드들은 순서대로 스택에 쌓이게 되며 LIFO (후입선출)로 함수를 실행하게 된다. 
    2.  Functional Context (함수 컨텍스트)
      • 동작과정 : Functional Context 는 선언된 함수가 호출이 될 때를 기점으로 생성이 되고 -> 함수의 모든 동작이 종료되면 Functional Context는 소멸된다. (closure를 사용한다면 스코프가 소멸하지 않고 이용 가능)
      • 각각의 함수들은 각각의 Functional Context를 가지지만 함수가 호출이 되어야만 생성된다.
  • Excution Context의 3가지 객체 : 실행 컨텍스트는 실행 가능한 코드를 형상화하고 구분하는 추상적인 개념이지만 물리적으로는 객체의 형태를 가지며 3가지 프로퍼티를 소유한다.
    1. Variable Object (변수 객체)
    2. Scope Chain
    3. this value

참고 : velog.io/@stampid/Execution-Context%EC%8B%A4%ED%96%89-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8%EB%9E%80

poiemaweb.com/js-execution-context

 

 

[클로져(Closure)]

간단히 설명하자면 클로저는 현재의 유효범위를 넘어 scope chain으로 연결되어 있는 객체,변수등의 참조를 발생시키는 것을 말한다.

javascript는 실행코드 블럭 단위로 context 를 스텍에 쌓게 되고 push, pop 을 통해 코드블럭이 실행 된다. 이때 각각의 실행 코드블럭이 수행되는 시점에서 실행 환경을 저장하게 되는데 이는 실행 유효범위인 scope 에 의해 결정된다.

이 scope 는 chain구조로 연결되어 있어 현재 실행 시점 이전의 scope 를 타고 올라가는 형태로 참조 되기 때문에 현재 scope 에 선언되지 않는 객체참조가 가능하다.

이는 java 등의 언어만 다루던 사람들에겐 좀 의아한 모습으로 동작한다. local 변수와 global 변수의 경계와 유요범위 설정에 대한 이해를 한번에 무너트려버리기 때문이다.

 

 

a 내부에 선언된 변수 b가 죽지 않고 계속 살아 있습니다.
클로저는 이와 같이 이미 생명 주기가 끝난 외부 함수의 변수를 참조하는 함수를 의미합니다.

 

 

 

 

 

 

 

 

 

클로저의 장점

  1. 함수를 호출할 때마다 기존에 생성했던 값을 유지할 수 있다. 즉, 변수를 재활용할 수 있다.
  2. 외부에 해당 변수(참조하고 있는 변수)를 노출시키지 않는다. 전역적으로 노출 되고 있진 않지만, 전역적인 방식으로 사용될 수 있다는 것이다. 쉽게 말해 코드의 안정성을 보장한다.

클로저의 단점

  1. 클로저에 할당 된 변수는, 프로그램이 종료될 때 까지 메모리에 남아있다.

즉, 클로저를 통하여 변수를 생성하면 재활용을 할 수 있으나, 클로저를 지나치게 많이 사용하면 메모리가 낭비될 수 있다는 것이다.

클로저에 대한 개념을 정확하게 이해하기 위해서는

  1. 변수의 스코프
  2. 변수의 생명주기
  3. 가비지 컬렉터(쓰레기 변수 수집기)
  4. 1급시민

등의 개념을 알고 있어야 한다.

insanehong.kr/post/front-end-developer-interview-javascript/