■ 클로저(Closure)란?
Closure
- 사전적 의미: “닫힘, 폐쇄, 종결”
- 프로그래밍에서는 “함수가 선언될 당시의 환경을 닫아서 보존한다”는 뜻.
즉, 함수가 선언될 당시의 외부 스코프(환경, lexical environment)를 기억하고, 그 함수가 외부 스코프 밖에서 실행되더라도 그 변수에 접근할 수 있게 해주는 기능.
// 예시 코드
function outer() {
let count = 0; // 외부 스코프 변수
function inner() {
count++;
return count;
}
return inner;
}
const counter = outer();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
작동 원리
1. outer()가 실행되면 내부에 count 변수가 생성되고, inner 함수가 만들어짐
2. outer()는 끝났지만, 반환된 inner는 자신이 선언된 스코프(outer의 환경) 을 기억함.
3. 그래서 count는 계속 살아있고, inner()를 호출할 때마다 이전 값을 기억하고 증가시킴.
>>> 즉, 함수가 “태어날 당시의 기억(환경)”을 간직하고 있는 것.
■ 스코프(Scope)란?
변수가 접근 가능한 범위를 의미
자바스크립트는 렉시컬 스코프(Lexical Scope) 를 사용. 즉, 함수가 선언된 위치에 따라 스코프가 결정.
클로저가 "외부 스코프 변수"를 기억한다는 건, 그냥 변수를 복사해오는 게 아니라 외부 스코프 자체를 통째로 기억하고 있다는 뜻.
그래서 함수가 종료된 뒤에도 외부 변수에 접근할 수 있는 것.
■ React에서 클로저가 문제가 되는 이유
React는 함수형 컴포넌트 기반으로 작동하므로 컴포넌트가 렌더링될 때마다 함수 전체가 다시 실행됨.
그런데 클로저는 “그 당시 렌더링 시점의 상태(state)”를 캡쳐해서 기억해버려서 이전 렌더링의 상태를 참조(stale 값 참조) 하는 문제가 생김. 그래서 useEffect이나 이벤트핸들링 사용할 때 이 전의 값을 참조해서 stale값이 유지되는 현상이 발생함.
// 문제사항 예시
import { useState, useEffect } from "react";
export default function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
const id = setInterval(() => {
console.log("count:", count); // 👈 항상 0만 찍힘
setCount(count + 1);
}, 1000);
return () => clearInterval(id);
}, []); // 👈 빈 배열
return <h1>{count}</h1>;
}
// 문제 발생 이유
1. useEffect는 처음 렌더링 시 딱 한 번 실행([] 의존성 때문)
2. 그때의 count 값은 0.
3. 클로저가 당시 count=0을 기억함.
4. setInterval 안의 함수는 계속 그 “옛날 count”를 사용.
5. 그래서 콘솔엔 계속 count: 0만 찍히고, 값이 안 바뀜.
■■ 해결 방법
1. 콜백 함수형 setState 사용
useEffect(() => {
const id = setInterval(() => {
setCount(prev => prev + 1); // ✅ 항상 최신 prev 값 참조
}, 1000);
return () => clearInterval(id);
}, []); // interval 한 번만 설정
- setCount(prev => prev + 1)는 React가 가장 최신 상태(prev) 를 전달
- 따라서 stale 값 문제 없이 안정적으로 동작.
2. 의존성 배열에 상태값 추가
useEffect(() => {
const id = setInterval(() => {
console.log("count:", count);
setCount(count + 1);
}, 1000);
return () => clearInterval(id);
}, [count]); // ✅ count가 바뀔 때마다 최신 값 반영
>>> 결론
React는 함수형 컴포넌트가 랜더링 될 때, 내부의 클로저가 랜더링 될 때의 값을 참조하는 문제가 있음. 그래서 useEffect이나 이벤트핸들링 사용할 때 이 전의 값을 참조해서 stale값이 유지되는 현상이 발생함.
∴ 해결방안: 의존형 배열에 값을 넣거나 콜백함수로 만들면 됨.
'React > 프론트엔트 개념 정리' 카테고리의 다른 글
| [Next.js] - RSC에서 수정 후 이전 데이터가 보일 때 해결 방법 (0) | 2025.11.04 |
|---|---|
| Next.js에서 RSC 방식이란?(feat.서버, 클라이언트 컴포넌트) (0) | 2025.10.27 |
| JWT – Stateless 인증의 핵심 (0) | 2025.10.22 |
| Vue가 다시 뜨는 이유 (0) | 2025.10.14 |