본문 바로가기

카테고리 없음

Closure가 뭔가요?

짜잔! 폐쇄입니다. 이상 Closure가 무엇인가에 대한 포스팅이였습니다~


Execution Context

Closure가 무엇인지 알기 위해서는 우선 Execution Context에 대하여 알고 있어야 합니다.

Execution Context는 javascript 코드를 실행하기 위한 환경 정보를 모아둔 객체입니다.

 

기본적으로 생성되는 Global Context를 제외하면 eval을 통해 코드를 실행하거나 함수를 호출할 때 Context 정보를 생성합니다.

Context가 생성되면 Call Stack에 쌓이게 되며 해당 Context의 작업이 종료되면 Call Stack 밖으로 나가게 됩니다.

이때 중요한 것은 Call Stack 밖으로 나가게 되더라도 Context는 바로 해제되지 않습니다.

javascript의 GC가 해제 할 때까지 메모리에 존재합니다.

최종적으로 Call Stack이 모두 비워지게 되면 프로그램이 종료됩니다.

Execution Context의 환경 정보들

Execution Context에는 VariableEnvironment와 LexicalEnvironment라는 2가지의 환경정보와 ThisBinding에 관한 정보가 들어있습니다.

VariableEnvironment - environmentRecord

environmentRecord에는 현재 Context에 관련된 코드의 식별자 정보들이 저장됩니다. (변수, 함수의 선언과 같은 것들이 식별자에 해당)

Context의 내부를 처음부터 끝까지 훑어가며 순서대로 수집합니다.

주의) 이해를 위해 이런 이미지를 사용하였지만 실제로 코드의 변수 선언을 끌어올린 것이 아님

이때 코드를 실행하지는 않았지만 Context 내부의 모든 변수명을 알 수 있게 됩니다.

이는 모든 식별자들을 최상단에 끌어올린 것으로 간주하게 되고 이를 Hoisting이라고 합니다.

Hoisting된 식별자들은 처음에는 undefined로 되어 있으며 LexicalEnvironment로 복사되어 값이 할당되기 시작할 때 실질적으로 값이 할당되기 시작합니다.

VariableEnvironment - outerEnvironmentReference

outerEnvironmentReference는 현제 Context의 상위 Context를 참조합니다.

전역 환경에서는 null 입니다.

function b()의 context에서 value1을 environmentRecord에서 찾지 못할 경우 outerEnvironmentReference의 environmentRecord에서 탐색하게 됩니다.

때문에 function b()에서 value1의 값을 가져올 수 있게 됩니다.

LexicalEnvironment

LexicalEnvironment는 Context 생성시 VariableEnvironment의 값을 복사하여 만들어집니다.

실제로 Call Stack에 쌓이는 것은 LexicalEnvironment입니다.

 

Context가 생성되고 프로그램이 종료되는 과정 정리 (이미지가 많아 접어두었습니다.)

더보기

1. VariableEnvironment 생성

2. function a() 호출

3. value1 값 할당

4. function b() 호출

5. value2 할당

6. value1 탐색

7. outEnvironmentReference의 environmentRecord 탐색

8. value1 출력

9. value2 탐색 & 출력

10. function b() 호출 종료

이때 중요한 것은 함수 호출이 종료되어도 Context는 바로 해제되지 않습니다.
javascript의 GC가 해제 할 때까지 메모리에 존재합니다.

11. function a() 호출 종료

12. Global Context 소멸, 프로그램 종료

그래서 결국 Closure가 무엇인가?

이 처럼 Context가 Call Stack에서 빠져나가 접근 경로가 폐쇄된 상태를 Closure라고 합니다.

정리

Q. Closure가 무엇인가요?

A. Closure란 Context가 Call Stack에서 빠져나가 LexicalEnvironment에 접근이 폐쇄된 상태를 응용한 기법입니다.