티스토리 뷰
JavaScript 클로저(Closure)의 원리
1. 클로저(Closure)의 컴퓨터 공학적 정의와 발생 조건
MDN(Mozilla Developer Network) 및 ECMAScript 명세에 따르면, 클로저(Closure)는 함수와 그 함수가 선언된 어휘적 환경(Lexical Environment)의 조합입니다. 이를 조금 더 쉽게 풀이하면, 외부 함수의 실행이 완료되어 호출 스택(Call Stack)에서 소멸(Pop)했음에도 불구하고, 내부 함수가 여전히 외부 함수의 스코프(변수)에 접근할 수 있는 메커니즘을 말합니다.
JavaScript는 렉시컬 스코프(Lexical Scoping)를 따르기 때문에, 함수를 어디서 호출했는지가 아니라 '어디에 선언했는지'에 따라 상위 스코프가 결정됩니다. 내부 함수가 상위 스코프의 변수를 참조하고 있고, 해당 내부 함수가 외부로 반환되거나 다른 고차 함수의 콜백으로 살아남을 때 비로소 클로저가 형성됩니다.
| 구분 지표 | 일반적인 함수 환경 | 클로저(Closure) 활성화 환경 |
|---|---|---|
| 메모리 생명주기 | 함수 종료 시 실행 컨텍스트와 내부 지역 변수가 가비지 컬렉터(GC)에 의해 즉시 수거됨. | 외부 함수가 끝나도 내부 함수가 외부 변수를 참조하고 있어 메모리(Heap)에 계속 유지됨. |
| 변수 접근성 | 외부에서 함수 내부 변수에 직접 접근하는 것이 원천적으로 불가능함. | 반환된 내부 함수라는 제한된 인터페이스를 통해서만 외부 변수 제어 가능. |
2. 자바스크립트 가상 머신 내부 아키텍처와 실행 컨텍스트 동작 과정
클로저가 동작하는 원리를 완전히 이해하기 위해서는 자바스크립트 엔진(V8 등) 내부의 실행 컨텍스트(Execution Context) 구조를 들여다보아야 합니다. 함수가 실행되면 가상 머신은 실행 컨텍스트를 생성하고, 그 안에 변수 객체와 상위 스코프에 대한 참조를 기록하는 외부 환경 참조(Outer Environment Reference)를 바인딩합니다.
호출 스택에서 외부 함수의 실행 컨텍스트가 완전히 제거되더라도, 내부 함수 객체의 숨겨진 프로퍼티인 [[Environment]]가 외부 함수의 렉시컬 환경(Lexical Environment) 객체를 메모리 힙(Heap) 공간에서 가리키고 있게 됩니다. 가비지 컬렉터(Garbage Collector)는 참조 카운트가 0이 아닌 메모리 블록을 지우지 않으므로, 외부 함수의 변수들은 온전히 보존됩니다.
3. 실무 중심 클로저 구현 패턴: 정보 은닉(Information Hiding)과 캡슐화
과거 자바스크립트는 클래스 기반 언어처럼 완전한 private 접근 제어자를 지원하지 못했습니다. (최근 # 명세가 추가되었으나 호환성 이슈가 존재) 개발자들은 클로저의 스코프 차단 특성을 이용하여 외부에서 손댈 수 없는 '안전한 상태 저장소'를 구축해 왔습니다.
const createAccount = (holderName, initialBalance) => {
let balance = initialBalance; // 외부에서 절대 직접 변경할 수 없는 Private 상태
return {
deposit(amount) {
if (amount > 0) {
balance += amount;
Console.log(`${holderName}님 계좌에 ${amount}원 입금 완료. 현재 잔액: ${balance}원`);
}
},
withdraw(amount) {
if (amount > balance) {
throw new Error("잔액이 부족하여 출금할 수 없습니다.");
}
balance -= amount;
return amount;
},
getBalance() {
return balance; // 읽기 전용 인터페이스 제공
}
};
};
const myAcc = createAccount("홍길동", 10000);
myAcc.deposit(5000); // 출력: 홍길동님 계좌에 5000원 입금 완료. 현재 잔액: 15000원
Console.log(myAcc.balance); // undefined (직접 참조 우회로 원천 차단)
위 예제에서 createAccount 함수는 이미 실행이 끝났지만, 객체 내부의 메서드들(deposit, withdraw, getBalance)이 balance 변수가 존재했던 상위 어휘적 환경을 영구적으로 기억하고 활용합니다. 전역 변수의 오염 없이 독립적인 모듈 상태를 안전하게 설계할 수 있는 비결입니다.
4. Stack Overflow 단골 질문: 클로저의 부작용 및 메모리 누수(Memory Leak) 제어
클로저는 강력하지만, 메모리 관리 관점에서는 양날의 검입니다. 참조하는 상위 렉시컬 환경이 가비지 컬렉션의 대상에서 제외되기 때문에, 대용량 데이터를 다루거나 단일 페이지 애플리케이션(SPA) 환경에서 클로저를 무분별하게 생성하고 정리하지 않으면 시스템의 사용 가능한 메모리가 서서히 고갈되는 메모리 누수(Memory Leak) 현상이 발생합니다.
이를 방어하기 위한 최적의 방법은 클로저 함수 관계 체인에 할당된 변수를 사용이 끝난 시점에 명시적으로 무력화(Nullify)시키는 것입니다. 아래의 코드는 메모리 안전 벨트를 확보하는 정밀 제어 예시입니다.
let leakProcessor = function() {
let massiveData = new Array(1000000).fill("🔥 Big Memory Heap Data");
return function() {
Console.log(`데이터 가공 유효성 체크: ${massiveData.length}`);
};
};
let runProcess = leakProcessor();
runProcess(); // 클로저 가동 및 상위 배열 메모리 점유 상태 유지
// [중요 트러블슈팅] 작업 완료 후 더 이상 함수 호출이 필요 없을 때 가비지 컬렉터로 밀어내기
runProcess = null; // 참조 고리를 임의로 끊어 렉시컬 환경 전체를 GC 수거 대상화함
📚 공식 기술 레퍼런스 (References)
- ECMAScript Language Specification (ECMA-262): "Section 9.1 - Lexical Environments & Environment Records" 기계식 구조 사양 준수
- V8 JavaScript Engine Documentation: "Trash 3P - Garbage Collection and Context Management Optimization" 가비지 컬렉팅 알고리즘 인용
- Stack Overflow Annual Developer Trends: "JavaScript Top Tagged Questions Analysis - Closures Scope & Variable Bindings" 트렌드 통계 반영
#자바스크립트클로저 #JSClosure #실행컨텍스트원리 #렉시컬스코프 #정보은닉캡슐화 #V8엔진메모리구조 #자바스크립트메모리누수 #스택오버플로우인기주제
'HTML, CSS, JS' 카테고리의 다른 글
| 토글 버튼 만들기 예제 (0) | 2026.05.06 |
|---|---|
| webview) ios와 android의 scroll 차이 (0) | 2019.06.05 |
| javascript date format 변경 방법 (0) | 2019.05.09 |
| 자바스크립트 객체 배열에서 indexOf 사용방법 (4) | 2019.04.11 |
| 자바스크립트 SyntaxError: missing 오류 해결 방법 (1) | 2019.04.10 |
| 자바스크립트 스크롤 멈춤 이벤트 (0) | 2019.04.07 |
| JavaScript String substring() Method : 자바스크립트 문자열 자르기 (0) | 2019.03.25 |
| css로 텍스트 ... 처리하기 - 고정, 가변 길이 element (0) | 2019.03.25 |
- Total
- Today
- Yesterday
- 배열
- html
- C언어
- Java
- 자바
- 블루투스
- 문제풀이
- DB연동
- 리스트
- C++ 클래스
- OpenCV
- MySQL
- Android
- 알고리즘
- 안드로이드
- 데이터베이스
- 상속
- 문자열
- 벡터
- 클래스
- C
- String
- C++
- 파이썬
- 자료구조
- 파일처리
- 아두이노
- Class
- 정보처리기사
- c#
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 9 | 10 | 11 | 12 | 13 | 14 | 15 |
| 16 | 17 | 18 | 19 | 20 | 21 | 22 |
| 23 | 24 | 25 | 26 | 27 | 28 | 29 |
| 30 | 31 |