상권's

TIL 67 (클로저) 본문

~2022 작성 글/TIL

TIL 67 (클로저)

라마치 2022. 3. 1. 19:44

오늘은 클로저에 대해서 더 자세하게 알아보겠습니다.

 

코드스테이츠 수강 중일 때도 클로저에 대해서 학습을 했었고, 수료 후에도 복습을 하긴 했는데 솔직히 정확하게 이해하고 있다고 말을 하긴 어려웠습니다. 동일한 어려움을 겪는 분들이 있으시면 이 글을 통해서 도움을 드릴 수 있길 바랍니다.

 

클로저는 함수와 그 함수가 선언된 렉시컬 환경과의 조합이다.

먼저 MDN에서는 클로저를 위와 같이 정의하고 있습니다.

 

자바스크립트 엔진은 함수를 어디서 호출했는지가 아니라 함수를 어디에 정의했는지에 따라 상위 스코프를 결정하는 렉시컬 스코프를 따릅니다.

const x = 1;

function foo () {
  const x = 10;
  boo();
}

function boo () {
  console.log(x);
}

foo(); // 1
boo(); // 1

위의 코드를 본다면 boo 함수가 출력하는 x가 foo 함수의 지역 변수가 아닌 전역 변수인 x인 것을 알 수 있습니다. 함수 boo가 실행되는 환경에서 스코프가 결정이 된다면 foo 함수 내부에서 정의된 x = 10이 출력될 것이지만, 정의된 위치에 의해 상위 스코프가 결정되면서 전역 변수 x 가 출력됩니다.

 

함수의 상위 스코프는 함수를 정의한 위치에 의해 정적으로 결정되고 변하지 않습니다. 스코프의 실체는 실행 컨텍스트의 렉시컬 환경입니다. 이 렉시컬 환경은 '외부 렉시컬 환경에 대한 참조'를 통해서 상위 렉시컬 환경과 연결이 됩니다.(스코프 체인)

 

이러한 외부 렉시컬 환경에 대한 참조는 평가 과정에서 이루어집니다. 즉 상위 스코프에 대한 참조는 함수 정의가 평가되는 시점에 함수가 정의된 환경에 의해 결정이 되며 이를 렉시컬 스코프라고 할 수 있습니다.

 

함수는 이처럼 자신이 정의된 환경, 즉 상위 스코프를 기억하고 있습니다. 이를 위해 함수는 평가되어 함수 객체를 생성할 때 자신의 내부 슬롯 [[Environment]]에 상위 스코프의 참조를 기억합니다. 

 

그리고 [[Environment]]에 저장된 렉시컬 환경의 참조가 함수 렉시컬 환경의 구성 요소 중 외부 렉시컬 환경에 대한 참조에 할당됩니다.

const x = 1;

function outer() {
  const x = 10;
  const inner = function () { console.log(x); };
  return inner;
}

const innerFunc = outer();
innerFunc(); // 10

innerFunc에 outer 함수를 호출하는데 outer 함수는 inner 함수를 반환하고 생명 주기를 마감합니다.

> outer 함수 생명 주기가 마감되면 실행 컨텍스트 스택에서 제거됩니다. 이 때 outer 함수 내부의 변수 또한 생명 주기를 마감하겠지만, 코드 실행결과를 보면 x는 10으로 출력됩니다.

 

이처럼 외부 함수보다 중첩 함수가 더 오래 유지되는 경우 중첩 함수는 이미 생명 주기가 종료한 외부 함수의 변수를 참조할 수 있습니다. 이러한 중첩 함수를 클로저라고 합니다.

 

mdn의 정의에서 '함수가 선언된 렉시컬 환경'은 함수가 정의된 스코프, 즉 상위 스코프를 의미하는 실행 컨텍스트의 렉시컬 환경을 말합니다.

 

inner 함수는 평가될 때 [[Environment]] 내부 슬롯에 outer 함수의 렉시컬 환경을 상위 스코프로서 저장하고, 이는 함수가 존재하는 한 유지됩니다.

 

이처럼 외부 함수 outer 보다 더 오래 생존한 중첩 함수 inner은 외부 함수의 생존 여부와 상관없이 자신이 정의된 위치에 결정된 상위 스코프를 기억합니다. 하지만 외부 함수의 모든 변수를 기억하지 않고 클로저가 참조하고 있는 식별자만을 기억합니다. 그리고 이러한 변수를 자유 변수라고 부릅니다.

 

마지막으로 클로저 함수는 상태를 안전하게 변경하고 유지하기 위해 사용합니다. 활용하는 코드에 대해서는 조금 더 학습을 해본 후 추가하도록 하겠습니다.

 

여러 TIL에 걸친 정보가 많이 포함되어 있어 처음 접하는 분들은 이해하기 어려우실 수 있습니다. 추가적으로 학습하면서 더 쉬운 단어로 표현할 수 있다면 변경하겠습니다.

 

 

참고 문서 : 모던 자바스크립트 Deep Dive

'~2022 작성 글 > TIL' 카테고리의 다른 글

TIL 70 (async/await)  (0) 2022.03.19
TIL 68 (브라우저 렌더링 과정)  (0) 2022.03.15
TIL 66 (렉시컬 환경)  (0) 2022.03.01
TIL 65 (실행 컨텍스트)  (0) 2022.02.27
TIL 64 (BookDam server TestCode Error)  (0) 2022.02.26
Comments