useInfiniteQuery 알아 보기

useInfiniteQuery를 학습해보자


useInfiniteQuery

무한 스크롤 구현을 하다 보면, 데이터를 페이지 단위로 나누고, 스크롤이 끝에 닿을 때마다 다음 데이터를 불러오는 흐름을 구현하게 된다. 유용하게 사용할 수 있는 도구가 바로 **React Query의 useInfiniteQuery**이다


useInfiniteQuery@tanstack/react-query에서 제공하는 훅으로, 페이징 또는 커서 기반의 데이터를 쉽게 구현 할 수 있게 해준다.

const {
  data,
  isLoading,
  isError,
  fetchNextPage,
  hasNextPage,
  isFetchingNextPage,
} = useInfiniteQuery({
  queryKey: ["my-query-key"],
  queryFn: ({ pageParam = initialValue }) => fetchFunction(pageParam),
  getNextPageParam: (lastPage, allPages) => nextPageParam,
});

옵션 알아보기

옵션명설명
queryKey쿼리의 고유 키 (캐싱/리페치 구분용)
queryFn데이터를 실제로 패칭하는 함수, pageParam으로 현재 페이지 정보를 받음
getNextPageParam다음 페이지 호출에 사용할 pageParam을 반환하는 함수 , 데이터를 받은 후 getNextPageParam을 실행하고 추가로 가져올 데이터가 있는지 판별하는 옵션
initialPageParam최초에 사용할 pageParam의 초기값 (기본은 undefined)

🧪 예제: Star Wars API로 무한 스크롤 구현하기

import { useInfiniteQuery } from "@tanstack/react-query";
 
const fetchUrl = async (url) => {
  const res = await fetch(url);
  return res.json();
};
 
const initialUrl = "https://swapi.py4e.com/api/species/";
 
const { data, isLoading, isError, isFetching, fetchNextPage } =
  useInfiniteQuery({
    queryKey: ["sw-species"],
    queryFn: ({ pageParam = initialUrl }) => fetchUrl(pageParam),
    getNextPageParam: (lastPage) => lastPage.next || undefined,
  });

Flow:

  1. pageParam이 없을 경우 initialUrl로 첫 fetch 실행
  2. 응답 결과에 있는 next 값을 getNextPageParam이 추출
  3. fetchNextPage() 호출 시, nextpageParam으로 넘겨 다음 데이터를 요청

useInfiniteQuery를 사용할 땐 첫 페이지 자동 호출 옵션이 켜져 있는지 꼭 확인하자.

react-infinite-scroller나 유사 라이브러리와 함께 사용할 경우, useInfiniteQuery가 첫 페이지를 자동 호출하고 InfiniteScrollinitialLoad로 호출해 두 번 호출되는 문제가 있다. 따라서 useInfiniteQuery를 사용할땐 초기 호출되는 함수를 막아서 사용하자.

<InfiniteScroll
  // InfiniteScroll 라이브러리 작동 방식은 데이터의 첫 페이지를 자동으로 호출한다 그래서 초기 호출을 막아줬다
  initialLoad={false}
  loadMore={() => {
    if (!isFetching) {
      fetchNextPage();
    }
  }}
  hasMore={!!data?.pages[data.pages.length - 1]?.next}
/>

정리

장점설명
페이징 API와 궁합이 좋음REST API뿐 아니라 커서 기반 API에도 적합
캐싱 & 상태 관리 내장기존 페이지 데이터 유지하면서 새로 불러오기 가능
getNextPageParam으로 유연한 페이징 가능숫자 기반, 커서 기반 모두 구현 가능

언제 사용해야 할까?

  • 페이지 단위 데이터를 불러오고 싶을 때 (서버 데이터에선 page로 불러오는 데이터가 많기 때문에 자주 사용한다.)
  • 무한 스크롤 UX가 필요한 앱 (게시판, 피드, 상품 목록 등)
  • 커서 기반 API와 연동할 때 (예: Supabase, Firebase, GraphQL 등)