인프런 커뮤니티 질문&답변

이자이님의 프로필 이미지

작성한 질문수

Next + React Query로 SNS 서비스 만들기

useSelectedLayoutSegment로 ActiveLink 만들기

Next와 React-query의 prefetch에 대해

24.04.06 09:53 작성

·

883

0

안녕하세요 !
Next14 버전과 tanstack-qeury를 이용해 프로젝트를 진행하던 도중 궁금한 점이 생겨 질문드립니다.

Next의 서버 컴포넌트에서 data를 prefetching 하여 사용하려면 다음과 같은 단계를 밟아야 하는 것으로 알고 있습니다.

1. 서버 컴포넌트에서 queryClient.prefetchQuery를 사용해 데이터를 불러오고 이를 dehydrate하여 HydrationBoundary 내에 state로 넘겨준다.

2. 데이터를 사용하는 컴포넌트에서 useQuery로 동일한 데이터를 불러오면 해당 데이터는 prefetch 된 상태로 넘어와 이를 사용한다.

현재 이를 토대로 아래 예시코드와 같이 작성하여 사용중입니다.

이 때 하위 컴포넌트에서 prefetch한 데이터를 사용하려면 useQuery를 써야하기에, 'use client' 를 사용해야하고, 그렇게 되면 그 하위 컴포넌트도 전부 Client Boundary에 들어오게 되는 것으로 알고있는데, 그럼 "Next를 사용하며 얻을 수 있는 장점이 줄어들지 않나 ?" 라는 의문이 생겼습니다.

제가 사용법을 잘못 알고있다거나 Next의 개념에 대해 부족한걸까요 ?

또, HydrationBoundary로 감싸지 않고 queryClient.getQueryData를 이용해 직접 데이터를 가져와 이를 props로 전달해도 기능은 정상적으로 작동하는데, 이 둘의 차이점이 정확히 무엇인가요 ?

 

// 서버 컴포넌트

import {
  HydrationBoundary,
  dehydrate,
  QueryClient,
} from "@tanstack/react-query";
import { QUERY_KEY } from "@/constants";
import { requestGetPushAlarmList } from "@/apis/notification";
import NotificationClient from "./Client";

export default async function Page() {
  const queryClient = new QueryClient();

  await queryClient.prefetchQuery({
    queryKey: [QUERY_KEY.PUSH_LIST],
    queryFn: () => requestGetPushAlarmList({}),
  });

// const { rows: pushList } = queryClient.getQueryData([
    // QUERY_KEY.PUSH_LIST,
  // ]) as unknown as Rows<PushAlarm>; 예시 2. getQueryData로 데이터에 접근

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

    // <NotificationList pushList={pushList} /> 예시2. props로 직접 데이터 전달
  );
}

// 하위 컴포넌트

"use client";

import { useQuery } from "@tanstack/react-query";
import { requestGetPushAlarmList } from "@/apis/notification";
import { QUERY_KEY } from "@/constants";
import NotificationList from "./_components/NotificationList";
import ScreenBox from "@/components/ui/ScreenBox";
import Empty from "@/components/ui/Empty";

export default function NotificationClient() {
  const { data } = useQuery({
    queryKey: [QUERY_KEY.PUSH_LIST],
    queryFn: () => requestGetPushAlarmList({}),
    select: (data) => data.rows,
  });

  return (
    <>
      {!data?.length ? (
        <ScreenBox.CenterBody>
          <Empty message="알림이 없습니다." />
        </ScreenBox.CenterBody>
      ) : (
        <NotificationList pushList={data} />
      )}
    </>
  );
}


답변 2

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

2024. 04. 06. 10:58

