[코어 자바스크립트] 클로저

김진서·2025년 7월 29일

우아한테크코스 7기

목록 보기
51/56
post-thumbnail

Overview

  • 책 정보

    • 제목: 코어 자바스크립트
    • 저자: 정재남
    • 출판사: 위키북스
    • ISBN: 9791158391720
  • 이 글의 목적 및 대상 독자

    1. JavaScript의 클로저(Closure) 개념을 체계적으로 이해하고 싶은 분
    2. 클로저가 메모리 관리에 어떻게 영향을 주는지 알고 싶은 분
    3. 클로저를 실제 코드에서 정보 은닉, 부분 적용, 커링 등으로 활용해 보고 싶은 분

1. 클로저란?

1.1 클로저의 정의

클로저(Closure)란 함수와 그 함수가 선언된 어휘적(렉시컬) 환경을 함께 기억하는 구조를 말합니다.
즉, 함수 바깥에 선언된 변수에 접근할 수 있는 함수 객체를 “클로저”라고 부릅니다.

정의 한 줄 요약
“함수 → 자신이 선언된 환경(scope)을 기억 → 외부 변수에 접근 가능”

1.2 클로저가 동작하는 원리

  • 스코프 체인(Scope Chain)
    • 함수가 선언될 때, 그 위치의 렉시컬 환경(Lexical Environment)을 내부 슬롯 [[Environment]]에 저장합니다.
  • 실행 컨텍스트(Execution Context)
    • 함수 실행 시 생성되는 변수 객체(Variable Object)와 렉시컬 환경 참조가 스코프 체인을 통해 연결됩니다.
함수A 내부 렉시컬 환경
 └─ [[Environment]] ─> 전역 렉시컬 환경(Global)

💡 Tip
클로저는 ‘함수가 어디서 실행되었느냐’가 아니라 ‘함수가 어디서 선언되었느냐’에 따라 외부 변수를 참조합니다.


2. 클로저와 메모리 관리

2.1 클로저가 메모리에 미치는 영향

  • 클로저는 자신이 참조하는 외부 변수들을 GC 대상에서 제외시켜, 함수가 종료되어도 해당 변수들이 메모리에 유지됩니다.

2.2 가비지 컬렉션과 해제 조건

  • 참조가 사라져야 GC가 해당 변수 메모리를 회수합니다.
  • 클로저를 생성한 함수나 참조 변수를 null로 설정하면 해제가 가능해집니다.
function createCounter() {
  let count = 0;      // ▶ 클로저가 참조하는 변수
  return function() {
    return ++count;
  };
}

const counter = createCounter();
// counter 함수가 살아있는 한 count 변수는 메모리에 남음

// 해제하려면…
counter = null;      // 이제 count는 GC 대상이 됨

2.3 메모리 누수 방지 팁

  • 불필요한 클로저 참조 제거
  • 이벤트 리스너나 타이머 내 클로저 사용 시, 언마운트 단계에서 clear 또는 remove 처리
  • WeakMap, WeakSet 등을 활용해 약한 참조(Weak Reference) 사용 고려

3. 클로저 활용 사례

3.1 콜백 함수 내부에서 외부 데이터 사용

function repeat(message, times) {
  for (let i = 0; i < times; i++) {
    setTimeout(() => {
      console.log(`${i + 1}: ${message}`);  // ▶ 클로저로 i, message 참조
    }, 1000 * i);
  }
}
repeat("안녕하세요", 3);
// 1초 후: "1: 안녕하세요"
// 2초 후: "2: 안녕하세요"
// 3초 후: "3: 안녕하세요"

💡 Tip
var 대신 let/const를 쓰면 블록 스코프가 적용되어 의도한 대로 동작합니다.

3.2 접근 권한 제어(정보 은닉)

function createSecret(secretValue) {
  return {
    getSecret() {
      return secretValue;  // ▶ 외부에서는 secretValue 접근 불가
    }
  };
}

const vault = createSecret("TOP_SECRET");
console.log(vault.getSecret());  // "TOP_SECRET"
// console.log(vault.secretValue); // undefined

💡 Tip
모듈 패턴(Module Pattern)에서 자주 사용됩니다.

3.3 부분 적용 함수(Partial Application)

function add(a, b) {
  return a + b;
}

function partial(fn, fixedA) {
  return function(b) {
    return fn(fixedA, b);  // ▶ 클로저로 fixedA 참조
  };
}

const addFive = partial(add, 5);
console.log(addFive(10));  // 15

💡 Tip
Lodash의 _.partial 유틸과 개념 동일

3.4 커링 함수(Currying)

function curry(fn) {
  return function curried(...args) {
    if (args.length >= fn.length) {
      return fn(...args);
    }
    return function(...more) {
      return curried(...args, ...more);
    };
  };
}

// 사용 예
function multiply(a, b, c) {
  return a * b * c;
}

const curriedMul = curry(multiply);
console.log(curriedMul(2)(3)(4));    // 24
console.log(curriedMul(2, 3)(4));    // 24

💡 Tip
커링은 함수 조합(Function Composition)과 함께 함수형 프로그래밍에서 널리 사용됩니다.


4. 요약 및 정리

  • 클로저: 함수가 선언된 환경을 기억해, 외부 변수에 접근 가능
  • 메모리: 클로저는 참조된 변수를 GC 대상에서 제외 → 메모리 누수 주의
  • 활용
    1. 비동기 콜백에서 외부 상태 접근
    2. 정보 은닉·캡슐화
    3. 부분 적용(Partial Application)
    4. 커링(Currying)

5. 참고 문헌 및 링크

profile
PAy IT forwaRD를 실천하는 프론트엔드 개발자.

2개의 댓글

comment-user-thumbnail
2025년 8월 5일

진서님 좋은 글 잘 보고 갑니다~👍

1개의 답글