[functional programming] 클로저(Closure)를 샅샅이 파헤치자: 스코프(scope)와 렉시컬 스코프(lexical scope)
01 Dec 2019
Reading time ~3 minutes
1. 클로저(closure)의 개념
- 클로저는 자바스크립트 고유의 개념이 아니라 함수를 일급 객체로 취급하는 함수형 프로그래밍 언어에서 사용되는 중요한 특성이다
클로저는 자바스크립트 고유의 개념이 아니다. 따라서 ECMAScript 문서에 클로저의 정의가 등장하지 않는다.
MDN이 얘기하는 클로저의 정의:
“A closure is the combination of a function and the lexcial environment within which that function was declared.”
클로저는 어떠한 한 함수가 선언된 렉시컬 환경과 그 함수의 조합이다.
무슨 말인지 잘 모르겠다. 싫증이 나기 시작할 수도 있다. 하지만 하나하나 천천히 파헤쳐보자.
여기서 말하는 렉시컬 환경은 함수가 속한 렉시컬 스코프와 동의어라고 할 수 있다. 그럼 렉시컬 스코프는 무엇인가? 아니 먼저 스코프는 또 무엇인가?
scope: FPS 게임을 해본 사람이라면 혹은 총기에 대해 잘 아는 사람이라면 들어봤을 단어다. 스코프는 사격시에 조준율을 높일 수 있도록 배율을 높이는 망원경과도 같은 역할을 한다. 스코프가 있어야만 볼 수 있는 것들이 있고 사격할 수 있는 타겟들이 있다. 특정 총기는 스코프가 없다면 제대로된 구실도 못하는 상황도 있다. 스코프는 우리 몸의 감각기관(시각, 촉각, 후각, 청각…)과도 같다고 보면 된다.
어떠한 변수 혹은 함수가 선언 됬을 때 그 함수는 어떠한 스코프에 속해 있다. 그 변수 혹은 함수가 볼 수 있는 영역이 있고 없는 영역이 있다. 스코프는 변수나 함수가 볼 수 있는 혹은 참조할 수 있는 영역을 뜻한다. 그리고 이 스코프는 함수를 호출할 때가 아니라 함수를 어디에 선언하였는지에 따라 결정된다
자, 그럼 다음으로 렉시컬 스코프는?
lexical scoping: 함수 자신이 속한 스코프와 상위스코프의 환경에 접근할 수 있는 것을 뜻한다.
설명을 꼼꼼히 읽어보기도 하고 여러번 읽어보기 했는데 아직 완전히 내것이 아닌듯하다.
그렇다면 백문이 불여일견. 코드를 보면서 앞서 말한 개념들을 확인해보자.
function outtie () {
var 취뽀 = '소리벗고 팬티질러';
function innie () {
console.log(취뽀)
}
innie();
}
outtie(); // 소리벗고 팬티질러
outtie 라는 함수가 선언 되어있다. 그 안에 var 변수 ‘취뽀’ 선언과 값이 할당되고 또 다른 함수 innie 라는 함수가 선언 되어있다. Innie 안에는 콘솔에 로그하는 함수 실행문이 있다. 함수 실행문에는 인자로 변수 취뽀의 값을 받는다. innie 함수 선언은 여기까지고, 그 뒤에 innie 함수를 호출 한다. 그리고 가장 아래엔 outtie 함수를 호출한다.
함수 outtie와 innie가 각각 속한 스코프는 어떤 것이 있을까?
outtie와 innie 각각 자신히 속한 렉시컬 스코프를 참조할 수 있다. outtie의 렉시컬 스코프는 자신의 스코프와 전역이 해당되고, innie의 렉시컬 스코프는 자신의 스코프, outtie의 스코프, 그리고 전역이 해당된다.
이것을 실행 컨텍스트 관점에서 보다면?
내부 함수 innie가 호출되면 실행컨텍스트 스텍에 innie의 실행 컨텍스트가 쌓이게 된다. 이때 innie의 실행 컨텍스트에 변수 객체, 스코프 체인, 그리고 this가 바인딩할 객체, 총 3가지가 결정된다.
- 변수객체: innie 실행 컨텍스트의 변수객체에는 innie 함수 스코프 안의 선언된 변수와 함수가 들어있다.
- 스코프체인: 그리고 innie의 실행 컨텍스트의 스코프 체인에 자신의 변수객체와, outtie의 스코프를 가리키는 outtie의 실행 컨텍스트의 변수객체, 그리고 전역 실행 컨텍스트에 들어있는 변수객체를 리스트 형태로 담게 된다.
- this: 마지막으로 innie 실행 컨텍스트의 this 값은 함수 호출 방식에 결정된다.
여기서 말한 스코프 체인이 바로 렉시컬 스코프의 실체이다. 이 스코프 체인을 통해 자신의 부모(상위)의 스코프에 접근 할 수 있다.
스코프 체인의 정의를 잠시 알아보자.
스코프 체인은 식별자 중에서 객체(전역 객체 제외)의 프로퍼티가 아닌 식별자, 즉 변수를 검색하는 메커니즘이다.
식별자 중에서 변수가 아닌 객체의 프로퍼티(물론 메소드도 포함된다)를 검색하는 메커니즘은 프로토타입 체인(Prototype Chain)이다.
“내부 함수 innie가 자신을 포함하고 있는 외부 함수 outtie의 변수에 접근할 수 있다는 것, 다시 말해 상위 스코프에 접근할 수 있는 것은 렉시컬 스코프의 레퍼런스를 차례대로 저장하고 있는 실행 컨텍스트의 스코프 체인을 자바스크립트 엔진이 검색하였기에 가능한 것이다.”
이 내용을 정리해보자
- innie 함수 스코프(함수 자신의 스코프를 가리키는 활성 객체) 내에서 변수 취뽀를 검색한다. 검색이 실패하였다.
- innie 함수를 포함하는 외부 함수 outtie의 스코프(함수 outtie의 스코프를 가리키는 함수 outtie의 활성 객체)에서 변수 x를 검색한다. 검색이 성공하였다.
이렇게 하여 실행컨텍스트의 관점에서 클로저를 알아보았다.
poiemaweb을 참조하여 작성하였습니다.