클로저(Closure)란?
클로저(Closure) 는 함수가 자신이 선언된 환경(Lexical Scope)의 변수를 기억하고, 해당 스코프 바깥에서도 계속 접근할 수 있는 개념
✅ 클로저의 핵심 개념
- 내부 함수(Inner Function)가 외부 함수(Outer Function)의 변수에 접근할 수 있음
- 외부 함수가 실행을 마친 후에도 내부 함수가 외부 변수 값을 유지함
- 데이터를 은닉(Encapsulation)하고 유지하는 데 유용
1. 기본적인 클로저 예제
function outer() {
let count = 0; // 외부 함수의 변수 (내부 함수가 접근 가능)
return function inner() { // 내부 함수 (클로저)
count++; // 외부 함수의 변수 사용
console.log(`현재 count 값: ${count}`);
};
}
const counter = outer(); // outer() 실행 후, inner 함수가 반환됨
counter(); // "현재 count 값: 1"
counter(); // "현재 count 값: 2"
counter(); // "현재 count 값: 3"
📌 여기서 inner 함수는 count 변수를 기억하며 계속 사용할 수 있음.
📌 outer() 함수는 실행이 끝났지만, 내부 함수 inner()는 클로저로 인해 count 변수에 접근 가능.
2. 클로저를 활용한 데이터 은닉
클로저를 사용하면 객체의 속성을 직접 변경하지 못하도록 보호(Encapsulation)할 수 있음.
function createCounter() {
let count = 0; // 외부에서 접근할 수 없는 private 변수
return {
increment: function () {
count++;
console.log(`Count: ${count}`);
},
decrement: function () {
count--;
console.log(`Count: ${count}`);
},
getCount: function () {
return count;
}
};
}
const counter = createCounter();
counter.increment(); // "Count: 1"
counter.increment(); // "Count: 2"
console.log(counter.getCount()); // 2
console.log(counter.count); // undefined (직접 접근 불가)
📌 count 변수는 createCounter() 내부에서 선언되었기 때문에 외부에서 직접 접근할 수 없음.
📌 대신, increment(), decrement(), getCount() 메서드를 통해서만 값을 조작할 수 있음.
3. 클로저를 활용한 이벤트 핸들러 예제
클로저는 이벤트 리스너에서 상태를 유지하는 데 유용함.
function createButtonCounter(button) {
let count = 0;
button.addEventListener("click", function () {
count++;
console.log(`버튼 클릭 횟수: ${count}`);
});
}
const button = document.querySelector("button");
createButtonCounter(button);
📌 count 변수는 외부에서 직접 변경할 수 없고, 클릭할 때마다 클로저가 값 유지.
4. 클로저의 메모리 관리 주의점
클로저를 사용할 때 불필요한 메모리 점유를 피해야 함.
특히 큰 객체를 클로저 내부에서 계속 참조하면 가비지 컬렉션이 불가능하여 메모리 누수가 발생할 수 있음.
❌ 잘못된 예제 (메모리 누수 발생)
function createBigObject() {
let bigData = new Array(1000000).fill("🚀"); // 큰 배열
return function() {
console.log(bigData[0]); // 클로저가 bigData를 계속 참조
};
}
const myClosure = createBigObject();
// myClosure는 bigData를 계속 참조 -> 메모리 해제되지 않음
✅ 해결 방법 (bigData를 필요 없을 때 삭제)
function createSafeBigObject() {
let bigData = new Array(1000000).fill("🚀");
return function() {
console.log(bigData[0]);
bigData = null; // 필요 없으면 참조 해제
};
}
const safeClosure = createSafeBigObject();
safeClosure(); // 사용 후 bigData 메모리 해제
📌 클로저 사용 후, 필요 없는 데이터를 null로 설정하여 참조를 해제하면 메모리 누수를 방지할 수 있음.
🎯 정리
✅ 클로저(Closure)란?
- 함수가 자신이 선언된 환경의 변수를 기억하고 바깥에서도 접근할 수 있는 개념
- 데이터 은닉(Encapsulation) 및 상태 유지에 활용됨
✅ 클로저 활용 예시
1️⃣ 상태 유지 (counter() 예제)
2️⃣ 데이터 은닉 (객체처럼 활용 가능)
3️⃣ 이벤트 리스너에서 상태 관리
4️⃣ 비동기 처리 및 setTimeout 활용
✅ 주의할 점
- 클로저를 잘못 사용하면 메모리 누수가 발생할 수 있음
- 필요 없는 데이터는 참조를 해제하여 메모리 최적화 필요
📌 클로저는 JavaScript에서 강력한 기능이지만, 올바르게 사용해야 성능과 유지보수성이 좋아짐! 🚀