React 성능 최적화: 실전 가이드
React 애플리케이션이 느려지는 이유와 이를 해결하는 방법들을 알아보겠습니다.
🚀 주요 최적화 기법
1. React.memo 활용
const ExpensiveComponent = React.memo(({ data, onUpdate }) => {
return (
<div>
{/* 복잡한 렌더링 로직 */}
</div>
);
});
// props가 같으면 리렌더링하지 않음
2. useMemo와 useCallback
function ProductList({ products, category }) {
// 비싼 계산 결과를 메모화
const filteredProducts = useMemo(() => {
return products.filter(p => p.category === category);
}, [products, category]);
// 함수를 메모화해서 자식 컴포넌트 리렌더링 방지
const handleUpdate = useCallback((id) => {
// 업데이트 로직
}, []);
return (
<div>
{filteredProducts.map(product => (
<ProductItem
key={product.id}
product={product}
onUpdate={handleUpdate}
/>
))}
</div>
);
}
3. 가상화(Virtualization)
import { FixedSizeList as List } from 'react-window';
function VirtualizedList({ items }) {
const Row = ({ index, style }) => (
<div style={style}>
{items[index].name}
</div>
);
return (
<List
height={600}
itemCount={items.length}
itemSize={35}
>
{Row}
</List>
);
}
🔍 성능 문제 진단
React DevTools Profiler 사용
- Profiler 탭 열기
- 녹화 시작 후 문제되는 동작 수행
- Flamegraph 분석해서 느린 컴포넌트 찾기
Performance API 활용
function usePerformanceMonitor(componentName) {
useEffect(() => {
performance.mark(`${componentName}-start`);
return () => {
performance.mark(`${componentName}-end`);
performance.measure(
componentName,
`${componentName}-start`,
`${componentName}-end`
);
};
});
}
⚡ 렌더링 최적화
1. 조건부 렌더링 최적화
// ❌ 나쁜 예
function App() {
const [showModal, setShowModal] = useState(false);
return (
<div>
{/* 항상 Modal 컴포넌트가 마운트됨 */}
<Modal show={showModal} />
</div>
);
}
// ✅ 좋은 예
function App() {
const [showModal, setShowModal] = useState(false);
return (
<div>
{/* 필요할 때만 Modal 컴포넌트 마운트 */}
{showModal && <Modal />}
</div>
);
}
2. 키 최적화
// ❌ 나쁜 예
items.map((item, index) => (
<Item key={index} data={item} />
))
// ✅ 좋은 예
items.map((item) => (
<Item key={item.id} data={item} />
))
📊 번들 크기 최적화
코드 스플리팅
import { lazy, Suspense } from 'react';
const LazyComponent = lazy(() => import('./LazyComponent'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
);
}
Tree Shaking
// ❌ 전체 라이브러리 import
import _ from 'lodash';
// ✅ 필요한 함수만 import
import debounce from 'lodash/debounce';
🎯 핵심 원칙
- 측정 먼저: 추측하지 말고 측정하기
- 병목지점 찾기: 가장 느린 부분부터 최적화
- 사용자 경험: 실제 사용자가 느끼는 성능 개선
- 점진적 개선: 작은 개선사항들의 누적 효과
성능 최적화는 끝이 없는 여정입니다. 사용자 경험을 항상 염두에 두고 최적화하세요! 🚀