React 성능 코드 리뷰 체크리스트
대형 프로젝트의 렌더링, 메모리, 네트워크 병목을 포함해 컴포넌트 설계와 훅 사용까지 포괄적으로 점검할 수 있도록 구성한 코드 리뷰 체크리스트
목차
소개
이 문서는 React 코드 리뷰에서 집중해야 할 성능 항목을 정리한 체크리스트다. 리뷰 대상은 컴포넌트 설계, 렌더링 빈도, 훅 사용, 메모리 관리, 네트워크 호출, 번들 크기, 프로파일링 전략 등이다. 초보자도 이해할 수 있도록 개념 설명과 체크 포인트, 예제 코드를 함께 제시한다.
전체 검토 흐름
코드 리뷰는 전체 흐름을 먼저 파악하는 것으로 시작한다. 애플리케이션의 사용 시나리오를 이해한 뒤, 빈번한 경로부터 우선 검토한다. 일반적인 절차는 다음과 같다.
- 핫스팟(자주 실행되는 컴포넌트) 식별
- 렌더링 프로파일 수집
- 개별 컴포넌트의 상태와 훅 사용 점검
- 네트워크/이미지/번들 관련 병목 확인
- 개선안 제시 및 재검증
렌더링 관련 체크리스트
불필요한 재렌더링 확인
컴포넌트가 자주 재렌더링되는지 확인한다. 부모에서 넘기는 props가 매번 새로운 객체나 함수인지 확인한다. 값이 변하지 않는데 재렌더링이 발생하면 React.memo, useMemo, useCallback 적용 검토가 필요하다.
키(key) 사용의 적절성
리스트 렌더링 시 index를 키로 사용했는지 확인한다. 데이터 순서가 변하거나 삽입/삭제가 빈번하면 고유 식별자를 키로 사용해야 한다. 잘못된 키는 불필요한 재렌더링과 상태 손실을 초래한다.
메모리 및 상태 관리
상태의 소유권과 범위
상태가 너무 상위에 있거나 불필요하게 컴포넌트 트리를 통해 전파되는지 확인한다. 전역 상태는 꼭 필요한 경우에만 사용하고, 로컬 상태는 컴포넌트에 둬야 한다.
메모리 누수 점검
useEffect 내부에서 등록한 이벤트 리스너나 타이머가 정리(cleanup)되는지 확인한다. 구독 해제 누락은 메모리 누수로 이어진다.
훅과 최적화 패턴
useMemo와 useCallback 사용 기준
useMemo와 useCallback은 비용이 큰 계산이나 함수 재생성을 막기 위한 도구다. 남용은 오히려 복잡도와 메모리 비용 증가로 이어진다. 의존성 배열이 정확한지 반드시 검토한다.
React.memo 적용 여부
순수 렌더링 컴포넌트라면 React.memo로 감싸는 것을 고려한다. 다만 props 비교 비용이 더 클 경우에는 효과가 없을 수 있다.
네트워크와 리소스
데이터 페칭 전략
중복 요청과 불필요한 refetch가 발생하는지 확인한다. 캐싱, 쿼리 키 설계, SWR/React Query 같은 라이브러리 적용을 검토한다.
이미지와 미디어 최적화
이미지 사이즈, 포맷, 레이지 로딩 여부를 점검한다. 브라우저 지원을 고려해 WebP 같은 형식을 검토한다.
빌드와 번들링
번들 크기는 초기 로드 성능에 직접 영향이 있다. 코드 스플리팅, 동적 import, 라이브러리 의존성 줄이기를 검토한다. 불필요한 폴리필과 중복 패키지 포함을 확인한다.
측정과 프로파일링
문제는 측정으로 확증해야 한다. 다음 도구를 권장한다.
- React Profiler: 렌더링 원인과 비용 확인
- Lighthouse: 전체 성능 지표 점검
- Chrome DevTools Performance: 타임라인 분석
- Web Vitals: 사용자 중심 지표 확인
체크 항목 요약
- 핫스팟 우선순위 지정
- 불필요한 재렌더링 제거
- useMemo/useCallback/React.memo 적용 여부 검토
- 상태의 적절한 위치와 범위 확인
- 이펙트 정리(cleanup) 확인
- 데이터 페칭 중복 제거 및 캐싱 전략
- 이미지 최적화와 레이지 로딩
- 번들 크기와 코드 스플리팅 점검
- 프로파일링으로 개선 효과 측정
간단한 예제
아래 코드는 부모가 매 렌더마다 새로운 콜백을 넘겨 자식이 재렌더링되는 상황과 해결 예시다.
const Parent = () => {
const [count, setCount] = useState(0);
const onClick = () => setCount(c => c + 1); // 매 렌더 새 함수 생성
return <Child onClick={onClick} />;
}
// 개선
const ParentFixed = () => {
const [count, setCount] = useState(0);
const onClick = useCallback(() => setCount(c => c + 1), []); // 콜백 재사용
return <Child onClick={onClick} />;
}
const Child = React.memo(({ onClick }) => {
console.log('Child render');
return <button onClick={onClick}>Click</button>;
});
마무리
리뷰는 한 번에 끝나지 않는다. 우선순위를 두고 반복 측정과 개선을 통해 성능 목표를 달성하는 접근이 필요하다. 위 체크리스트는 react 코드 리뷰 체크리스트, 리액트 성능 리뷰 항목, 퍼포먼스 코드 리뷰 react 같은 검색어를 염두에 두고 구성했다. 실제 프로젝트에 맞춰 항목을 조정하면 효과가 더 크다.