클로저(Closure)란?
No Filled
함수가 선언될 당시의 렉시컬 환경 (Lexical Environment)을 기억하여, 함수가 스코프 밖에서 실행될 때도 그 환경에 접근할 수 있는 자바스크립트의 특성
기본 개념
- 클로저는 함수와 그 함수가 선언된 렉시컬 환경의 조합
- 내부 함수가 외부 함수의 변수에 접근할 수 있고 외부 함수가 종료된 후에도 그 변수들에 계속 참조 가능
등장 배경
- 데이터 은닉 문제: JS에는 초기에 private 변수 개념 없었음
- 상태 유지 필요성: 함수 실행이 끝나도 특정 값을 보존해야 하는 상황
- 함수형 프로그래밍: 함수를 일급 객체로 다루면서 자연스럽게 발생한 패턴
- 콜백과 비동기: 이벤트 핸들러나 비동기 처리에서 외부 컨텍스트 접근 필요
동작 원리
1단계 - 함수 선언 시
- 함수가 생성될 때 해당 함수는 자신이 선언된 렉시컬 환경을 내부 슬롯
[[Environment]]에 저장
2단계 - 실행 컨텍스트
- 외부 함수 실행 시 실행 컨텍스트와 렉시컬 환경 생성
- 내부 함수는 외부 렉시컬 환경에 대한 참조 유지
3단계 - 외부 함수 종료
- 일반적으로 실행 컨텍스트는 콜 스택에서 제거
- 하지만 내부 함수가 외부 함수의 변수를 참조하고 있으면 가비지 컬렉션 대상이 되지 않음
4단계 - 내부 함수 실행
- 내부 함수가 호출되면 스코프 체인을 통해 외부 변수에 접근
- 저장된 렉시컬 환경을 통해 값을 읽거나 수정
예시 코드
function createCounter() {
let count = 0 // 외부 함수의 지역 변수
return function () {
// 내부 함수 (클로저)
count++
return count
}
}
const counter1 = createCounter()
const counter2 = createCounter()
console.log(counter1()) // 1
console.log(counter1()) // 2
console.log(counter1()) // 3
console.log(counter2()) // 1
console.log(counter2()) // 2헷갈리기 쉬운 부분
클로저 vs 스코프
- 스코프: 변수의 유효 범위 (어디서 접근 가능한가)
- 클로저: 함수가 선언된 환경을 기억하는 현상 (어떻게 접근하는가)
렉시컬 환경 vs 실행 컨텍스트
- 렉시컬 환경: 변수와 함수 선언을 저장하는 구조 (정적)
- 실행 컨텍스트: 코드 실행에 필요한 환경 (동적, 콜 스택에서 생성/제거)
개념 정리
클로저란 무엇인가요?
클로저는 함수가 선언될 당시의 렉시컬 환경을 기억하여, 함수가 스코프 밖에서 실행될 때도 그 환경에 접근할 수 있는 자바스크립트 특성입니다.
자바스크립트에서 함수가 생성될 때 그 함수는 자신이 선언된 위치의 렉시컬 환경을 내부적으로 참조합니다. 일반적으로 함수가 실행을 마치면 그 함수의 지역 변수들은 메모리에서 제거되지만, 내부 함수가 외부 함수의 변수를 참조하고 있다면 가비지 컬렉션의 대상이 되지 않습니다. 외부 함수의 실행이 종료된 후에도 내부 함수는 외부 함수의 변수에 계속 접근할 수 있는 것입니다.
주의할 점으로 클로저가 외부 변수를 계속 참조하고 있으면 메모리에서 해제되지 않기 때문에, 불필요한 클로저를 많이 만들거나 제대로 정리하지 않으면 메모리 사용량이 늘어날 수 있습니다.
핵심 문장
- 클로저는 함수가 자신이 선언된 렉시컬 환경을 기억하는 것입니다.
- 내부 함수가 외부 함수의 변수를 참조할 때 발생하며, 외부 함수 실행이 종료된 후에도 그 변수에 접근할 수 있게 해줍니다.