채널 목록 화면을 만들려고 하는데 데이터의 양이 많기에 스크롤을 활용하여 데이터를 렌더링하려고 한다. 대표적으로 FlatList 컴포넌트와 ScrollView 컴포넌트가 있는데 TodoList를 만들때 ScrollView를 사용해보았으니 이번에는 FlatList 컴포넌트를 사용하기로 했다.
FlatList 컴포넌트는 필요한 양만큼만 렌더링하고 스크롤의 위치에 따라 추가로 데이터를 렌더링. 데이터의 길이가 가변적이고 양을 예측할 수 없는 상황에서 플랫리스트 컴포넌트를 많이 사용
공식 문서 : https://reactnative.dev/docs/flatlist
import { FlatList } from 'react-native';
//렌더링할 임시 데이터
const channels = [];
for (let i = 0; i < 1000; i++) {
channels.push({
id: i,
title: `title : ${i}`,
description: `desc : ${i}`,
createdAt: i,
});
}
(...)
//렌더링할 컴포넌트
const Item = ({ item: { id, title, description, createdAt }, onPress }) => {
console.log(id);
return (
<ItemContainer>
<ItemTextContainer>
<ItemTitle>{title}</ItemTitle>
<ItemDesc>{description}</ItemDesc>
</ItemTextContainer>
<ItemTime>{createdAt}</ItemTime>
<ItemIcon />
</ItemContainer>
);
};
(...)
<FlatList
// 렌더링할 데이터를 갖고 있는 배열을 data에 전달
data = {channels}
//항목을 렌더링하기 위해 컴포넌트를 반환하는 함수 전달
renderItem={({item})=> < Item item={item}/>}
//키 지정.keyExtractor은 함수로 전달해야 함
keyExtractor={item => item['id'].toString()}
/>
위에서 렌더링할 데이터를 1000개를 준비하였다. 근데 렌더링되는 데이터를 보면 75(76)개만 렌더링 되는 것을 볼 수 있다.

그 이유는 아래와 같이 windowSize가 21로 설정되어 있기 때문이다. windowSize는 FlatList가 렌더링할 화면의 수라고 할 수 있다. 21의 의미는 이전 화면 10개 이후 화면 10개 그리고 현재화면 1개를 더해서 나온 값이다.
https://reactnative.dev/docs/optimizing-flatlist-configuration#windowsize

그렇다면 75개만 렌더링 되는 이유는 현재 페이지가 가장 위에 있기에 이전 화면이 없고 아래 사진에서 보면 현재 화면에 보여지는 데이터의 숫자가 6.9개 정도이다. 이전 페이지 0개, 현재페이지 다음 10개를 계산해보면 76개 정도 렌더링 되는 것이다.
6.9 * (0 +1 + 10) = 75.9

그래서 사이즈를 조절해서 렌더링하는 컴포넌트의 숫자를 줄여서 메모리의 소비를 줄이고 성능을 향상시켰다. 렌더링되는 데이터가 76개에서 20개으로 줄여 메모리 사용량을 30% 감소시켰다.
<FlatList
data={channels}
renderItem={({ item }) => <Item item={item} />}
keyExtractor={(item) => item['id'].toString()}
windowSize={5} // 렌더링될 데이터 사이즈 조절
/>

화면을 스크롤하면 이미 불러왔던 데이터가 또 불려졌다.

이것은 스크롤의 위치가 변경되면서 해당 위치를 기준으로 필요한 데이터를 렌더링하기 때문에 발생하는 것이고 React.memo로 컴포넌트를 감싸 컴포넌트의 변화가 없을 때 리렌더리되는 것을 방지하였다.
const Item = React.memo(({ item: { id, title, description, createdAt }, onPress }) => {
console.log(id);
return (
<ItemContainer>
<ItemTextContainer>
<ItemTitle>{title}</ItemTitle>
<ItemDesc>{description}</ItemDesc>
</ItemTextContainer>
<ItemTime>{createdAt}</ItemTime>
<ItemIcon />
</ItemContainer>
);
});
50에서 53으로 늘어난 것을 볼 수 있다.

