포스트

[JavaScript] 클로저(Closure)

[JavaScript] 클로저(Closure)

클로저(Closure)
“함수가 만들어질 때의 스코프(변수 환경) 를 기억해서, 함수 바깥에서 실행돼도 그 변수를 계속 접근할 수 있는 것”을 말한다.

즉, 함수 + 그 함수가 참조하는 외부 변수(렉시컬 환경) 가 함께 묶여서 살아있는 상태가 클로저다.



왜 ‘기억’이 가능한가?

자바스크립트 함수는 실행될 때마다 내부에서 필요한 변수를 찾는다.

1) 먼저 자기 스코프에서 찾고
2) 없으면 바깥(상위) 스코프로 올라가며 찾는다(스코프 체인).

이때, 함수가 바깥 변수를 참조하고 있다면, 그 바깥 변수는 가비지 컬렉션(GC) 대상이 되지 않고 유지된다.
그래서 함수가 나중에 호출돼도 그 변수를 계속 쓸 수 있다.

가비지 컬렉션(GC): 어디에서도 참조되지 않아 도달 불가능한 값을 자동으로 메모리에서 정리하는 기능



가장 기본 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function makeCounter() {
  let count = 0;

  return function () {
    count += 1;
    return count;
  };
}

const counter = makeCounter();

counter(); // 1
counter(); // 2
counter(); // 3


클로저를 쓰는 대표 이유 3가지

1) 상태(State) 캡슐화 (외부에서 직접 못 건드리게)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function createUser(name) {
  let point = 0;

  return {
    getName() {
      return name;
    },
    addPoint(v) {
      point += v;
    },
    getPoint() {
      return point;
    },
  };
}

const user = createUser("test");
user.addPoint(10);
user.getPoint(); // 10
  • point는 외부에서 직접 접근 불가, 함수로만 접근 가능
  • 안전하게 상태를 관리할 수 있다.


2) 함수 팩토리(함수 생성기)

1
2
3
4
5
6
7
8
9
10
11
function multiplyBy(n) {
  return function (x) {
    return x * n;
  };
}

const double = multiplyBy(2);
const triple = multiplyBy(3);

double(10); // 20
triple(10); // 30
  • n을 기억하는 함수들을 쉽게 만들 수 있음


3) 콜백/이벤트에서 “원래 값” 유지

1
2
3
4
5
6
7
function greetLater(name) {
  setTimeout(() => {
    console.log(`안녕, ${name}!`);
  }, 1000);
}

greetLater("test"); // 1초 뒤: "안녕, test!"
  • setTimeout은 나중에 실행되지만 콜백이 name을 기억(클로저)해서 출력 가능


클로저의 단점(주의점)

1) 메모리 유지가 길어질 수 있음

클로저가 외부 변수를 참조하면, 그 변수는 계속 살아있다.
큰 데이터를 참조하는 클로저를 오래 유지하면 메모리를 더 쓸 수 있다.

1
2
3
4
5
6
7
8
let handler = (() => {
  const big = new Array(1000000).fill("x");
  return () => big.length;
})();

handler(); // 사용

handler = null; // 더 이상 필요없으면 참조 끊기 (GC 가능해짐)


2) “값이 고정된 줄 알았는데” 같이 변하는 경우

클로저는 값을 복사하는 게 아니라 변수(참조) 를 잡는다.
그래서 바깥 변수가 바뀌면 클로저 결과도 바뀐다.

1
2
3
4
5
6
let x = 1;
const f = () => x;

f(); // 1
x = 10;
f(); // 10


마무리 정리

  • 클로저 = 함수가 바깥 스코프 변수를 “기억”하고 계속 접근 가능한 상태
  • 장점: 상태 캡슐화, 함수 생성, 콜백에서 값 유지
  • 주의: 메모리/예상 못한 참조 공유
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.