React Native에서 FlatList 성능 개선하기
문제 상황
상품 목록 화면에서 500개 이상의 아이템을 렌더링할 때 스크롤이 버벅이는 현상이 발생했다. 특히 Android에서 심했고, 이미지가 포함된 복잡한 레이아웃이라 더 느렸다.
적용한 최적화
1. getItemLayout 구현
아이템 높이가 고정되어 있다면 getItemLayout을 반드시 구현해야 한다. FlatList가 스크롤 위치를 계산하는 비용을 크게 줄일 수 있다.
getItemLayout={(data, index) => ({
length: ITEM_HEIGHT,
offset: ITEM_HEIGHT * index,
index,
})}
2. keyExtractor 최적화
기본 keyExtractor는 index를 사용하는데, 데이터가 변경될 때 불필요한 리렌더를 유발한다.
keyExtractor={(item) => item.id.toString()}
3. removeClippedSubviews 활성화
Android에서 화면 밖의 뷰를 제거해 메모리를 절약한다.
<FlatList
removeClippedSubviews={true}
maxToRenderPerBatch={10}
windowSize={10}
/>
4. shouldComponentUpdate 구현
renderItem에 전달되는 컴포넌트를 PureComponent로 변경하거나 React.memo로 감쌌다.
const ProductItem = React.memo(({ item }) => {
return (
<View style={styles.item}>
<Image source={{ uri: item.imageUrl }} />
<Text>{item.name}</Text>
</View>
);
});
결과
위 최적화를 모두 적용한 결과 Android에서도 부드러운 스크롤을 유지할 수 있었다. 특히 getItemLayout과 removeClippedSubviews의 효과가 컸다. 개발자 메뉴의 Perf Monitor로 확인했을 때 60fps에 근접한 수치가 나왔다.
복잡한 리스트 화면을 만들 때는 처음부터 이런 최적화를 염두에 두고 설계하는 게 중요하다는 걸 다시 한번 느꼈다.