[nextJS] prefetchQuery

Yeong·2025년 10월 15일

1. 서버 컴포넌트 준비

prefetch & dehydrate는 useQuery를 사용하는 컴포넌트 바로 상위에서 적용해 주는 것이 좋다.
한 번 상위에서 적용하면 모든 하위 컴포넌트에 전역적으로 적용이 가능하지만, 모든 컴포넌트에서 해당 쿼리 데이터를 미리 불러오게 되기 때문에 불필요한 데이터 로딩이 이뤄질 수 있기 때문이다.

// layout.tsx

import { dehydrate, QueryClient } from "@tanstack/react-query";
import { HydrationBoundary } from "@tanstack/react-query";
import { QnALoungeApi } from "@/domains/board/qna-lounge";

export default async function TestLayout({
     children,
   }: {
  children: React.ReactNode;
}) {
  const queryClient = new QueryClient();

  const key = ["qa", 1, 10];

  await queryClient.prefetchQuery({
    queryKey: key,
    queryFn: () => QnALoungeApi.getQnALounges({ page: 1, size: 10 }),
  });

  return (
    <HydrationBoundary state={dehydrate(queryClient)}>
      {children}
    </HydrationBoundary>
  );
}

prefetch와 hydration 방식은 서버에서 페이지 렌더링 시 데이터를 가져오고 직렬화하여 페이지와 함께 클라이언트에 내려보내는 방식이다.

2. 하위 클라이언트 컴포넌트

클라이언트 컴포넌트는 클라이언트 측에서만 렌더링 될 것 같지만, Nextjs에서는 서버에서도 렌더링이 가능하다.

1. 전체 페이지 로드 시

전체 페이지 로드는 사이트의 페이지를 처음 방문하거나 새로고침을 통해 전체 페이지를 요청하는 경우이다.
prefetch를 사용하면 서버의 페이지 렌더링 단계에서 데이터를 fetching하고 클라이언트 컴포넌트의 query data로 전달된다. 덕분에 클라이언트 컴포넌트지만 초기 html을 서버에서 렌더링할 수 있다.

prefetch를 사용하지 않으면 서버에서는 아직 data가 없으므로 데이터가 없을 때는 아래와 같이 지정해 둔 fallback을 렌더링한다.

"use client";

import React from "react";
import { useQuery } from "@tanstack/react-query";
import { QnALoungeApi } from "@/domains/board/qna-lounge";

const MyComponent = () => {

  const {data, isLoading} = useQuery({
    queryKey: ["qa", 1, 10],
    queryFn: () => QnALoungeApi.getQnALounges({ page: 1, size: 10 }),
  })

  if(isLoading) return "로딩중";

  return (
    <>
      {data?.qa?.content?.map((item) => (
        <div key={item.id}>
          {item.title}
        </div>
      ))}
    </>
  );
};

export default MyComponent;

서버 컴포넌트에서 queryClient.prefetchQuery를 사용해 데이터를 불러오고 이를 dehydrate하여 하위 컴포넌트를 HydrationBoundary로 감싸 state를 넘겨 준다.
데이터를 사용하는 컴포넌트에서 useQuery로 동일한 데이터를 불러오면 해당 데이터는 prefetch 된 상태로 넘어와 이를 사용한다.

0개의 댓글