네, useQuery를 사용하려면 클라이언트 컴포넌트여야하지만, 그건 리액트 쿼리를 쓰려면 어쩔 수 없는 부분입니다. 서버 컴포넌트만 쓰려면 리액트 쿼리를 걷어내면 되는 것이죠. 넥스트를 쓸 때는 최상단 컴포넌트는 서버 컴포넌트로 하고 최하단 컴포넌트는 클라이언트 컴포넌트로 하는 경우가 대부분입니다.

getQueryData 부분은 잘 모르겠는데요. ssr 데이터를 가져오는게 아니라 useQuery로 클라이언트에서 가져온 데이터를 다시 get하는게 아닌가, 비효율적인 것이 아닌가 합니다.

0

인프런 AI 인턴님의 프로필 이미지

2024. 04. 06. 09:56

안녕하세요, 인프런 AI 인턴입니다.

이자이님의 질문은 Next.js에서 React Query를 사용하여 데이터를 prefetch하는 방식과 이를 HydrationBoundary와 useQuery를 통해 관리하는 과정의 이해와 관련 있습니다. 여기에는 서버 컴포넌트와 클라이언트 컴포넌트 간의 데이터 관리, 그리고 Next.js의 장점을 최대한 활용하는 법에 대한 궁금증이 포함되어 있습니다.

비슷한 컨텍스트에서 질문을 한 이전 질문들 중 하나를 참고해보시면 도움이 될 것 같습니다.

-Next와 React-query의 prefetch에 대해에서는 React Query의 prefetch, dehydrate, 및 useQuery의 사용 방법과 의미에 대해 논의되었습니다. 미리 데이터를 불러오고, 클라이언트 사이드에서 해당 데이터의 재사용에 대한 질문으로, 이자이님의 궁금증과 유사한 맥락입니다.

-강의에서 진행된 React-query로 prefetchQuery와 서스펜스를 사용한 패턴에 대해서 궁금한게 있습니다! 이 질문에서는 prefetchQuery 사용과 서스펜스의 적용에 대한 궁금증을 다루고 있으며, 데이터를 서버 사이드에서 미리 불러오는 과정과 클라이언트에서의 활용에 대한 답변이 포함되어 있습니다.

특히, prefetchQueryHydrationBoundary, useQuery 등의 사용과 관련하여 Next.js의 서버사이드 렌더링(SSR) 기능과 tanstack-query 패키지의 기능을 접목하는 방법에 대한 궁금증을 가진 것 같습니다. 이러한 접근은 성능 최적화 및 사용자 경험 향상을 목표로 합니다.

prefetchQuery를 사용하는 주된 이유 중 하나는 초기 페이지 로드 시 필요한 데이터를 미리 서버에서 불러와 클라이언트에 전달하는 것입니다. 이 과정에서 dehydrate는 서버에서 불러온 데이터를 클라이언트로 전송하기 위한 직렬화 과정을 말하며, HydrationBoundary는 이러한 직렬화된 데이터를 클라이언트에서 사용할 수 있도록 하기 위한 맥락에서 사용됩니다.

useQuery를 통해 데이터를 불러오는 과정에서 HydrationBoundary 내에 의해 직렬화되었던 데이터가 활용되며, 이러한 방식을 통해 데이터를 효율적으로 관리하고 네트워크 요청을 줄일 수 있습니다. 이는 Next.js의 서버사이드 렌더링(SSR) 및 정적 사이트 생성(SSG)의 이점과 결합되어, 보다 빠른 페이지 로드 속도와 개선된 사용자 경험을 제공합니다.

getQueryData 를 사용한 접근 방법은 직접적으로 쿼리 클라이언트에서 데이터를 추출해 사용하는 것으로, 주로 서버 사이드에서 데이터의 상태를 확인하거나 관리할 때 유용하게 사용됩니다. 하지만 이 방법은 데이터를 클라이언트 사이드로 전달할 때 dehydrateHydrationBoundary를 사용하는 것에 비해 직접적이고 명시적인 데이터의 흐름을 제공하면서 특정 상황에서 더 편리할 수 있습니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.

현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏

추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.