본문 바로가기
JavaScript

클로저란, javascript Closure?

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

 

이게 도대체 무슨 소리일까요? 한국말이 맞긴 한 걸까요?

자, 차분히 한 번 알아봅시다!

 

저 뜻을 이해하기 위해, 우선 렉시컬 환경이 무엇인지에 대해 알아보겠습니다.

 

렉시컬 환경은 상위 스코프를 의미하는 실행 컨텍스트의 렉시컬 환경을 뜻합니다.

 

자, 또 위기에 봉착했습니다!

포기하지 않고, 여기서 다시 한 번 저게 무슨 말인지 알아보겠습니다!

 

렉시컬(스코프) 환경은 함수를 "어디서 호출" 했는지가 아닌 "어디서 정의" 했는지에 따라 상위 스코프가 결정되는 것 입니다!

 

코드로 한 번 보시죠!

자 이게 바로 위에서 설명드린 렉시컬 스코프와 클로저의 예시인데요!

 

마지막에 innerFunc()가 리턴하는 값은 무엇이 될까요?

바로 1이 아닌 10입니다.

 

왜 그럴까요?

바로 렉시컬 스코프 환경이기 때문입니다!

 

inner함수는 outer 함수 안에서 정의되었기에 x 값이 10이 됩니다.

"어디서 호출"하는지와 상관없이 "어디서 정의"되느냐에 따라 x값이 달라지게 되는거죠!

 

어디서 정의 되느냐에 따라 내 상위 스코프가 결정되는 것, 이것을 바로 렉시컬 스코프 환경이라고 합니다.

 

자! 오케이!

그렇다면 렉시컬 스코프가 무엇인지는 알았습니다.

 

이제 클로저를 왜 렉시컬 환경과의 조합이라 설명하는지 알아보겠습니다.

다시 코드로 돌아오겠습니다!

 

렉시컬 스코프는 다시 한 번,

함수를 "어디서 호출"했지는지가 아닌 "어디서 정의"했는지에 따라 상위 스코프가 결정 되는 것인데요.

 

자 그렇다면?

 

렉시컬 환경때문에 위의 코드에서 Inner함수는 outer함수의 변수인 x를 참조하고 있습니다.

그런데 outer함수는 inner 함수를 리턴하고 생명 주기를 마감해버립니다.

실행 컨텍스트 스택에서 제거되는 것이죠.

 

그런데 어떻게 inner함수는 outer함수의 변수를 참조할 수 있게 되는 걸까요?

 

그 이유는  Outer 함수의 생명주기가 끝나도 해당 함수의 변수가 참조되고 있다면, 렉시컬 환경 레코드는 여전히 남기 때문입니다!

가비지 컬렉터는 누군가 참조하고 있는 메모리 공간을 함부로 해제하지 않습니다.

그래서 이미 생명 주기가 끝나버린 함수의 변수를 중첩함수인 Inner함수가 참조할 수 있게 되는 건데요!

 

이와 같이,

외부 함수(outer)보다 중첩 함수(Inner)가 더 오래 유지되는 경우, 이미 생명 주기가 종료된 외부 함수의 변수를 참조할 수 있는 중첩 함수 "클로저"라고 부릅니다.

 

조금 이해가 되셨을까요?

자 그럼 이제, 이 클로저는 어떻게, 어디서 쓰이길래 자바스크립트에서 꼭 배워야하는 것 일까요?

 

클로저는 상태를 안전하게 변경하고 유지하기 위해 사용합니다!

 

클로저를 활용한 새로운 코드 예시를 보여드릴게요!

즉시 실행 함수는 단 한 번만 실행이 되기 때문에, Increase()가 호출될 때마다 num 변수가 초기화되진 않습니다.

그리고 실행이 종료되면 num을 증가시키는 클로저 함수를 반환하게 되죠!

반환된 함수는 이미 생명주기가 종료된, 즉시 실행함수의 변수 num을 참조하고 있기에 클로저라고 부릅니다!

그리고, 이 반환된 클로저 함수만이 num에 대한 값을 변경할 수 있게 되는 겁니다!

 

클로저는 이처럼 상태를 안전하게 은닉하고, 의도치 않게 값이 변경되지 않도록 특정 함수에게만 상태 변경을 허용하는 것이죠!

 

그럼 오늘은 여기까쥐~

혹시 잘못된 정보가 있다면 알려주세요!

 

 

참고 문헌:

MDN, Javascript Deep Dive

 

반응형