[Javascript] 클로저(Closure)

SungWoo·2024년 10월 27일

자바스크립트 공부

목록 보기
15/42
post-thumbnail

클로저는 자바스크립트에서 난해하기로 유명한 개념들 중 하나이다. 이전에 학습했던 실행 컨텍스트에 대한 지식과 함께 클로저에 대해 정리해보자.

클로저(Closure)

클로저는 함수와 그 함수가 선언된 렉시컬 환경과의 조합이다.

function outerFunction() {
  let outerVariable = 'I am outside!';

  function innerFunction() {
    console.log(outerVariable); // outerVariable에 접근할 수 있음
  }

  return innerFunction;
}

const myClosure = outerFunction();
myClosure(); // 'I am outside!'

위 코드에서, innerFunctionouterVariable을 사용할 수 있는데, 이는 innerFunctionouterVariable이 선언된 스코프를 기억하고 있기 때문이다. 즉, outerFunction이 실행을 마치고 끝났더라도, innerFunction이 반환되어 나가면 여전히 outerVariable에 접근할 수 있다.

이처럼 외부 함수보다 중첩 함수가 더 오래 유지되는 경우 중첩 함수는 이미 생명 주기가 종료한 외부 함수의 변수를 참조할 수 있다. 이러한 중첩 함수를 클로저(Closure)라고 부른다.

즉, 클로저는 내부 함수가 외부 함수의 변수에 접근할 수 있게 해주는 메커니즘이다. 외부 함수는 실행이 끝났지만 내부 함수는 여전히 외부 함수의 변수를 기억하고 사용할 수 있다.

클로저는 중첩 함수가 상위 스코프의 식별자를 참조하고 있고 중첩 함수가 외부 함수보다 더 오래 유지되는 경우에 한정하는 것이 일반적이다.

클로저의 활용

클로저는 상태가 의도치 않게 변경되지 않도록 안전하게 은닉하고 특정 함수에게만 상태 변경을 허용하여 상태를 안전하게 변경하고 유지하기 위해 사용한다.

1. 상태 유지

클로저는 상태를 안전하게 변경하고 유지하기 위해 사용한다.

function createAdder(x) {
  return function (y) {
    return x + y;
  };
}

const addFive = createAdder(5);
console.log(addFive(3)); // 8
console.log(addFive(10)); // 15

createAdder(5)는 내부의 x 값을 5로 저장한 클로저를 반환한다. 이 클로저는 x를 기억하고 있기 때문에 addFive는 나중에 y를 받아도 x와의 덧셈 연산을 수행할 수 있다.

  • 클로저는 함수가 실행을 끝낸 후에도 특정 상태를 유지하도록 할 수 있다.
  • 이를 통해 값의 상태를 저장하거나 여러 함수 호출 간에 공유할 수 있다.

2. 데이터 은닉

상태를 안전하게 은닉하고 특정 함수에게만 상태 변경을 허용하기 위해 사용한다.

function createPrivateCounter() {
  let count = 0;
  return function () {
    return ++count;
  };
}

const counter = createPrivateCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3

count 변수는 createPrivateCounter 외부에서는 접근할 수 없고, counter 함수에서만 접근이 가능하다.

  • 클로저는 외부에서 접근할 수 없는 변수를 만드는데 유용하다.
  • 클로저 내부에서만 접근이 가능한 변수를 통해 데이터 은닉을 쉽게 구현할 수 있다.

3. 비동기 프로그래밍

function delayedLogger() {
  for (let i = 1; i <= 3; i++) {
    setTimeout(function () {
      console.log(i); // 클로저로 인해 각기 다른 `i` 값을 기억함
    }, i * 1000);
  }
}

delayedLogger(); // 1초 뒤 1, 2초 뒤 2, 3초 뒤 3 출력

setTimeout 함수의 콜백함수는 각기 다른 i값을 기억한다. 만약 var 키워드를 사용했다면 모두 4로 출력되었겠지만, let 키워드를 사용함으로써 블록 스코프가 적용되고 클로저가 정확히 작동하게 된다.

  • 타이머나 비동기 호출을 다룰 때 클로저를 사용해 유효한 값을 기억할 수 있다.
profile
어제보다 더 나은

0개의 댓글