자바스크립트에서 클로저(Closure)는 매우 중요한 개념 중 하나로, 함수와 함수가 선언된 어휘적 환경(Lexical Environment) 사이의 조합을 의미합니다. 클로저는 자바스크립트의 강력한 기능 중 하나로, 주로 함수 내부에서 정의된 변수를 외부에서 접근하거나 유지하고 싶을 때 사용됩니다.
이 글에서는 자바스크립트 클로저의 개념을 깊이 있게 설명하고, 실제 사용 예제를 통해 클로저가 어떻게 작동하는지 살펴보겠습니다.
클로저란 무엇인가?
클로저는 함수가 자신이 선언된 환경(scope)의 변수들을 기억하고, 그 환경에 접근할 수 있게 해주는 기능입니다. 즉, 클로저를 사용하면 함수가 자신이 생성될 때의 환경(스코프)을 "기억"하여, 함수가 생성된 이후에도 그 환경에 접근할 수 있습니다.
클로저의 기본 예제
function outerFunction() {
let outerVariable = 'I am outside!';
function innerFunction() {
console.log(outerVariable);
}
return innerFunction;
}
const myClosure = outerFunction();
myClosure(); // "I am outside!"
위의 예제에서 innerFunction은 outerFunction 내부에 정의된 함수입니다. outerFunction이 실행되고 종료된 이후에도 innerFunction은 outerVariable에 접근할 수 있습니다. 이는 innerFunction이 outerFunction의 환경을 기억하고 있기 때문이며, 이 현상이 바로 클로저입니다.
클로저의 실제 활용 예제
클로저는 특정 데이터의 은닉화 및 유지가 필요할 때 자주 사용됩니다. 예를 들어, 다음과 같은 예제는 클로저를 활용하여 카운터를 구현합니다.
클로저를 활용한 카운터 예제
function createCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
이 예제에서는 createCounter 함수가 호출될 때마다 count 변수를 초기화하고, 내부 함수를 반환합니다. 반환된 함수는 count를 증가시키고 그 값을 반환하는 역할을 합니다. 중요한 점은 count 변수가 createCounter 함수 외부에서 접근할 수 없고, 오직 클로저 내부에서만 유지된다는 점입니다.
클로저와 함수의 스코프
클로저는 자바스크립트의 스코프 체인과 밀접한 관련이 있습니다. 함수가 선언된 위치에 따라 그 함수의 스코프가 결정되며, 클로저는 이 스코프 체인을 기억하여 언제든지 접근할 수 있게 합니다.
스코프 체인과 클로저 예제
function outerFunction() {
let outerVariable = 'Outer';
function innerFunction() {
let innerVariable = 'Inner';
console.log(outerVariable); // "Outer"
console.log(innerVariable); // "Inner"
}
return innerFunction;
}
const closureFunc = outerFunction();
closureFunc();
위의 예제에서 innerFunction은 outerFunction 내부에 정의되어 있어, outerFunction의 변수 outerVariable에 접근할 수 있습니다. 반대로 outerFunction은 innerFunction의 변수에 접근할 수 없습니다. 이와 같은 스코프 체인과 클로저의 특성을 이해하면, 자바스크립트 함수가 어떻게 동작하는지를 더 깊이 있게 이해할 수 있습니다.
클로저의 메모리 관리
클로저는 함수가 더 이상 필요하지 않을 때에도 스코프 체인을 유지하기 때문에, 클로저를 사용할 때는 메모리 관리에 신경 써야 합니다. 잘못된 클로저 사용은 메모리 누수를 일으킬 수 있습니다.
메모리 관리에 대한 주의사항
function outerFunction() {
let largeArray = new Array(1000000).fill('Hello');
return function() {
console.log(largeArray[0]);
};
}
const closureFunc = outerFunction();
closureFunc(); // "Hello"
// largeArray는 여전히 메모리에 남아있음
위의 예제에서 largeArray는 클로저에 의해 메모리에 계속 유지됩니다. 만약 이러한 클로저가 많은 데이터에 접근하거나 오랜 시간 동안 유지된다면, 메모리 누수가 발생할 수 있습니다. 따라서 클로저를 사용할 때는 필요한 변수만 유지하고, 불필요한 데이터는 가능한 빨리 메모리에서 해제하는 것이 중요합니다.
클로저의 실전 활용
클로저는 다양한 상황에서 유용하게 활용될 수 있습니다. 예를 들어, 이벤트 핸들러나 비동기 작업에서 클로저를 사용하여 외부 변수에 접근하거나, 특정 데이터를 보호하는 데 사용할 수 있습니다.
이벤트 핸들러에서의 클로저 예제
function setupEventHandler() {
let message = 'Event triggered!';
document.getElementById('myButton').addEventListener('click', function() {
alert(message);
});
}
setupEventHandler();
위의 예제에서 message 변수는 setupEventHandler 함수가 종료된 후에도 click 이벤트 핸들러 내부에서 접근 가능합니다. 이는 클로저 덕분이며, 클로저를 통해 특정 데이터를 보호하면서도 이벤트 핸들러에서 사용할 수 있게 됩니다.
결론
자바스크립트에서 클로저는 함수와 그 함수가 선언된 환경 간의 관계를 활용하여 스코프 체인을 기억하고, 외부 함수의 변수에 접근할 수 있는 강력한 기능입니다. 클로저를 이해하고 적절하게 사용하면, 더 구조적이고 안전한 코드를 작성할 수 있습니다. 클로저는 특히 데이터 은닉화, 함수형 프로그래밍, 이벤트 핸들링 등의 상황에서 매우 유용하게 사용됩니다.
'JS > JavaScript' 카테고리의 다른 글
#22 자바스크립트 Promise (0) | 2024.09.05 |
---|---|
#21 자바스크립트 비동기 처리: setTimeout과 setInterval (0) | 2024.09.05 |
#20 자바스크립트 이벤트 루프(Event Loop): 콜 스택, 이벤트 큐, 태스크 큐 (0) | 2024.09.04 |
#19 자바스크립트 클로저 활용 예시 : 즉시 실행 함수(IIFE)와 모듈 패턴 (0) | 2024.09.03 |
#17 자바스크립트 프로토타입 상속 (0) | 2024.08.31 |
#16 자바스크립트 프로토타입 체인 (0) | 2024.08.31 |
#15 자바스크립트 이벤트 (0) | 2024.08.31 |
#14 자바스크립트 DOM 조작하기 (0) | 2024.08.31 |