⚛️ 리액트 개발 환경 세팅: CRA vs Vite

⚛️ 리액트 개발 환경 세팅: CRA vs Vite

React Query로 무한 스크롤(Infinite Scroll) 우아하게 구현하기 🚀

복잡한 스크롤 이벤트는 이제 그만! useInfiniteQuery 하나로 UX와 DX를 모두 잡아봅시다.

웹 서핑을 하다가 페이지 하단에 닿았을 때, 자연스럽게 다음 콘텐츠가 로딩되는 경험을 해보신 적이 있으신가요?
인스타그램, 트위터(X), 핀터레스트 등 우리가 자주 쓰는 앱들은 대부분 이런 '무한 스크롤(Infinite Scroll)' 방식을 채택하고 있습니다.

🤔 개발자의 고민:
"하지만 이걸 직접 구현하려면 스크롤 위치 계산, 데이터 병합, 로딩 상태 관리까지... 코드가 너무 복잡해지지 않나요?"

맞습니다. 순수 리액트(React) 상태 관리로만 구현하면 꽤나 골치 아픈 작업이 됩니다.
하지만 React Query(TanStack Query)를 사용하면, 마법처럼 간결하게 이 기능을 구현할 수 있습니다.
오늘은 useInfiniteQuery를 활용한 무한 스크롤 구현법을 아주 쉽게 풀어드리겠습니다.


🧐 1. 왜 무한 스크롤에 React Query를 쓸까요?

기존 방식과 React Query 방식의 차이를 이해하면, 왜 우리가 이 도구를 배워야 하는지 명확해집니다.
데이터를 계속해서 불러와야 하는 무한 스크롤의 특성상, '서버 상태 관리'가 핵심이기 때문입니다.

구분 기존 방식 (useEffect + State) React Query (useInfiniteQuery)
데이터 관리 기존 배열에 새 데이터를 수동으로 합침 (concat 등) 자동으로 페이지별 데이터를 캐싱 및 병합
로딩/에러 상태 isLoading, isError 변수를 직접 선언 및 관리 직관적인 상태 플래그 제공 (isFetchingNextPage 등)
다음 페이지 로직 page 번호를 state로 관리하며 직접 증가시킴 getNextPageParam으로 다음 커서 자동 관리

표에서 보듯이, React Query는 반복적이고 지루한 작업들을 알아서 처리해 줍니다.
우리는 오직 '어떤 데이터를 가져올 것인가'에만 집중하면 되는 것이죠.


🛠️ 2. useInfiniteQuery 핵심 3요소

무한 스크롤을 구현하기 위해 꼭 알아야 할 세 가지 옵션이 있습니다.
이 세 가지만 기억하면 구현의 80%는 끝난 셈입니다.

1️⃣ queryKey (쿼리 키)

데이터를 식별하는 고유한 이름표입니다. 예: ['posts', 'infinite']

2️⃣ queryFn (쿼리 함수)

실제로 서버에서 데이터를 가져오는 비동기 함수입니다. 이곳에서 pageParam을 받아 API에 전달합니다.

3️⃣ getNextPageParam (다음 페이지 계산)

현재 불러온 데이터를 보고, "다음 페이지가 있는지, 있다면 몇 번인지" 결정하는 함수입니다.


💻 3. 실전 구현: 코드로 살펴보기

이제 실제 코드를 작성해 보겠습니다.
가장 일반적인 패턴인 Intersection Observer(화면 감지)를 이용해 스크롤이 바닥에 닿으면 자동으로 데이터를 부르는 방식입니다.

// 1. 데이터 패칭 함수 정의 const fetchProjects = async ({ pageParam = 1 }) => { const res = await fetch('/api/projects?cursor=' + pageParam); return res.json(); } // 2. 컴포넌트 내부에서 Hook 사용 const { data, fetchNextPage, hasNextPage, isFetchingNextPage, } = useInfiniteQuery({ queryKey: ['projects'], queryFn: fetchProjects, getNextPageParam: (lastPage, pages) => { // 다음 페이지가 있으면 그 값을 반환, 없으면 undefined return lastPage.nextCursor; }, })

위 코드는 useInfiniteQuery의 기본 뼈대입니다.
여기서 fetchNextPage 함수가 핵심입니다. 사용자가 스크롤을 내려서 특정 지점에 도달했을 때, 이 함수만 실행시켜주면 됩니다.

📌 UI 연결하기 (Tip)

가장 쉬운 방법은 react-intersection-observer 라이브러리의 <InView /> 컴포넌트를 리스트 맨 아래에 두는 것입니다.

  • 리스트의 맨 마지막에 투명한 div(관찰 대상)를 배치합니다.
  • div가 화면에 보이면(InView), fetchNextPage()를 실행합니다.
  • isFetchingNextPage 상태를 이용해 로딩 스피너를 보여주면 UX가 훨씬 좋아집니다.

✨무한한 가능성을 향해

React Query를 활용한 무한 스크롤 구현, 생각보다 어렵지 않죠?
이제 여러분은 복잡한 스크롤 계산 로직에서 벗어나, 데이터와 사용자 경험에만 집중할 수 있게 되었습니다.

📝 오늘의 핵심 요약

  1. 무한 스크롤은 useInfiniteQuery 훅을 사용하면 매우 효율적이다.
  2. getNextPageParam 함수를 통해 다음 데이터를 불러올 기준(커서)을 정한다.
  3. 화면 하단 감지는 Intersection Observer를 활용하여 자동 로딩을 구현한다.

댓글 쓰기