도움말 - 글감 수집하기 (인용)

도움말 - 부분 리뷰 작성하기

리액트 네이티브 FlatList (React Native FlatList)

얼마전, 리액트 네이티브 0.43 버전이 릴리즈(release) 되었습니다. 이번 0.43 릴리즈 버전에서 새로 추가되는 리스트 관련 컴포넌트(FlatList, SectionList, VirtualizedList)가 있어 이에 대해 알아보도록 하겠습니다.

기존의 ListView 컴포넌트는 향 후 deprecated될 예정이라고 합니다. 그 이유는 버그, 과도한 메모리 사용 등의 문제점들 때문입니다. 또한, 기존의 ListView 컴포넌트의 경우 DataSource를 통해 데이터를 핸들링 해야 하는 부분에서 불편한 점도 있었습니다. 이번 0.43 릴리즈에서 추가되는 컴포넌트로 api도 많이 심플해졌으며, 퍼포먼스 향상도 상당히 많이 되었다고 합니다. 

이 글에서는 이번에 새로 추가 될 3개의 리스트 관련 컴포넌트(FlatList, SectionList, VirtualizedList) 중 FlatList 컴포넌트를 기존의 ListView와 비교를 통해 어떤 것들이 변화 되는지 알아보도록 하겠습니다. 그리고 직접 리액트 네이티브 0.43 버전을 설치하고, 간단한 샘플 코드를 통해 FlatList 사용법에 대해서 알아보도록 하겠습니다.

FlatList 

FlatList 컴포넌트는 심플한 api, 높은 퍼포먼스, 편리한 기능지원을 하는 리스트 컴포넌트 입니다. 여기에서는 퍼포먼스 보다는 api가 얼마나 간단해졌는지와 기능 위주로 ListView와 비교해가면서 다뤄 보도록 하겠습니다.

API: 데이터 핸들링

먼저, 기존의 ListView 컴포넌트의 경우 DataSource를 통해 데이터를 만들어 줘야 하기 때문에, constructor에서 아래와 같이 인스턴스를 만들어 줘야 합니다:

const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state = {
dataSource: ds.cloneWithRows([
'John', 'Joel', 'James', 'Jimmy', 'Jackson', 'Jillian', 'Julie', 'Devin'
])
};

하지만, FlatList의 경우 data prop에 배열(array)을 넘겨주기만 하면 됩니다:

data={['John', 'Joel', 'James', 'Jimmy', 'Jackson', 'Jillian', 'Julie', 'Devin']}

API: 데이터 변경 처리

ListView 컴포넌트의 경우 변경된 데이터를 반영하기 위해서는 dataSource를 변경해줘야 합니다:

 componentWillReceiveProps(nextProps) {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(nextProps.listData),
});
}

하지만, FlatList 컴포넌트의 경우 기본 배열 데이터이기 때문에, 위와 같이 불필요한 로직은 필요가 없이 데이터가 변경되면 리액트에 의해 알아서 리렌더(rerender)됩니다.

기능: Refresh 컨트롤

먼저, 모바일 앱에서 많이 사용되는 "pull to refresh" 기능 같은 경우,  ListView에서 구현 하기 위해선, refreshControl prop에 RefreshControl 컴포넌트를 따로 추가해서 사용 해야 합니다:

<ListView
refreshControl={
<RefreshControl
refreshing={this.state.refreshing}
onRefresh={this._onRefresh.bind(this)}
/>
}
...
>

하지만, FlatList의 경우 onRefreshrefreshing prop이 기본적으로 제공 하기 때문에, 아래와 같이 사용 할 수 있습니다:

<FlatList
  refreshing={this.state.refreshing}
  onRefresh={this._onRefresh}
  ...
/>  

ListView 컴포넌트와 비교 했을 때, 눈에띄게 변경된 점에 대해서 다뤄 보았습니다. 그럼 실제 간단한 리스트 컴포넌트를 만들어서 어떤식으로 동작 하는지 알아보도록 하겠습니다.


React Native 0.43 설치

리액트 네이티브를 처음 사용 하시는 분이라면, getting started를 참고해서 기본 환경 세팅을 하시면 됩니다.

먼저, 아래의 터미널 명령어를 통해 새 리액트 네이티브 프로젝트를 설치 합니다:

react-native init rn_0430

