[Javascript] 클로저(Closure)

SNXWXH·2025년 3월 21일

Javascript

목록 보기
13/13
post-thumbnail

클로저란?

📍 MDN 정의
A clousre is the combination of a function and thee lexical environment within which that function was declared

📍 내 정의
상위 스코프의 식별자를 참조하는 하위 스코프가 외부에서 지속적으로 참조되어 상위 스코프보다 더 오래 살아있는 것

  • 클로저(Closure)는 함수와 그 함수가 선언된 렉시컬 환경(Lexical Environment)의 조합

  • 상위(부모) 스코프의 식별자를 하위 스코프가 지속적으로 참조

    ⇒ 하위 스코프가 살아있는 한 상위 스코프는 죽을 수 없음

    ⇒ 따지자면 하위 스코프가 더 오래 사는 것

클로저의 특징

  • 내부 함수가 외부 함수의 변수를 기억
  • 외부 함수 실행이 끝난 후에도 변수를 유지 가능
  • 자바스크립트에서 상태를 안전하게 저장하는 방법으로 사용

클로저의 예제

function outer() {
  let count = 0; // 외부 함수의 변수

  return function inner() {
    count++; // 내부 함수에서 외부 변수 접근
    console.log(count);
  };
}

const closureFunc = outer(); // outer 실행 후 반환된 inner 함수 저장

closureFunc(); // 1
closureFunc(); // 2
closureFunc(); // 3

클로저의 동작 방식

  1. outer 실행 → count 변수를 포함한 실행 컨텍스트 생성
  2. inner 함수가 반환되면서 outer 실행 컨텍스트는 사라짐
  3. 하지만 closureFuncinner를 참조하고 있으므로 count 변수가 사라지지 않음
  4. closureFunc 실행 시마다 count 값이 유지되며 증가

클로저의 활용

데이터 보호 (정보 은닉)

  • 클로저를 사용하면 외부에서 직접 변수에 접근하는 것을 막을 수 있음
function createCounter() {
  let count = 0; // 외부에서 접근 불가능

  return {
    increase() {
      count++;
      console.log(count);
    },
    decrease() {
      count--;
      console.log(count);
    },
    getCount() {
      return count;
    }
  };
}

const counter = createCounter();
counter.increase(); // 1
counter.increase(); // 2
console.log(counter.getCount()); // 2
counter.count = 100; // 직접 변경 불가능
console.log(counter.getCount()); // 2
  • count 변수는 외부에서 직접 접근할 수 없으며, increase, decrease, getCount 메서드를 통해서만 조작 가능

이벤트 핸들러에서의 사용

  • 클로저는 이벤트 리스너에서 이전 상태를 유지하는 데 사용할 수 있음
function makeClickCounter() {
  let count = 0;

  return function () {
    count++;
    console.log(`버튼 클릭 횟수: ${count}`);
  };
}

const button = document.querySelector("#myButton");
const clickHandler = makeClickCounter();
button.addEventListener("click", clickHandler);
  • 버튼을 클릭할 때마다 count 값이 유지

setTimeout과 함께 사용

  • 클로저를 이용하면 비동기 코드에서도 변수의 상태를 유지할 수 있음
  • setTimeout의 콜백 함수는 실행될 때 message 변수를 기억하고 있음
function delayedMessage(message, delay) {
  setTimeout(function () {
    console.log(message);
  }, delay);
}

delayedMessage("3초 후 실행", 3000);

클로저가 발생하는 조건

  1. 함수 내부에 또 다른 함수가 정의되어야 함
  2. 내부 함수가 외부 함수의 변수를 참조해야 함
  3. 내부 함수가 외부 함수의 실행이 끝난 후에도 유지되어야 함

클로저의 주의점

메모리 누수

  • 클로저를 과도하게 사용하면 참조가 계속 유지되어 메모리가 해제되지 않는 문제가 발생할 수 있음
function outer() {
  let data = new Array(1000000).fill("데이터");

  return function () {
    console.log(data[0]);
  };
}

const leak = outer(); // 클로저가 데이터를 계속 유지하여 메모리 누수 발생 가능
  • 필요하지 않은 클로저는 null로 설정하여 해제하는 것이 좋음
let closureFunc = outer();
closureFunc = null; // 참조를 해제하여 메모리 정리
profile
세상은 호락호락하지 않다. 괜찮다. 나도 호락호락하지 않으니까.

0개의 댓글