1. 문제: "누가 내 카운터를 바꿨을까?"
자바스크립트로 클릭 횟수를 세는 기능을 만들 때, 가장 쉬운 방법은 전역 변수를 쓰는 것입니다.
let count = 0; // 전역 변수: 누구나 접근 가능
function click() {
count++;
}
하지만 이 코드는 치명적인 단점이 있습니다. 어디서든 count에 접근할 수 있다는 점입니다. 다른 개발자가 실수로 count = 999라고 코드를 짜거나, 변수명이 겹치면 프로그램 전체가 꼬이게 됩니다.
"변수를 함수 안에 숨기면서도, 그 값을 계속 기억하게 할 순 없을까?" 이 고민을 해결해 주는 것이 바로 **클로저(Closure)**입니다.
2. 해결: 클로저(Closure)라는 금고
클로저는 **"이미 생명주기가 끝난 외부 함수의 변수를 참조하는 내부 함수"**를 말합니다. 쉽게 말해, 함수가 종료되어도 자신이 사용하던 변수(환경)를 '배낭'처럼 메고 다니는 것입니다.
[클로저를 적용한 코드]
function createCounter() {
let count = 0; // 은닉된 변수 (외부에서 접근 불가)
return function() {
// count 변수는 이 내부 함수만 접근할 수 있음 (클로저)
count += 1;
return count;
};
}
const myCounter = createCounter();
이제 count 변수는 createCounter 함수 내부의 '비밀 금고'에 들어갔습니다. 오직 myCounter()를 통해서만 값을 증가시킬 수 있고, 외부에서 강제로 수정하는 것은 불가능해졌습니다. 이것이 바로 **캡슐화(Encapsulation)**입니다.
3. 트러블슈팅: count++ vs ++count
구현 과정에서 예상치 못한 버그를 만났습니다. 초기값이 0인데 첫 호출 결과가 1이 아니라 0이 나온 것입니다.
[Before: 버그 발생 코드]
return function() {
return count++; // 문제 발생: 값을 반환한 '후'에 1을 더함 (후위 연산)
};
- 결과: 0 → 1 → 2
[After: 개선된 코드]
return function() {
count += 1; // 1. 값을 먼저 올리고
return count; // 2. 반환한다 (명확한 의도)
};
- 결과: 1 → 2 → 3
단순히 ++ 위치를 바꾸는 것보다, **"동작을 명확히 나누는 코드"**가 가독성이 좋고 실수를 줄여준다는 현업 팁을 얻었습니다.
4. 결론 (Insight)
클로저는 단순히 면접용 암기 단어가 아닙니다. **"상태(State)를 안전하게 유지관리(Maintenance)"**하기 위한 필수 기술입니다. 리액트(React)의 useState 훅도 내부적으로는 이 클로저 원리로 동작한다는 사실을 깨달았습니다.
'목표 : 풀스택 개발자' 카테고리의 다른 글
| 6일차 스택(Stack)과 힙(Heap): 리액트가 화면을 안 그리는 진짜 이유 (1) | 2025.11.27 |
|---|---|
| 5일차 클로저 실전 응용 2가지 (0) | 2025.11.26 |
| 3일차 호이스팅과 TDZ: 자바스크립트는 왜 내 변수를 숨겼을까? (feat. Call Stack) (0) | 2025.11.24 |
| 2일차 터미널(CLI) 정복 (Mouse-less) (0) | 2025.11.24 |
| 1일차 컴퓨터 구조와 데이터 (0) | 2025.11.24 |