클로저 (Closure)
- 자신이 정의될 때의 스코프를 기억하는 함수
- 외부 함수가 종료되어도 해당 스코프 변수에 접근 가능
function outer() {
let count = 0;
return function inner() {
count++;
console.log(count);
};
}
const counter = outer();
counter(); // 1
counter(); // 2
- inner는 outer의 count 변수에 접근 가능
- 이 현상이 클로저
클로저 특징
- 종료된 함수의 변수도 참조 중이면 GC 대상 아님
- 은닉화 가능 (private 변수처럼 사용)
- 상태 유지 가능 (카운터, 메모이제이션 등)
활용 예시
function createUser(name) {
return {
sayName: function () {
console.log(name);
}
};
}
const user = createUser("Jay");
user.sayName(); // "Jay"
- name은 외부에서 접근 불가하지만, sayName으로 참조 가능
var, let, const와 클로저
1) var와 클로저
function test() {
var funcs = [];
for (var i = 0; i < 3; i++) {
funcs.push(function () {
console.log(i);
});
}
return funcs;
}
const result = test();
result[0](); // 3
result[1](); // 3
result[2](); // 3
- 모두 3 출력
- var는 함수 스코프 → i는 동일 참조
2) let과 클로저
function test() {
var funcs = [];
for (let i = 0; i < 3; i++) {
funcs.push(function () {
console.log(i);
});
}
return funcs;
}
const result = test();
result[0](); // 0
result[1](); // 1
result[2](); // 2
- let은 블록 스코프 → 매 반복마다 새로운 i 생성
3) const와 클로저
- const도 블록 스코프
- let과 유사하지만 재할당 불가
메모리 관리 측면에서의 클로저
function createCounter() {
let count = 0;
return function () {
count++;
console.log(count);
};
}
const counter = createCounter();
counter(); // 1
counter(); // 2
- count는 참조 중 → GC 대상 아님
- 상태 유지 가능하지만, 메모리 누수 주의
요약
- var: 함수 스코프 → 반복문 등에서 같은 참조 공유
- let: 블록 스코프 → 반복마다 독립된 참조
- const: let과 유사, 재할당 불가
- 클로저는 강력하지만, 불필요한 참조 제거 필요
OOP와의 비교
- 클로저는 클래스 기반 OOP의 은닉화·모듈화와 유사
- 구조는 다르지만 개념적으로 유사
방식 |
클로저 (함수 기반) |
클래스 (객체지향 기반) |
데이터 은닉 |
함수 내부 변수 |
private 속성 |
공개 인터페이스 |
반환된 함수 |
public 메서드 |
상태 유지 |
함수 스코프 |
인스턴스 멤버 |
용도 |
간단한 모듈 |
복잡한 구조 |
클로저 예시
function Counter() {
let count = 0;
return {
increment() {
count++;
},
getCount() {
return count;
}
};
}
const counter = Counter();
counter.increment();
console.log(counter.getCount()); // 1
C++ 클래스 예시
class Counter {
private:
int count;
public:
Counter() : count(0) {}
void increment() {
count++;
}
int getCount() const {
return count;
}
};
결론
- 자바스크립트는 클래스 없이도 객체지향 설계 가능
- 함수를 일급 객체로 다뤄 유사한 역할 수행
자바스크립트에도 클래스 문법이 있는데 왜 클로저를 쓰는지?
- 함수형 스타일에 적합
- 은닉 및 보안 처리에 유리
- 가볍고 빠르게 객체 구성 가능
- 귀찮아서