프론트엔드 면접 질문 리스트에 빠지지 않는 중요도 ⭐️x5개인 질문이지만, 내용을 읽어봐도 항상 헷갈리는 개념입니다.
아래에서 차근차근 살펴보겠습니다.
🪴 정의
클로저(Closure)란, 외부 함수에 선언된 변수에 접근할 수 있는 내부 함수를 의미합니다.
이 내부 함수는 자신이 선언될 때의 환경(스코프)을 기억하고 있어서, 외부 함수가 종료된 이후에도 외부 변수에 접근할 수 있는 특징이 있습니다.
이러한 특징을 가진 클로저는 함수가 변수를 기억하는 기능을 하기 때문에 데이터를 은닉하거나 상태를 유지해야 하는 경우에 사용됩니다.
보통 '외부 변수에 접근할 수 있는 내부 함수'를 클로저라고 하며,
좀 더 넓은 의미로 이러한 함수와 외부 변수에 접근할 수 있는 현상 전체를 클로저라고 부르기도 합니다.
🪴 예시 코드
예를 들어, 아래의 코드에서는 내부 함수인 inner가 외부 함수 outer의 변수(지역 변수)인 counter에 접근할 수 있습니다.
function outer() {
let count = 0;
return function inner() {
count++;
console.log(count);
};
}
const counter = outer();
counter(); // 1 출력
counter(); // 2 출력
아래에서 코드를 자세히 살펴보겠습니다.
🪴 코드 설명
1) outer 함수 호출
const counter = outer();
/**
function outer() {
let count = 0;
return function inner() {...};
}
**/
- outer 함수가 실행되면 내부에서 count라는 지역 변수가 선언되고 0으로 초기화됩니다.
- 함수의 실행이 끝나면 내부 함수인 inner 함수를 리턴합니다.
- 이때 리턴되는 inner 함수는 단순히 함수의 정의만 리턴되는 것이 아니라, count가 선언될 때의 환경(스코프)도 함께 기억한 상태로 리턴됩니다.
- 그리고 리턴된 내부 함수(inner 함수)는 counter라는 이름으로 저장됩니다.
2) 첫 번째 counter 함수 호출
counter(); // 1 출력
/**
function inner() {
count++;
console.log(count);
}
**/
- counter 함수 호출하면 inner 함수가 실행됩니다.
- inner 함수는 count++를 실행하고, count 변수의 값은 1이 됩니다.
- 이후 console.log(count)가 실행되어 1이 출력됩니다.
이때 count는 outer 함수의 지역 변수지만, inner 함수는 outer 함수의 실행이 끝나도 여전히 count에 접근할 수 있습니다.
이렇게 '외부 함수의 지역 변수에 접근할 수 있는 내부 함수'를 클로저라고 하며, 내부 함수가 외부 환경(스코프)을 기억하고 있는 현상이 클로저의 동작 원리입니다.
3) 두 번째 counter 함수 호출
counter(); // 2 출력
/**
function inner() {
count++;
console.log(count);
}
**/
- 2번 코드 설명과 마찬가지로 counter 함수 호출하면 inner 함수가 실행됩니다.
- 그러나 이때 count 변수는 여전히 살아있고, 새롭게 선언되지 않습니다.
- 따라서 inner 함수는 count++를 실행하고, count 변수의 값은 2가 됩니다.
- 이후 console.log(count)가 실행되어 2가 출력됩니다.
🪴 정리
예시 코드에서 살펴보았듯이, outer 함수의 실행은 끝났지만 내부 함수인 inner 함수가 count를 참조하고 있기 때문에 자바 스크립트는 count가 선언된 환경(스코프)을 메모리에서 제거하지 않습니다.
이처럼 외부 함수의 지역 변수를 기억하는 내부 함수가 바로 클로저입니다.
클로저는 값을 계속 기억할 수 있는 특성을 활용해 상태 유지, 카운터 구현, 데이터 은닉 등의 상황에 자주 사용됩니다.
읽어주셔서 감사합니다:)