1. 렉시컬 스코프
자바스크립트의 스코프는 호출한 위치가 아니라 정의한 위치에 따라 결정된다. 이를 정적 스코프(Lexical Scope) 라고 한다.
함수의 상위 스코프는 정의한 위치에 의해 정적으로 결정되며, 변하지 않는다.
스코프의 실체는 실행 컨텍스트의 렉시컬 환경(Lexical Environment) 이다.
이 렉시컬 환경은 내부적으로 외부 렉시컬 환경에 대한 참조를 갖고 있어, 상위 스코프를 연결한다.
상위 스코프 참조는 함수가 정의될 때 저장된다. (호출 시점 아님)
즉, 자바스크립트 엔진은 변수를 찾을 때 현재 스코프 → 상위 스코프 순으로 탐색하며, 이 연결 구조를 스코프 체인이라고 한다.
2. 클로저란?
클로저(Closure) 는 “함수와 그 함수가 선언된 렉시컬 환경의 조합”이다.
함수 객체는
[[Environment]]내부 슬롯에 자신이 정의된 위치의 상위 스코프를 저장한다.외부 함수보다 내부 함수가 더 오래 살아남으면, 내부 함수는 종료된 외부 함수의 변수도 계속 참조할 수 있다.
이렇게 살아남은 중첩 함수를 클로저라고 한다.
함수가 실행되면 원래 변수들은 함수 끝나고 사라짐.
근데 내부 함수가 바깥 함수 변수를 참조하고 있으면, 그 변수는 메모리에 남아있음.
그래서 함수가 종료된 후에도 내부 함수가 그 변수를 “기억”하고 쓸 수 있음.
function makeCounter() {
let count = 0; // 외부 함수의 지역 변수
return function() { // 내부 함수 (클로저)
count++;
return count;
};
}
const counterA = makeCounter();
console.log(counterA()); // 1
console.log(counterA()); // 2
console.log(counterA()); // 3
const counterB = makeCounter();
console.log(counterB()); // 1
같은
makeCounter로 만들어도 각 인스턴스는 독립된 클로저(counterA와counterB는 각각 독립된 클로저를 가진다.)makeCounter는 실행이 끝났지만, 내부 함수가count를 참조하고 있기 때문에count는 메모리에 유지된다.
function multiplier(factor) {
return function(number) {
return number * factor;
};
}
const double = multiplier(2);
const triple = multiplier(3);
console.log(double(5)); // 10
console.log(triple(5)); // 15actor는multiplier실행 시 생성된 렉시컬 환경 안에 묶여서 계속 기억됨.double은factor=2를,triple은factor=3을 각자 캡처한 클로저.
3. 클로저의 활용
클로저는 단순히 변수 참조가 남아 있는 현상 그 이상으로, 코드 구조를 안정적으로 만드는 데 유용하다.
상태 유지 및 은닉
외부에서 직접 접근할 수 없게 하고, 내부 함수로만 값을 변경하도록 제한한다.
의도치 않은 값 변경을 막아 안정성을 높인다.
정보 은닉과 캡슐화
객체 지향에서의 캡슐화와 비슷하다.
공개할 필요 없는 데이터를 숨겨서 코드의 결합도를 낮춘다.
함수형 프로그래밍
가변 데이터를 최소화하고 부수 효과를 줄여, 예측 가능한 동작을 만든다.
4. 정리
렉시컬 스코프: 함수의 상위 스코프는 정의 위치에 따라 정적으로 결정된다.
클로저: 함수가 종료된 뒤에도, 내부 함수가 외부 함수의 변수를 기억하고 접근할 수 있는 현상.
활용: 상태 관리, 정보 은닉, 안정성 확보, 함수형 프로그래밍 패턴 구현에 사용된다.