React Native에서 FlatList 성능 개선 작업

문제 상황

이커머스 앱의 상품 목록 화면에서 스크롤 성능 이슈가 발생했다. 약 200개 정도의 상품 아이템을 렌더링하는데, 스크롤 시 프레임 드롭이 눈에 띄게 발생했다. 각 아이템은 이미지, 제목, 가격, 좋아요 버튼 등을 포함하고 있었다.

적용한 최적화

1. getItemLayout 구현

아이템 높이가 고정되어 있어서 getItemLayout을 구현했다.

getItemLayout={(data, index) => (
  {length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index}
)}

2. removeClippedSubviews 활성화

화면 밖 뷰를 제거하는 옵션을 켰다. Android에서 특히 효과적이었다.

<FlatList
  removeClippedSubviews={true}
  maxToRenderPerBatch={10}
  windowSize={10}
/>

3. 이미지 최적화

react-native-fast-image 라이브러리로 교체했다. 캐싱과 우선순위 설정이 가능해 이미지 로딩이 훨씬 부드러워졌다.

import FastImage from 'react-native-fast-image';

<FastImage
  source={{uri: item.imageUrl, priority: FastImage.priority.normal}}
  style={styles.image}
  resizeMode={FastImage.resizeMode.cover}
/>

4. keyExtractor 최적화

처음엔 index를 key로 사용했는데, 상품 ID를 사용하도록 변경했다.

keyExtractor={item => item.id.toString()}

결과

Perf Monitor로 확인했을 때 초당 프레임이 4045fps에서 5560fps로 개선되었다. 특히 Android 저사양 기기에서 체감 차이가 컸다. initialNumToRender를 줄이니 초기 렌더링 속도도 빨라졌다.

다음엔 React.memo와 useCallback을 활용한 리렌더링 최적화도 시도해볼 예정이다.