React Native에서 FlatList 성능 개선하기
문제 상황
300개 이상의 아이템을 렌더링하는 피드 화면에서 스크롤이 버벅이는 현상이 발생했다. 안드로이드 저사양 기기에서 특히 심했다.
원인 분석
React Native Profiler로 확인해보니 스크롤할 때마다 불필요한 리렌더링이 발생하고 있었다. FlatList가 아이템 높이를 측정하느라 많은 연산을 수행하는 것이 문제였다.
해결 방법
1. getItemLayout 구현
아이템 높이가 고정된 경우 getItemLayout을 구현해 높이 측정 과정을 생략했다.
const ITEM_HEIGHT = 120;
const getItemLayout = (data, index) => ({
length: ITEM_HEIGHT,
offset: ITEM_HEIGHT * index,
index,
});
<FlatList
data={items}
getItemLayout={getItemLayout}
renderItem={renderItem}
/>
2. keyExtractor 최적화
const keyExtractor = (item) => item.id.toString();
<FlatList
keyExtractor={keyExtractor}
// ...
/>
3. removeClippedSubviews 활성화
화면 밖의 뷰를 네이티브 뷰 계층에서 제거해 메모리를 절약했다.
<FlatList
removeClippedSubviews={true}
maxToRenderPerBatch={10}
windowSize={10}
// ...
/>
결과
스크롤 FPS가 30에서 55로 개선됐다. 안드로이드 저사양 기기에서도 부드러운 스크롤이 가능해졌다.
참고사항
getItemLayout은 아이템 높이가 가변적일 때는 사용할 수 없다removeClippedSubviews는 iOS에서 가끔 렌더링 이슈가 있어 테스트가 필요하다- React.memo()로 renderItem 컴포넌트를 감싸는 것도 효과적이었다