강신규

[React] 상태 관리 최적화: 불필요한 리렌더링 줄이기 본문

Framework/React

[React] 상태 관리 최적화: 불필요한 리렌더링 줄이기

kangnew 2024. 12. 4. 15:30

리렌더링이란 무엇인가?

리렌더링은 React 컴포넌트가 자신의 UI를 다시 그리는 과정을 말합니다. 이는 컴포넌트의 상태나 속성이 변경되었을 때 발생하며, React는 이전 렌더링 결과와 새로운 결과를 비교하여 실제 DOM에 필요한 변경사항만을 적용합니다.

 

리렌더링이 발생하는 경우

1. 상태(state)변경: 컴포넌트의 상태가 변경이 되었을 때

2.속성(props) 변경: 부모 컴포넌트로부터 전달받는 props가 변경 되었을때

3.부모 컴포넌트의 리랜더링: 부모 컴포넌트가 리렌더링되면 자식 컴포넌트들도 기본적으로 리렌더링

 

상태(state)변경의 최적화

컴포넌트를 실행을 하게되면 useState에 값을 Fiber Node에 저장을 하게 됩니다. 만약에 setState를 통해 값이 변경이 된다면 저장했었던 Fiber Noder 값의 비교를 통해 리랜더링이 발생하게 됩니다. 

  const [liveHomeAddress, setLiveHomeAddress] = useState('');
  const [liveHomeAddressDetail, setLiveHomeAddressDetail] = useState('');
  const [liveZipCode, setLiveZipCode] = useState('');
  const [liveBuildungNum, setLiveBuildungNum] = useState('');
  const [iruAddress, setIruAddress] = useState('');
  const [iruAddressDetail, setIruAddressDetail] = useState('');
  const [iruZipCode, setIruZipCode] = useState('');
  const [iruZipCodeMngNo, setIruZipCodeMngNo] = useState('');
  const [iruBuildungNum, setIruBuildungNum] = useState('');
  
  
  const fetchData = async number => {
    try {
      showLoading(loadingDispatch);
      const response = await UserService.getUserDetail();
      if (response.status === 'OK') {
        fetched.current = true;
        setFetched(true);
        setFirstNum(response.data?.residNo.substring(0, 6));
        setLastNum(response.data?.residNo.substring(6, 13));
        setPhoneNum(number ? number : response.data?.decHndNo);
        response.data?.liveHomeTelNo &&
          setHomeNum(response.data?.liveHomeTelNo);
        setCompanyName(response.data?.companyName);
        response.data?.companyTelNo &&
          setCompanyNum(response.data?.companyTelNo);
        response.data?.email && setEmail(response.data?.email);
        setLiveHomeAddress(response.data?.liveHomeAddress);
      } else {
        throw new Error(response.error.message);
      }
    } catch (error) {
      showAlert({
        dispatch: alertDispatch,
        message: error.message,
      });
    } finally {
      hideLoading(loadingDispatch);
    }
  };

 

이 방식으로 상태를 관리할 때, 서버에서 값을 받아와 각 상태를 개별적으로 설정하면서 setState 함수가 호출될 때마다 리렌더링이 발생했습니다. 이로 인해, 실제로 리렌더링이 필요하지 않은 컴포넌트들까지 불필요하게 렌더링되는 문제가 나타났습니다.

 

 

 

해결 방안 : 단일 객체 상태로 관리

여러 개의 개별 상태를 하나의 객체로 통합하여 관리하는 방법을 사용하였습니다.

const [addressInfo, setAddressInfo] = useState({
  liveHomeAddressDetail: '',
  liveZipCode: '',
  liveBuildungNum: '',
  iruAddress: '',
  iruAddressDetail: '',
  iruZipCode: '',
  iruZipCodeMngNo: '',
  iruBuildungNum: '',
  companyAddress: ''
});

setAddressInfo(prevState => ({
  ...prevState,
  liveHomeAddressDetail: newValue1,
  liveZipCode: newValue2,
  // ... 기타 필드 업데이트
}));

 

이를 통해 React DevTools 기준 28번의 컴포넌트 랜더링에서 1번의 렌더링으로 리렌더링을 최소화 하였습니다.

(16.2 ms -> 4ms)

 

결론:

React 애플리케이션의 성능을 최적화 하는 방법중에서 상태 관리를 통한 방법이 있습니다.

여러 상태를 하나의 객체로 통합하여 관리하면 유지보수가 용이해지고, 서버 조회 후 값을 설정할 때 불필요한 리렌더링을 줄일 수 있습니다.

 

 

'Framework > React' 카테고리의 다른 글

[React] useRef란  (0) 2025.01.08
[React] useEffect란  (5) 2025.01.02
[React] useState + CallBack  (1) 2024.12.24
React useRef vs 변수 vs useState  (0) 2022.11.25
React 상태관리 Context  (0) 2022.11.11