React Native에서 VirtualizedList는 매우 큰 크기의 목록을 렌더링할 때 가장 적합한 컴포넌트입니다. 일반적인 FlatList나 ScrollView와 달리, 화면에 보이는 영역의 항목만 실제로 렌더링하기 때문에 성능과 메모리 사용량을 크게 개선할 수 있습니다. 사용자가 스크롤을 내리면 필요한 시점에 데이터가 동적으로 로드되어 화면에 표시됩니다.
VirtualizedList 기본 구조
VirtualizedList의 기본적인 사용 구조는 다음과 같습니다.
<VirtualizedList data={DATA} initialNumToRender={4} renderItem={renderItem} keyExtractor={keyExtractor} getItemCount={getItemCount} getItem={getItem} />주요 Props 정리
VirtualizedList를 제대로 활용하려면 아래 핵심 속성들을 이해해야 합니다.
| Props | 설명 |
|---|---|
| renderItem | 데이터의 각 항목을 VirtualizedList 내부에 렌더링하는 함수입니다. |
| data | 화면에 표시할 원본 데이터입니다. |
| getItem | 데이터에서 개별 항목을 가져오는 함수입니다. |
| getItemCount | 표시할 데이터 항목의 전체 개수를 반환하는 함수입니다. |
| initialNumToRender | 초기 렌더링 시 화면에 먼저 그릴 항목 수입니다. |
| keyExtractor | 지정된 인덱스의 각 항목에 고유 키(key)를 부여하는 함수입니다. |
예제: VirtualizedList로 데이터 표시하기
VirtualizedList를 사용하려면 먼저 react-native에서 해당 컴포넌트를 임포트해야 합니다.
import { SafeAreaView, View, VirtualizedList, StyleSheet, Text } from 'react-native';VirtualizedList의 기본 JSX 코드는 다음과 같습니다.
<SafeAreaView>
<VirtualizedList
data={DATA}
initialNumToRender={4}
renderItem={({ item }) => <Item title={item.title} />}
keyExtractor={item => item.id}
getItemCount={getItemCount}
getItem={getItem}
/>
</SafeAreaView>여기서 initialNumToRender={4}는 처음 화면에 렌더링할 항목 수를 4개로 지정한 것입니다. renderItem은 각 항목을 화면에 표시하는 역할을 하며, 아래와 같이 커스텀 Item 컴포넌트를 활용합니다.
const Item = ({ title }) => {
return (
<View style={styles.item}>
<Text style={styles.title}>{title}</Text>
</View>
);
}keyExtractor는 각 항목에 고유한 키를 지정하여 React가 항목을 효율적으로 추적할 수 있도록 합니다.
keyExtractor={item => item.id}getItemCount props는 사용자에게 표시될 항목의 총 개수를 반환합니다. 현재 예제에서는 다음과 같이 정의된 함수를 호출합니다.
const getItemCount = (data) => {
return 100;
}
getItemCount={getItemCount}getItem props는 실제로 표시할 데이터를 가져오는 역할을 하며, 다음과 같이 정의합니다.
const getItem = (data, index) => {
return {
id: index,
title: 'test'
}
}
getItem={getItem}전체 예제 코드
아래는 VirtualizedList를 실행하기 위한 완전한 코드입니다.
import React from 'react';
import { SafeAreaView, View, VirtualizedList, StyleSheet, Text } from 'react-native';
const DATA = [];
const getItem = (data, index) => {
return {
id: index,
title: 'test'
}
}
const getItemCount = (data) => {
return 100;
}
const Item = ({ title }) => {
return (
<View style={styles.item}>
<Text style={styles.title}>{title}</Text>
</View>
);
}
const VirtualizedListExample = () => {
return (
<SafeAreaView>
<VirtualizedList
data={DATA}
initialNumToRender={4}
renderItem={({ item }) => <Item title={item.title} />}
keyExtractor={item => item.id}
getItemCount={getItemCount}
getItem={getItem}
/>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
item: {
backgroundColor: '#ccc',
height: 100,
justifyContent: 'center',
marginVertical: 8,
marginHorizontal: 16,
padding: 20,
},
title: {
fontSize: 32,
},
});
export default VirtualizedListExample;실행 결과
위 코드를 실행하면 회색 배경의 항목 100개가 스크롤 가능한 리스트 형태로 표시되며, 초기에는 4개의 항목만 렌더링됩니다. 스크롤을 내리면 나머지 항목이 필요한 순간에 자동으로 로드됩니다.

마무리
VirtualizedList는 수천, 수만 개에 달하는 대용량 데이터를 다룰 때 필수적인 컴포넌트입니다. getItem과 getItemCount를 직접 정의해야 하는 번거로움이 있지만, 그만큼 렌더링 방식을 세밀하게 제어할 수 있어 복잡한 리스트 요구사항에 유연하게 대응할 수 있습니다. 단순한 목록이라면 FlatList를, 극단적으로 큰 데이터셋이나 특수한 데이터 구조를 다룰 때는 VirtualizedList를 선택하는 것이 좋습니다.