무한호출

히니·2025년 9월 13일

workLogs

목록 보기
4/5

React 무한 루프, 왜 발생할까? 🤔

React 컴포넌트에서 무한 루프는 주로 useEffect 내에서 객체(Object)나 배열(Array) 상태를 잘못 업데이트할 때 발생합니다.

1. 문제의 핵심: 새로운 객체 참조

React 렌더링 과정: 상태 변경 → 컴포넌트 재실행(리렌더링) → useEffect 의존성 비교

무한 루프의 원인:

useEffect 내부에서 setState로 새로운 객체를 생성하여 상태를 업데이트합니다. 상태가 변경되었으므로 리렌더링이 발생합니다.

리렌더링 후 useEffect가 다시 실행되면서 또다시 새로운 객체를 생성하여 setState를 호출합니다.

1번으로 돌아가 무한 반복됩니다.

JavaScript에서 { a: 1 }과 { a: 1 }은 내용이 같아도 서로 다른 메모리 주소를 가진 별개의 객체입니다. React는 이 주소(참조)가 다르기 때문에 상태가 변경되었다고 판단하고 리렌더링을 계속 발생시킵니다.

// ❌ 무한 루프가 발생하는 코드 예시
useEffect(() => {
  // 렌더링될 때마다 '새로운' 객체가 생성되어 상태가 계속 변경됨
  setSomeObject({ key: 'value' }); 
}, [someObject]); // 의존성 배열에 객체 자신이 포함되어 있는 경우

2. 원시값(Primitive)은 괜찮은 이유

반면, boolean, number, string과 같은 원시값은 값이 같으면 React가 리렌더링을 생략합니다.


// ✅ 괜찮은 코드 예시
// device.powerMode가 'on'으로 동일하다면 계속 true가 전달됨
setPowerStatus(device.powerMode === 'on');

// React는 기존 상태가 true인데 또 true로 업데이트하라는 요청을 받으면
// 상태 변경이 없다고 판단하고 리렌더링을 하지 않습니다.

객체 상태, 어떻게 안전하게 다룰까? ✅
객체 상태를 업데이트하면서 무한 루프를 피하는 핵심은 "의존성이 실제로 변경되었을 때만 새로운 객체를 생성"하는 것입니다.

🥇 1. useMemo 사용 (가장 추천)

useMemo는 의존성 배열의 값이 변경될 때만 새로운 객체를 생성하고, 그렇지 않으면 이전에 생성했던 객체를 그대로 반환합니다.

장점: 코드가 깔끔하고, 의도치 않은 객체 재생성을 막아 성능 최적화와 무한 루프 방지에 효과적입니다. device 같은 값이 초기 로딩 시 undefined여도 안전하게 처리됩니다.


// device의 특정 속성들이 바뀔 때만 softApData 객체가 새로 생성됨
const softApData = useMemo(() => ({
  softApMode: device?.softApMode || 0,
  softApPassword: device?.softApPassword || '',
  // ...
}), [device?.softApMode, device?.softApPassword]); // 실제 값들을 의존성으로 지정

useEffect(() => {
  setSoftApPopupData(softApData);
}, [softApData]); // softApData의 참조가 바뀔 때만 실행됨

2. 조건부로 상태 업데이트

상태를 업데이트하기 전에 새로운 데이터와 이전 데이터를 비교하여, 실제로 내용이 다를 때만 업데이트를 실행하는 방법입니다.

단점: 객체가 복잡하면 비교 로직(예: JSON.stringify)이 번거롭고 성능에 부담을 줄 수 있습니다.

3. 상태를 개별적으로 분리

하나의 큰 객체 대신 여러 개의 useState를 사용하여 각 속성을 개별적인 상태로 관리합니다. 이는 객체 참조 문제 자체를 원천적으로 방지합니다.

단점: 관리해야 할 상태가 너무 많아지면 코드가 복잡해질 수 있습니다.

결론

React에서 객체 상태를 다룰 때는 참조 동일성(Reference Equality)을 이해하는 것이 무한 루프를 방지하는 핵심입니다. useMemo는 이러한 문제를 가장 우아하고 효율적으로 해결해 주는 최고의 방법입니다.

profile
안녕하세요

0개의 댓글