불필요한 리렌더링 이해와 방지
React 애플리케이션의 성능을 최적화하는 데 있어 불필요한 리렌더링을 이해하고 방지하는 것은 매우 중요합니다.
이 절에서는 리렌더링의 원인과 이를 최적화하는 방법에 대해 알아보겠습니다.
컴포넌트 리렌더링의 조건
React 컴포넌트가 리렌더링되는 주요 조건은 다음과 같습니다.
- 컴포넌트의 상태(state)가 변경될 때
- 부모 컴포넌트가 리렌더링될 때
- 컴포넌트에 전달되는 props가 변경될 때
예를 들어,
이 예제에서 setCount
가 호출될 때마다 Counter
컴포넌트가 리렌더링됩니다.
부모 컴포넌트 리렌더링의 영향
부모 컴포넌트가 리렌더링되면, 기본적으로 모든 자식 컴포넌트도 리렌더링됩니다.
이 경우, Parent
의 count
상태가 변경될 때마다 Child
컴포넌트도 리렌더링됩니다.
Props 변경에 따른 리렌더링
Props가 변경되면 해당 컴포넌트는 리렌더링됩니다.
count
prop이 변경될 때마다 Child
컴포넌트가 리렌더링됩니다.
React.memo를 사용한 최적화
React.memo
는 고차 컴포넌트(HOC)로, props가 변경되지 않으면 컴포넌트의 리렌더링을 방지합니다.
이 경우, count
가 변경되어도 MemoizedChild
는 리렌더링되지 않습니다.
useCallback 사용법
useCallback
은 함수를 메모이제이션하여, 불필요한 리렌더링을 방지합니다.
handleClick
함수가 메모이제이션되어 MemoizedChild
의 불필요한 리렌더링을 방지합니다.
useMemo 사용법
useMemo
는 계산 비용이 큰 값을 메모이제이션합니다.
data
가 변경되지 않으면 expensiveResult
는 재계산되지 않습니다.
리렌더링 최적화 전략
- 상태를 적절한 레벨에 위치시키기
- 불변성 유지하기
- 리스트 렌더링 시 적절한 key 사용하기
- 대규모 리스트는 가상화 기법 사용하기 (예 : react-window)
- 이벤트 핸들러를 인라인으로 정의하지 않기
- Context API 사용 시 Provider 최적화하기
불필요한 최적화의 위험성
과도한 최적화는 코드의 복잡성을 증가시키고 가독성을 해칠 수 있습니다.
따라서 다음 경우에만 최적화를 고려하세요.
- 성능 문제가 실제로 발생했을 때
- 컴포넌트가 자주 리렌더링될 때
- 컴포넌트의 리렌더링 비용이 클 때
적절한 사용 시기에 대한 가이드라인
- 프로파일링을 통해 실제 성능 병목지점 식별하기
- 사용자 경험에 직접적인 영향을 미치는 부분부터 최적화하기
- 데이터 흐름과 상태 관리 구조를 먼저 개선하기
- 최적화 전후의 성능을 측정하고 비교하기
불필요한 리렌더링을 방지하는 것은 React 애플리케이션의 성능을 크게 향상시킬 수 있습니다. 그러나 모든 컴포넌트를 무조건적으로 최적화하는 것은 바람직하지 않습니다. 성능 최적화는 항상 측정 가능한 문제에 대한 해결책으로 접근해야 합니다.
React의 기본적인 렌더링 메커니즘은 이미 꽤 효율적이므로, 대부분의 경우 추가적인 최적화 없이도 충분한 성능을 발휘합니다. 따라서 실제 성능 문제가 발생했을 때, 그리고 그 원인이 불필요한 리렌더링임이 확인되었을 때 최적화 기법을 적용하는 것이 좋습니다.
마지막으로, 최적화 기법을 적용할 때는 항상 코드의 가독성과 유지보수성을 고려해야 합니다. 때로는 약간의 성능 저하를 감수하고 코드를 더 명확하고 이해하기 쉽게 유지하는 것이 장기적으로 더 유리할 수 있습니다. 팀의 다른 개발자들과 최적화 전략에 대해 논의하고 합의하는 것도 중요한 과정입니다.