무한 스크롤 구현하기: React Native에서 효율적인 데이터 로딩

oversleep·2025년 2월 25일
0

app-development

목록 보기
22/38
post-thumbnail

들어가며

모바일 앱을 개발할 때 사용자 경험을 향상시키는 중요한 기능 중 하나는 무한 스크롤(Infinite Scroll)입니다.
사용자가 콘텐츠의 끝까지 스크롤할 때 자동으로 새로운 데이터를 로드하는 이 기능은 페이지 번호를 클릭하거나 '더 보기' 버튼을 누르는 번거로움을 줄여줍니다.
이 글에서는 React Native에서 무한 스크롤을 구현하는 방법에 대해 살펴보겠습니다.

무한 스크롤의 장점

무한 스크롤은 다음과 같은 장점을 제공합니다:

  1. 향상된 사용자 경험: 사용자가 별도의 액션 없이 계속해서 콘텐츠를 소비할 수 있습니다.
  2. 초기 로딩 시간 감소: 필요한 데이터만 로드하기 때문에 앱의 초기 로딩 속도가 빨라집니다.
  3. 서버 부하 감소: 사용자가 실제로 보는 데이터만 요청하기 때문에 서버 리소스를 효율적으로 사용할 수 있습니다.
  4. 더 나은 모바일 경험: 특히 모바일 환경에서 스크롤은 가장 자연스러운 상호작용 방식입니다.

React Native에서 무한 스크롤 구현하기

React Native에서 무한 스크롤을 구현하는 방법은 여러 가지가 있지만, 여기서는 ScrollView를 사용한 기본적인 방법을 알아보겠습니다.

1. 상태 관리

먼저 필요한 상태 변수들을 설정합니다:

const [allData, setAllData] = useState([]);
const [currentPage, setCurrentPage] = useState(0);
const [totalPages, setTotalPages] = useState(0);
const [loading, setLoading] = useState(true);
const [isLoadingMore, setIsLoadingMore] = useState(false);

2. 데이터 가져오기

데이터를 가져오는 함수를 만듭니다:

const fetchData = async (page = 0, isLoadingMore = false) => {
  try {
    setLoading(!isLoadingMore);
    const response = await api.get("/data", {
      params: {
        page,
        size: 10,
      },
    });

    if (response.data?.items && Array.isArray(response.data.items)) {
      const newData = isLoadingMore
        ? [...allData, ...response.data.items]
        : response.data.items;

      setAllData(newData);
      setTotalPages(response.data.totalPages);
      setCurrentPage(page);
    }
  } catch (error) {
    console.error("Error fetching data:", error);
  } finally {
    setLoading(false);
    setIsLoadingMore(false);
  }
};

3. 더 많은 데이터 로드하기

사용자가 화면 하단에 가까워졌을 때 더 많은 데이터를 로드하는 함수를 만듭니다:

const loadMoreData = async () => {
  if (isLoadingMore || currentPage >= totalPages - 1) return;

  setIsLoadingMore(true);
  await fetchData(currentPage + 1, true);
};

4. ScrollView와 onScroll 이벤트 설정

ScrollView 컴포넌트에 onScroll 이벤트 핸들러를 추가합니다:

<ScrollView
  style={styles.container}
  onScroll={({ nativeEvent }) => {
    const { layoutMeasurement, contentOffset, contentSize } = nativeEvent;
    const isCloseToBottom = layoutMeasurement.height + contentOffset.y >= contentSize.height - 20;

    if (isCloseToBottom && !loading && !isLoadingMore) {
      loadMoreData();
    }
  }}
  scrollEventThrottle={400}
>
  {/* 데이터 렌더링 */}
  {allData.map((item) => (
    <View key={item.id}>{renderItem({ item })}</View>
  ))}
  
  {/* 로딩 표시 */}
  {isLoadingMore && (
    <View style={styles.loadingMoreContainer}>
      <Text style={styles.loadingText}>더 불러오는 중...</Text>
    </View>
  )}
</ScrollView>

여기서 주목할 부분은 다음과 같습니다:

  • isCloseToBottom 변수는 사용자가 화면 하단에 20픽셀 이내로 가까워졌는지 확인합니다.
  • scrollEventThrottle={400}은 스크롤 이벤트가 발생하는 빈도를 400ms로 제한하여 성능을 최적화합니다.
  • 로딩 중임을 표시하는 UI를 제공하여 사용자에게 피드백을 줍니다.

5. 초기 데이터 로드

컴포넌트가 마운트될 때 초기 데이터를 로드합니다:

useEffect(() => {
  fetchData(0);
}, []);

최적화 팁

무한 스크롤을 구현할 때 고려해야 할 몇 가지 최적화 방법이 있습니다:

  1. 데이터 캐싱: 이미 로드한 데이터를 캐싱하여 불필요한 네트워크 요청을 줄입니다.
  2. 이미지 지연 로딩: 화면에 보이는 이미지만 로드하여 메모리 사용을 최적화합니다.
  3. 데이터 페이징: 적절한 페이지 크기를 설정하여 네트워크 요청과 렌더링 성능 사이의 균형을 맞춥니다.
  4. 메모이제이션: React의 useMemouseCallback을 사용하여 불필요한 재렌더링을 방지합니다.
  5. 가상화: 많은 양의 데이터를 처리할 때는 FlatListRecyclerListView와 같은 가상화된 리스트 컴포넌트를 고려하세요.

FlatList를 사용한 대안

더 많은 성능 최적화가 필요하다면 ScrollView 대신 FlatList를 사용할 수 있습니다. FlatList는 화면에 보이는 항목만 렌더링하여 메모리 사용을 최적화합니다:

<FlatList
  data={allData}
  renderItem={renderItem}
  keyExtractor={(item) => item.id.toString()}
  onEndReached={loadMoreData}
  onEndReachedThreshold={0.1}
  ListFooterComponent={isLoadingMore ? <LoadingIndicator /> : null}
/>

FlatListonEndReached 속성을 통해 무한 스크롤을 더 쉽게 구현할 수 있게 해줍니다.

결론

무한 스크롤은 모바일 앱에서 사용자 경험을 향상시키는 강력한 패턴입니다.
React Native에서는 ScrollViewonScroll 이벤트나 FlatListonEndReached 이벤트를 활용하여 쉽게 구현할 수 있습니다. 데이터 캐싱, 지연 로딩, 가상화 등의 최적화 기법을 함께 사용하면 더욱 효율적인 무한 스크롤을 구현할 수 있습니다.

사용자가 끊김 없이 콘텐츠를 소비할 수 있도록 무한 스크롤을 구현하고, 앱의 성능과 사용자 경험을 향상시켜 보세요!

profile
궁금한 것, 했던 것, 시행착오 그리고 기억하고 싶은 것들을 기록합니다.

0개의 댓글