한양과학기술고등학교

에듀테크 프로젝트 대시보드

클로저 (Closure)

1클로저란?

함수는 자신이 정의된 위치의 스코프(렉시컬 스코프)를 기억합니다. 바깥 함수가 이미 실행을 끝내고 사라져도, 안쪽 함수가 그 스코프의 변수를 계속 붙잡고(캡처) 있는 현상을 클로저라고 부릅니다.

전역 스코프
makeCounterfunction
makeCounter() 실행 컨텍스트
count0 → 1 → 2 …
반환된 inner 함수
count += 1바깥 변수 참조
count는 inner 함수 안에 없음 → 스코프 체인을 따라 바깥에서 찾음
function makeCounter() { let count = 0; // 지역 변수 // inner 함수가 count를 "캡처" return function() { count += 1; return count; }; } const counterA = makeCounter(); counterA(); // 1 counterA(); // 2 ← count가 살아있음! const counterB = makeCounter(); counterB(); // 1 ← 완전히 별개의 count
핵심: makeCounter()가 끝나면 보통 지역변수는 사라지지만, 반환된 함수가 count를 참조하고 있어서 가비지 컬렉터가 회수하지 못합니다. 호출할 때마다 새 스코프가 생기므로 counterA와 counterB는 서로 다른 count를 갖습니다.

2직접 만들어보는 카운터 팩토리

아래 "카운터 추가" 버튼을 누르면 makeCounter()가 실제로 호출되어 새 클로저(=새 count 변수)가 하나 생성됩니다. 각 카운터는 독립된 메모리 박스를 갖고 있어서 서로 영향을 주지 않습니다.

3고전 문제: 반복문 안의 클로저

1초 뒤에 각각 i를 출력하는 타이머를 3개 등록합니다. var와 let의 결과가 왜 다를까요? — 실행 버튼을 눌러 확인해보세요.

var 함수 스코프 — 변수 1개 공유
for (var i = 0; i < 3; i++) { setTimeout(() => print(i), 1000); }
let 블록 스코프 — 반복마다 새 변수
for (let i = 0; i < 3; i++) { setTimeout(() => print(i), 1000); }