함수의 호출 위치에 따라 scope 범위가 달라진다면 dynamic scope라고 할 수 있겠지만 자바스크립트는 dynamic scope가 아닌 static scope를 채택하고 있습니다. 자바스크립트의 함수의 유효 범위는 그 함수가 어디서 실행됐느냐가 아니라 어디서 정의됐느냐에 따라서 달라집니다. static scope는 lexical scope라고도 부르는데, 함수를 함수 안에 정의하면 그 함수의 부모 함수의 scope에 접근할 수 있습니다. 즉, 클로저는 반환된 내부함수가 자신이 선언됐을 때의 환경(Lexical environment)인 스코프를 기억하여 자신이 선언됐을 때의 환경(스코프) 밖에서 호출되어도 그 환경(스코프)에 접근할 수 있는 함수를 말합니다.
자바스크립트는 기본적으로 어휘적 환경(Lexical environment)을 갖고, 코드가 실행되면 스크립트 내에서 선언한 변수들이 어휘적 환경에 올라갑니다. 코드에서 변수를 찾을 때 유효 범위 안의 내부에서 찾고, 없으면 외부, 거기에도 없으면 전역 Lexical까지 범위를 넓혀서 찾습니다. 클로저는 결국 함수와 렉시컬 환경의 조합입니다. 함수가 생성될 당시의 외부 변수를 기억해서 사용할 수 있으며, 생성 이후에도 계속 접근 가능합니다. 식별자에 대한 직접적인 접근을 막을 수 있기 때문에 캡슐화 및 은닉화가 가능하지만, 역으로 무분별하게 사용한다면 쓸데없이 메모리를 낭비할 수 있기 때문에 해제를 통해 메모리 소모를 줄여야 합니다.
클로저는 여러 함수형 프로그래밍 언어에서 등장하는 보편적인 특성입니다. 자바스크립트 고유의 개념이 아니라서 ECMAScript 명세에서도 클로저의 정의를 다루지 않고 있고, 꼭 그것 때문이라고는 할 수 없지만 다양한 문헌에서 제각각 클로저를 다르게 정의하거나 설명하는 경우가 많습니다.
ES3까지는 실행 컨텍스트 없이 dynamic scope였는데, ES5 이후 (2009년~)부터는 어디에 선언되어 있느냐에 따라 정적으로 결정되어 하나의 실행 컨테스트 개념으로 묶였습니다.
꼬리 질문
ECMAScript는 무엇인가요?
ECMA International이라는 비영리 국제 표준화 기구에서 JS 발전이나 변화 등을 관리
규칙이나 준수사항 등을 ECMA-262이라는 문서로 관리하게 되는데 이 문서의 내용을 ECMAScript
변화가 있을 때마다 ES1, ES2 형식으로 부르다가 6 버전이 등장한 2015년부터는 1년마다 출시하기로 결정하면서 편의상 ES6라고 부르지만 정식 명칭은 뒤에 연호를 달아서 ES2015, ES2016의 형식
ES6 버전은 JavaScript의 많은 부분을 보완한 버전 → ES5가 가지고 있던 문제점들을 보완하고(Arrow function, let, for of 등), 코드를 더 간결하게 작성할 유용한 문법들이 등장
현시점에 사용하기 적합한 범위 내에서 최신 버전의 표준을 준수하는 자바스크립트를 모던 자바스크립트라고 부름