설치가 완료되면 설치 폴더로 이동 한 뒤 앱을 실행 합니다.

cd rn_0430 && react-native run-ios

빌드가 완료 되면 아래와 같은 화면이 보입니다.


FlatList 컴포넌트 예제 생성

이제 실제로 FlatList를 사용 해보도록 하겠습니다. FlatList에서 지원하는 기능중에서 가장 많이 사용되는 무한 스크롤, pull to refresh, 가로 스크롤 구현 해보도록 하겠습니다.

우선, 더미 데이터를 만들기 위해 faker 패키지를 추가합니다:

yarn add faker
// util.js
import faker from 'faker';

// 랜덤 유저 데이터 생성
export const randomUsers = (count = 10) => {
const arr = [];
for (let i = 0; i < count; i ++) {
arr.push({
key: faker.random.uuid(),
name: faker.name.firstName(),
avatar: faker.image.avatar(),
});
}
return arr;
};

먼저, 간단하게 랜덤 유저를 생성하는 함수를 하나 만들었습니다.

UI 라이브러리를 추가 해서 사용 하도록 합니다(스타일은 여기서 다루지 않겠습니다):

yarn add react-native-elements react-native-vector-icons

react-native-vector-icons를 네이티브 코드에 연결 합니다:

react-native link react-native-vector-icons

FlatList샘플의 전체 소스 입니다:


그럼, 샘플 소스를 살펴 보도록 하겠습니다. 

기본 prop 세팅

실제로, FlatList에서 최소한으로 필요한 prop은 datarenderItem 뿐입니다. data에는 일반적인 배열 데이터를, renderItem은 리스트에서 row로 사용 될 컴포넌트를 리턴하는 함수가 세팅 되면 됩니다. 

data={this.state.data} // default state로 randomUsers(20) 함수를 통해 랜덤 데이터 생성
renderItem={({ item }) => {
return (
<ListItem
roundAvatar
avatar={{uri: item.avatar}}
title={item.name}
/>
);
}}

Pull to Refresh 구현

일반적으로 모바일 앱 리스트에서 많이 사용되는 "pull to refresh"를 사용 하려면 refreshingonRefresh 함수를 사용 해서 이 기능을 구현 합니다. 예를들어, onRefresh 함수를 통해 서버에서 새로운 데이터를 받아오는 로직을 구현하고, 데이터를 기다리는 동안 refreshing 상태를 true로 변경 한 후, 데이터를 받은 후에 refreshing 상태를 다시 false로 하는 등으로 구현 할 수 있습니다. 

refreshing={this.state.refreshing}
onRefresh={this.onRefresh}

여기에서는 간단히 onRefresh 함수가 실행 되면 랜덤 유저 데이터 20개를 받아오도록 했습니다:

onRefresh = () => {
this.setState({
data: randomUsers(20),
});
}



무한 스크롤 구현

FlatList에서 무한 스크롤은 onEndReachedThresholdonEndReached prop을 통해 구현 할 수 있습니다. 스크롤이 onEndReachedThreshold에 설정한 값에 도달하면 onEndReached 함수가 실행 됩니다.

onEndReachedThreshold={1}
onEndReached={this.onEndReached}

여기 샘플 소스에서는 onEndReached 함수가 실행 되면 기존 데이터에 추가적으로 랜덤 데이터 10개를 더 추가하도록 구현 했습니다:

onEndReached = () => {
this.setState(state => ({
data: [
...state.data,
...randomUsers(),
]
}));
};


가로 스크롤 구현

가로 스크롤은 horizontal prop에 true 값만 넘겨주면 됩니다.

horizontal={true}




지금까지 리액트 네이티브 0.43 버전에 새로 추가된 FlatList에 대해서 알아 봤습니다. 간단하게 사용해보기만 했지만, api가 ListView에 비해 많이 편해져서 리스트 구현하는데 수월해질 것 같습니다. 다음에는 SectionList에 대해서 다뤄보도록 하겠습니다. 감사합니다.

리뷰

한영수

리액트 네이티브 FlatList (React Native FlatList)

Uicollectioview 구현

글 잘 봤습니다;)혹시 ios의 uicollectionview와 비슷한 기능을 제공하는 컴포넌트가 있나요??! 없다면 어떤식으로 구현하는게 좋을까요??!