클로저(Closure)는 JavaScript의 중요한 개념 중 하나로, 함수와 함수가 선언된 어휘적 환경(Lexical Environment)을 함께 기억하는 구조이다.
클로저는 주로 함수 내부에서 정의된 또 다른 함수를 통해 외부 함수의 변수에 접근할 수 있도록 하며, 이를 통해 다양한 유용한 기능을 구현할 수 있다.
클로저의 기본 개념
클로저는 내부 함수가 외부 함수의 변수에 접근할 수 있는 메커니즘이며, 내부 함수가 외부 함수의 범위에 있는 변수를 "기억"하기 때문에 클로저가 형성된다.
function outerFunction() {
const outerVariable = "I am outside!";
function innerFunction() {
console.log(outerVariable); // "I am outside!" 출력
}
return innerFunction;
}
const myInnerFunction = outerFunction();
myInnerFunction();
이 예제에서 outerFunction은 innerFunction을 반환한다. myInnerFunction은 outerFunction의 외부 변수인 outerVariable에 접근할 수 있다.
이처럼 innerFunction이 외부 함수의 변수에 접근할 수 있는 능력을 클로저라고 한다.
클로저의 특징
클로저는 몇 가지 중요한 특징을 가지고 있다.
변수의 유지
클로저는 외부 함수가 종료된 후에도 외부 함수의 변수 값을 유지할 수 있기에, 함수가 호출되고 종료된 이후에도 해당 함수의 변수에 접근할 수 있는 방법을 제공한다.
function counter() {
let count = 0;
return function () {
count += 1;
return count;
};
}
const myCounter = counter();
console.log(myCounter()); // 1 출력
console.log(myCounter()); // 2 출력
console.log(myCounter()); // 3 출력
여기서 counter 함수는 count 변수를 포함하는 내부 함수를 반환한다. 이 반환된 함수는 count 변수에 접근할 수 있으며, count 값은 클로저에 의해 유지된다.
캡슐화
클로저는 데이터를 은닉하고 캡슐화하는 데 사용된다.
외부 함수의 변수는 외부에서 직접 접근할 수 없지만, 클로저를 통해서만 접근할 수 있으며, 이로 인해 변수를 안전하게 보호할 수 있다.
function createCounter() {
let count = 0;
return {
increment: function () {
count += 1;
return count;
},
decrement: function () {
count -= 1;
return count;
},
};
}
const counter = createCounter();
console.log(counter.increment()); // 1 출력
console.log(counter.increment()); // 2 출력
console.log(counter.decrement()); // 1 출력
createCounter 함수는 count 변수를 직접적으로 노출하지 않지만, 클로저를 통해 increment와 decrement 메서드를 통해 안전하게 접근할 수 있게 한다.
클로저의 활용
클로저는 다양한 실용적인 상황에서 사용될 수 있다.
함수의 결과를 저장
클로저를 사용하여 함수의 실행 결과를 메모이제이션(Memoization) 하여 성능을 최적화할 수 있습니다.
이벤트 핸들러
클로저는 이벤트 핸들러 내부에서 유용하다. 예를 들어, 반복문 내에서 클로저를 사용하면 각 반복마다 고유한 변수를 유지할 수 있다.
for (var i = 0; i < 3; i++) {
setTimeout(
(function (i) {
return function () {
console.log(i);
};
})(i),
1000
);
}
이 코드는 1초 후에 0, 1, 2를 출력한다. 클로저를 사용하지 않으면 모든 타이머가 동일한 변수를 참조하게 되어 반복문의 마지막 값만 출력된다.
모듈 패턴
클로저는 모듈 패턴을 구현하여 공개와 비공개 메서드를 정의하는 데 사용되며, 이는 데이터 은닉과 캡슐화를 지원한다.
const Module = (function () {
let privateVar = "I am private";
return {
publicMethod: function () {
console.log(privateVar);
},
};
})();
Module.publicMethod(); // "I am private" 출력
클로저 사용 시 주의점
메모리 관리
클로저는 변수를 유지하기 때문에 메모리 누수(memory leak)를 일으킬 수 있다. 필요하지 않은 클로저는 사용 후 제거해야 한다.
디버깅 어려움
클로저는 종종 디버깅을 어렵게 만들 수 있는데, 변수가 어느 스코프(scope)에 속하는지 헷갈릴 수 있기 때문이다.
결론
클로저는 JavaScript의 함수가 어떻게 작동하는지를 깊이 이해할 수 있게 해주는 중요한 개념이기에, 클로저를 사용하면 변수와 함수를 더 유연하고 강력하게 관리할 수 있다.
클로저의 특성과 활용법을 잘 이해하면, 더 나은 JavaScript 코드를 작성할 수 있다.
'Develope > Javascript' 카테고리의 다른 글
JavaScript 호이스팅(Hoisting) (0) | 2024.08.29 |
---|---|
CommonJS(CJS)와 ESModules(ESM) (0) | 2024.08.27 |
Javascript에서의 this (0) | 2024.08.27 |
자바스크립트에서의 커링(Currying) (0) | 2024.08.26 |
자바스크립트 비동기 처리: Callback, Promise, Async/Await 그리고 Yield (0) | 2024.08.26 |