프로그래밍/React
useMemo, React.memo, 컴포넌트 분리를 통한 렌더링 최적화 일기
윤수루
2022. 11. 27. 20:07
계기
- 현재 기획에 각 Todo에 대한 소요시간을 측정하는 기능이 있었다.
- 초 단위로 timer를 설정하려고 했기 때문에, start 버튼을 누르고 end를 누를 때까지 timer가 계속 작동한다.
- 이를 화면에 표시하기 위해 소요시간을 state로 관리했으며, '소요시간' 출력 부분이 1초마다 리렌더되어야 하므로 리렌더 범위를 최소화하고자 했다.
1. React.memo 사용
- 최하위 컴포넌트들 (Button, Text 등)은 부모 컴포넌트가 바뀌었을 때에 무조건 렌더링된다.
- 자녀 컴포넌트가 변하지 않았는데 불필요한 렌더링을 계속 하는 문제를 React.memo로 해결할 수 있다.
- 최적화된 컴포넌트를 리턴하여 렌더링이 될 상황에 Prop check 수행, Props 변화가 있을 때만 렌더링하도록 설정함.
export default memo(Image);
before

after

아주 미약하게 렌더링 범위가 축소된 것을 볼 수 있다.
🧐하지만 최적화무새에게는 아직 부족하지..
문제 인식
- prop는 원시 타입이 아니면 함수형 컴포넌트(부모)가 렌더링될 때마다 prop이 새로운 object이기 때문에 memo(Child); 해도 제대로 작동 안 할 수 있다.
- 이러한 경우에는 useMemo Hook과 함께 써야 최적화가 가능하다.
2. useMemo Hook과 함께 쓰기

const startPauseButton = useMemo(() => {
return <Button context={<Image src={buttonConfig.src} />} onClick={handleOnToggle} />;
}, [buttonConfig.src]);
const postponeDoneButton = useMemo(() => {
return (
<>
<Button context={<Image src={Postpone} />} />
<Button context={<Image src={Done} />} />
</>
);
}, []);
하지만 더덕더덕 붙어있는 useMemo 코드들과 Time interaction container가 통째로 재렌더링되는 것은 컴포넌트 분리로 문제를 해결해야 할 것 같았다..

3. 컴포넌트 분리하기
- 이제야 속이 좀 후련해졌다. 근데 버튼 1초마다 렌더링되는거 좀 불-편하다.. (timer와 상태를 공유하고 있어서 그런듯)
- 컨테이너 전체 -> 각각의 컴포넌트들로 렌더링 범위가 축소되었다.

느낀점
- 적당한 컴포넌트 분리와 적당한 메모이제이션을 통해 렌더링 최적화를 할 수 있다.
- 다만, 최적화를 '얼마나' 해야 하는가에 대한 부분은 지속적인 고민이 필요한 것 같다. 과한 분리, 과한 메모이제이션은 오히려 오버엔지니어링 + 성능 저하를 야기하니 말이다.!
반응형