최종 수정: 2025.06.04
클로저(Closure)
함수와 그 함수가 선언된 렉시컬 환경의 조합이다. 즉, 내부 함수가 외부 함수의 변수에 접근할 수 있는 개념으로, 외부 함수가 실행을 마친 후에도 외부 함수의 변수를 참조할 수 있다.
function outerFunction(x) {
// 외부 함수의 변수
const outerVariable = x;
// 내부 함수
function innerFunction(y) {
// 내부 함수에서 외부 함수의 변수에 접근
console.log(outerVariable + y);
}
return innerFunction;
}
const myClosure = outerFunction(10);
myClosure(5); // 15 출력
// outerFunction의 실행이 끝났지만
// innerFunction은 여전히 outerVariable(10)에 접근 가능
클로저를 이해하기 위해서는 먼저 렉시컬 스코프(Lexical Scope)에 대해 알아야 한다.
const globalVar = "전역";
function outerFunction() {
const outerVar = "외부";
function middleFunction() {
const middleVar = "중간";
function innerFunction() {
const innerVar = "내부";
// 모든 상위 스코프의 변수에 접근 가능
console.log(innerVar); // "내부"
console.log(middleVar); // "중간"
console.log(outerVar); // "외부"
console.log(globalVar); // "전역"
}
return innerFunction;
}
return middleFunction;
}
const closure = outerFunction()();
closure(); // 모든 변수에 접근 가능
■ 클로저의 동작 원리
1. 실행 컨텍스트와 스코프 체인
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(counter2()); // 1 (독립적인 클로저)
console.log(counter1()); // 3
2. 메모리에서 일어나는 일
// 1. createCounter 호출
function createCounter() {
let count = 0; // 이 변수는 일반적으로 함수 종료 시 사라져야 함
// 2. 익명 함수 반환 (이 함수가 count를 참조)
return function() {
count++;
return count;
};
} // 3. createCounter 실행 종료, 하지만 count는 사라지지 않음!
// 4. 반환된 함수가 count를 참조하고 있어서 가비지 컬렉션되지 않음
const counter = createCounter();
■ 활용
1. 데이터 은닉
function createBankAccount(initialBalance) {
let balance = initialBalance; // private 변수
return {
// public 메서드들
deposit: function(amount) {
if (amount > 0) {
balance += amount;
return balance;
}
throw new Error("입금액은 0보다 커야 합니다.");
},
withdraw: function(amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
return balance;
}
throw new Error("출금할 수 없습니다.");
},
getBalance: function() {
return balance;
}
// balance에 직접 접근할 방법이 없음
};
}
const account = createBankAccount(1000);
console.log(account.getBalance()); // 1000
account.deposit(500); // 1500
account.withdraw(200); // 1300
// balance에 직접 접근 불가
console.log(account.balance); // undefined
account.balance = 999999; // 외부에서 조작 불가
console.log(account.getBalance()); // 여전히 1300
2. 함수 팩토리
function createMultiplier(multiplier) {
return function(number) {
return number * multiplier;
};
}
const double = createMultiplier(2);
const triple = createMultiplier(3);
const quadruple = createMultiplier(4);
console.log(double(5)); // 10
console.log(triple(5)); // 15
console.log(quadruple(5)); // 20
// 각 함수는 독립적인 multiplier 값을 가짐
'프론트엔드 > JS 공부' 카테고리의 다른 글
자바스크립트 this (0) | 2025.06.04 |
---|---|
프로토타입 체인 (0) | 2025.06.04 |
동기 / 비동기 (0) | 2025.05.28 |
스토리지(Storage) (0) | 2024.05.01 |
쿠키(Cookie) (0) | 2024.05.01 |
댓글