클로저

이재민·2025년 6월 23일

자바스크립트

목록 보기
21/23

클로저는 함수가 선언될 때의 스코프를 기억하여, 함수가 생성된 이후에도 그 스코프에 접근할 수 있는 기능을 말한다.

클로저는 자바스크립트의 함수가 일급 객체라는 특성과 렉시컬 스코프의 조합으로 만들어 진다.

예시 코드

function makeCounter() {
  let count = 0; // 🔐 프라이빗 변수
  return function () {
    return ++count;
  };
}

const counter = makeCounter();
console.log(counter()); // 1
console.log(counter()); // 2
  • makeCounter() 실행 → 내부 변수 count가 생성
  • 내부에서 익명 함수를 반환 ⇒ 반환된 함수는 count가 있는 렉시컬 환경을 기억
  • 이후 counter() 호출 시마다 count를 증가시키며 상태 유지

클로저가 필요한 이유

  1.  데이터 은닉 (Encapsulation)
function createCounter() {
  let count = 0;
  return {
    increment() { count++; return count; },
    decrement() { count--; return count; },
  }
}

const counter = createCounter();
console.log(counter.increment()); // 1
console.log(counter.increment()); // 2

이 예시에서는 외부에서 count에 직접 접근하거나 변경할 수 없다. createCounter 내부에서만 접근 가능한 count는 클로저 덕분에 유지된다.

이로 인해 중요한 상태를 외부에서 직접 수정하지 못하도록 보호할 수 있다.

  1.  상태 유지 

클로저를 이용하면 함수 호출 이후에도 특정 상태를 계속 유지할 수 있다.

이는 UI 컴포넌트, 애니메이션, 이벤트 핸들러 등에 자주 사용된다.

function makeGreeting(name) {
  return function () {
    console.log(`Hi, ${name}`);
  }
}

const greetKim = makeGreeting('김철수');
greetKim(); // Hi, 김철수

함수가 실행된 이후에도 name이라는 상태를 잃지 않고 유지합니다.

  1. 모듈화를 구현하는데 사용

모듈화는 특정 기능을 캡슐화하고, 외부에 공개하고자 하는 부분만 선택적으로 노출하여 코드의 응집력을 높이고, 유지보수성을 향상시킬 수 있다. 클로저를 활용하면 필요한 함수와 데이터만 외부로 노출함으로써 모듈 패턴을 쉽게 구현할 수 있다.

React에서 클로저 사용 예

useState, useEffect, useCallback 내부

React의 훅들은 클로저를 적극적으로 사용한다.

useCallback 예시:

const MyComponent = () => {
  const [count, setCount] = useState(0);

  const handleClick = useCallback(() => {
    console.log(`현재 count: ${count}`);
  }, [count]);

  return <button onClick={handleClick}>클릭</button>;
}

이 handleClick 함수는 렌더링 시점의 count 값을 클로저로 캡처합니다. 즉, 해당 시점의 스냅샷을 기억한다.

주의점

클로저로 인해 오래된 값이 기억되는 Stale Closure 문제가 발생할 수 있다. 이를 해결하기 위해 useRefuseEffect의 dependency array를 관리한다.

예상 면접 질문

1. 클로저란 무엇인가요?

클로저는 함수가 선언될 당시의 렉시컬 스코프를 기억하여, 함수가 그 스코프 밖에서 호출되더라도 내부 변수에 접근할 수 있도록 하는 자바스크립트의 기능이다.

2. 클로저는 메모리에 어떤 영향을 주나요?

클로저는 함수가 참조하는 외부 변수들을 메모리에 유지시키기 때문에, 해당 변수가 더 이상 필요하지 않아도 참조가 남아 있다면 가비지 컬렉션(GC) 대상이 되지 않아 메모리 누수를 유발할 수 있습니다. 따라서 이벤트 핸들러, 타이머 등에서는 참조를 해제해주는 것이 중요하다.

3. 클로저를 활용한 데이터 은닉 또는 상태 유지 방법은?

클로저를 사용하면 외부에서 직접 접근할 수 없는 프라이빗 변수를 생성할 수 있다. 예를 들어, 클로저 내부에 let count = 0과 같은 상태를 유지시키고, 이 변수에 접근하는 인터페이스만 반환함으로써 상태를 은닉할 수 있다.

4. React에서 클로저가 문제를 일으키는 경우는? → stale closure

함수형 컴포넌트에서는 렌더링 시점의 상태나 props를 클로저로 캡처하기 때문에, 나중에 호출될 때 이전 값(old snapshot) 을 참조하게 되는 문제, 즉 stale closure가 발생할 수 있다. 이를 방지하기 위해 useEffect의 의존성 배열이나 함수형 업데이트(prev => ...)를 사용한다.

profile
안녕하세요

0개의 댓글