[JavaScript] 클로저(Closure)

hatoba29·2022년 2월 22일
0

클로저는 프론트엔드 기술면접을 준비하다 보면 단골로 등장하는 주제다. 그만큼 중요하기도 하지만 헷갈리기도 한다.
MDN Web Docs에선 다음과 같이 정의하고 있다.

A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function's scope from an inner function. In JavaScript, closures are created every time a function is created, at function creation time.
클로저는 함수와 그 주위의 상태(어휘적 환경)의 조합이다. 다시 말해, 클로저는 내부 함수에서 외부 함수의 스코프에 접근할 수 있게 한다. 자바스크립트에서 클로저는 함수가 만들어질 때마다 함수 생성 시점에 생성된다.

간단하게 말해서 함수가 자신이 생성된 당시의 어휘적 환경(Lexical Scope)을 기억하고 있는 것이다. 이 때, 어휘적 환경에 자신의 스코프뿐만 아니라 외부 함수의 스코프도 포함되는데, 이에 따라서 자연스럽게 외부 함수의 변수에도 접근할 수 있게 되는 것이다.

클로저는 주로 프라이빗 메소드를 흉내내기 위해 사용한다. 아래의 예제를 보자.

const counter = (() => {
  let privateCounter = 0;
  const changeBy = (val) => {
    privateCounter += val;
  };

  return {
    increment: () => {
      changeBy(1);
    },

    decrement: () => {
      changeBy(-1);
    },

    value: () => {
      return privateCounter;
    },
  };
})();

console.log(counter.value()); // 0.

counter.increment();
counter.increment();
console.log(counter.value()); // 2.

counter.decrement();
console.log(counter.value()); // 1.

counter 함수 안의 privateCounter과 changeBy는 반환된 함수들로만 접근할 수 있어 private member처럼 작동하게 된다. 반환된 함수들은 public method처럼 작동하게 된다.

여기서 코드를 조금 바꿔보자.

const makeCounter = () => {
  let privateCounter = 0;
  const changeBy = (val) => {
    privateCounter += val;
  };

  return {
    increment: () => {
      changeBy(1);
    },

    decrement: () => {
      changeBy(-1);
    },

    value: () => {
      return privateCounter;
    },
  };
};

const counter1 = makeCounter();
const counter2 = makeCounter();

console.log(counter1.value()); // 0.

counter1.increment();
counter1.increment();
console.log(counter1.value()); // 2.

counter1.decrement();
console.log(counter1.value()); // 1.
console.log(counter2.value()); // 0.

같은 makeCounter를 이용해서 counter1과 counter2를 만들었다. 하지만 counter1의 public method를 이용해 privateCounter를 변경해도 counter2의 privateCounter는 변하지 않는다. 이것을 통해 위에서 이야기한 '자신이 생성된 당시의 어휘적 환경'을 기억한다는 것이 어떤 의미인지 알 수 있다.


참고문헌
MDN Web Docs - Closures

profile
프론트엔드 개발과 UX 디자인에 관심이 많습니다.

0개의 댓글

관련 채용 정보