코어 자바스크립트 - 클로저

이상호·2025년 5월 21일

**클로저란?

"함수와 그 함수가 선언될 당시의 렉시컬 환경(Lexical Environment)의 조합"**을 말한다.

"함수가 생성될 때의 외부 변수 상태(환경)를 함께 기억하고 있는 함수" 라고 이해하면 된다.

function outer() {
  let a = 1;
  return function inner() {
    return ++a;
  };
}

const fn = outer();
console.log(fn()); // 2
console.log(fn()); // 3
  1. 전역 실행 컨텍스트 생성.

  2. outer 실행 컨텍스트 생성.
    outer 실행 컨텍스트에는 LexicalEnvironment가 있고, 그 안에는 EnvironmentRecord와 outerEnvironmentReference가 존재한다.
    EnvironmentRecord에는 a = 1, inner: f가 담긴다.
    outerEnvironmentReference에는 전역 실행 컨텍스트의 LexicalEnvironment가 담긴다. 여기에는 outer: f가 담겨져있다.

  3. inner 실행 컨텍스트 생성.
    inner 실행 컨텍스트에는 LexicalEnvironment가 있고, 그 안에는 EnvironmentRecord와 outerEnvironmentReference가 존재한다. EnvironmentRecord에는 아무 값도 존재하지 않는다.
    outerEnvironmentReference에는 outer 실행 컨텍스트의 LexicalEnvironment를 참조한다. 여기에는 a = 1, inner: f가 담겨져있다.

  4. inner 실행 컨텍스트 제거.

  5. outer 실행 컨텍스트 제거.

  6. 전역 실행 컨텍스트 제거.

이 예제에서 outer()는 종료됐지만, 내부 함수 inner는 a를 계속 참조하고 있다.
이렇게 함수 종료 이후에도 변수 상태를 '기억'하고 있는 현상이 바로 클로저이다.

클로저가 중요한 이유

함수 실행 이후에도 변수 값을 유지할 수 있다
→ 일종의 데이터 저장소 역할

외부에서 내부 변수에 접근할 수 없게 만든다
→ 캡슐화, 정보 은닉 가능

함수를 반환하거나, 콜백으로 넘기는 구조에서 자주 사용된다
→ 특히 비동기 프로그래밍이나 이벤트 핸들링에서 강력함

클로저가 발생하는 조건

  • 함수 내부에서 내부 함수가 선언되고,

  • 그 내부 함수가 외부 함수의 지역 변수를 참조하며,

  • 그 내부 함수가 외부로 반환되거나 나중에 사용될 때

    👉 즉, "내부 함수가 외부 변수에 접근하면서, 생명 주기를 늘릴 때" 클로저가 발생한다.

클로저의 예시.

function user(_name) {
  var _logged = true;
  
  return {
    get name() {return _name },
    set name(v) { _name = v },
    login() { _logged = true },
    logout() { _logged = false },
    get status() {
        return _logged ? 'login' : logout;
    },
  }
};

var roy = user('상호');
console.log(roy.name); 

출력결과 : '상호'
name 프로퍼티가 없지만, get name() {...}이 호출된다.
user('상호')의 user(_name) -> _name은 user 함수 내부에서 선언된 변수. 원래대로면 user 함수의 실행 컨텍스트가 종료되면서 같이 사라져야하지만. return 키워드롤 사용하여 해당 변수가 외부로 빠져나가기 때문에 변수는 사라지지않고 살아남게된다.

roy.name = '상우';
console.log(roy.name);

출력결과 : '상우'
name 프로퍼티가 없지만, set name(v) {...}이 호출된다.

roy._name = '상우';
console.log(roy.name);

출력결과 : '상호'
_name은 user 함수에서 생성되는 프로퍼티이지 user 함수로 인해 생성된 roy의 프로퍼티가 아니다. 따라서 roy 내부에 _name 변수가 새롭게 생성될 뿐이다.

console.log(roy.status);

출력결과 : true
user 함수 내부의 _logged 변수에 따라 결과값을 가져온다. _logged 변수도 마찬가지로 사라지지않고 살아남는 변수가 되는 것이다.

roy.logout();
roy.status = true;
console.log(roy.status);

출력결과 : false
status에는 setter가 없으므로 true 할당 명령은 무시된다. 외부에서 내부 변수에 접근하기 위한 방법이 제한된다는 것. 이를 캡슐화라고 한다.

클로저의 구조

함수가 호출되면 실행 컨텍스트가 생김

이 컨텍스트 안에는 LexicalEnvironment가 있음

내부 함수가 외부 변수에 접근하면 → 참조가 생김

이 참조가 남아있으면 실행 컨텍스트가 제거되지 않음

→ 변수는 계속 살아남음 → 클로저

요약

클로저: 함수 + 외부 변수 참조 환경
목적: 변수 은닉, 캡슐화, 상태 저장
발생 조건: 내부 함수가 외부 변수를 참조하면서 반환됨
장점: 상태 유지, 정보 보호
주의점: 메모리 누수 가능성 (참조가 계속 남을 경우)

profile
안녕하십니까

0개의 댓글