𝗘𝘀𝗰𝗮𝗽𝗶𝗻𝗴 𝘁𝗵𝗲 𝗧𝗿𝗮𝗽: 𝗙𝗶𝘅𝗶𝗻𝗴 𝗦𝘁𝗮𝗹𝗲 𝗖𝗹𝗼𝘀𝘂𝗿𝗲𝘀 𝗶𝗻 𝗥𝗲𝗮𝗰𝘁 𝗛𝗼𝗼𝗸𝘀
Stale Closure는 React에서 소리 없는 데이터 손실을 유발합니다.
백그라운드 타이머가 있는 대시보드를 구축한다고 가정해 봅시다. useEffect 훅 내부에서 setInterval을 사용하여 5초마다 데이터를 자동으로 저장합니다.
버그는 인터벌이 실행될 때 발생합니다. 사용자가 한 페이지를 가득 채워 작성했더라도 빈 문서를 저장해 버립니다. 인터벌이 과거에 머물러 있기 때문입니다. 즉, 상태(state)의 이전 버전을 사용하게 됩니다.
문제점
useEffect가 실행될 때, 해당 스코프 내의 변수들을 캡처합니다.
- 의존성 배열(dependency array)에서 상태를 제외하면, 인터벌은 첫 번째 렌더링 시의 상태를 사용합니다.
- 의존성 배열에 상태를 추가하면, React는 키를 입력할 때마다 인터벌을 재시작합니다. 이는 성능을 저하시키고 타이밍을 망가뜨립니다.
해결책: Mutable Ref 패턴
타이머와 데이터를 분리해야 합니다. useRef 훅을 사용하여 최신 상태에 대한 상수를 참조하도록 만드세요. 이렇게 하면 리렌더링을 방지하면서 인터벌을 안정적으로 유지할 수 있습니다.
구현 방법:
- 최신 상태를 담을 ref를 생성합니다.
- 상태가 변경될 때마다 해당 ref를 업데이트하도록
useEffect를 사용합니다. - 인터벌이 한 번만 실행되도록 빈 의존성 배열을 사용하여 인터벌을 시작합니다.
- 인터벌 콜백 내부에서 ref에 접근합니다.
이 방법을 사용하면 백그라운드 작업이 항상 최신 데이터를 사용하도록 보장할 수 있습니다. UI는 빠르게 유지하면서 데이터는 안전하게 보호할 수 있습니다.
출처: https://dev.to/iprajapatiparesh/escaping-the-trap-fixing-stale-closures-in-react-hooks-4gg7