Next.js
React에서 상태 관리 문제를 해결하기
React 컴포넌트의 상태 업데이트와 렌더링 문제를 체계적으로 진단하는 방법.
React에서 대량의 데이터를 다루면 상태 업데이트가 제대로 반영되지 않거나 성능이 급격히 저하될 수 있다. 로컬에서는 작은 데이터셋으로 잘 돌지만 배포 환경에서는 다르게 보일 수 있다.
처음 보이는 증상 정리
현상을 먼저 명확하게 파악한다:
- 화면에 데이터가 안 나타나는가?
- 데이터는 있지만 업데이트가 반영 안 되는가?
- 인터랙션(클릭, 입력)에 반응하지 않는가?
- 페이지가 느리게 로드되는가?
각 상황마다 원인이 다르므로 증상을 명확히 하는 것이 중요하다.
원인을 나누는 기준
React 문제는 세 가지로 나뉜다:
- 렌더링 조건: 컴포넌트가 렌더링될 조건이 맞지 않음
// 문제: useEffect 의존성 배열 누락
useEffect(() => {
fetchData();
// 의존성 배열 없음 → 매번 렌더링될 때마다 실행
})
// 해결
useEffect(() => {
fetchData();
}, []) // 초기 렌더링 때만 실행
- 상태 업데이트: setState가 제대로 호출되지 않음
const [items, setItems] = useState([]);
// 문제: 직접 수정
items.push(newItem); // ❌ React가 변경을 감지 못함
// 해결
setItems([...items, newItem]); // ✓ 새 배열 객체
- 이벤트 흐름: 이벤트가 발생했지만 핸들러가 실행 안 됨
브라우저 개발자 도구로 확인
모바일 폭으로 변경하고 키보드 입력을 시뮬레이션한다.
npm run build
이후 브라우저 개발자 도구에서:
- React DevTools 확장 프로그램 설치
- Components 탭에서 컴포넌트 트리 확인
- 각 컴포넌트의 props와 state 확인
- 상태가 실제로 변경되는지 추적
성능 측정
대량 데이터 처리 시 성능 문제가 있는지 확인한다.
// 렌더링 시간 측정
console.time('render');
// 렌더링 코드
console.timeEnd('render');
// 또는 React Profiler 사용
import { Profiler } from 'react';
<Profiler id="expensive-component" onRender={onRender}>
<ExpensiveComponent />
</Profiler>
특정 컴포넌트가 반복해서 렌더링되면 메모이제이션(React.memo, useMemo)을 고려한다.
단계별 확인
-
상태가 변경되는가?
- console.log로 setState 호출 확인
- React DevTools에서 상태값 변경 추적
-
컴포넌트가 다시 렌더링되는가?
- 콘솔에 렌더링 로그 추가
- 각 렌더링 사이의 시간 간격 확인
-
DOM이 업데이트되는가?
- 브라우저 개발자 도구 Elements 탭에서 HTML 변경 확인
- Mutation Observer로 DOM 변경 추적
마지막 점검
문제를 해결한 후:
- 작은 데이터셋에서 테스트
- 중간 크기 데이터셋에서 성능 확인
- 실제 프로덕션 데이터 크기로 테스트
각 단계에서 문제가 없는지 확인해야 배포 후 서프라이즈를 피할 수 있다.