인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

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

 키키님의 프로필 이미지
 키키

작성한 질문수

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

react-query SSR 설정하기

리액트 쿼리를 활용한 SSR으로 데이터 조회하기

해결된 질문

작성

·

81

·

수정됨

0

안녕하세요!

제가 강의를 모두 수강하고 프로젝트에서 리액트 쿼리를 통해 SSR을 적용하려고 하고 있습니다. 아래 코드는 fetchAPISever 함수를 통해 백엔드 api로부터 데이터를 요청하는 함수입니다. 이때fetchAPIsever 함수는 next/headercookies()를 통해 사용자의 토큰이 있으면 토큰을 넣어서 api를 요청하는 함수입니다.

export const getBestAndPendingReviews =
  async (): Promise<ReviewePageResponse> => {
    const res = await fetchAPIServer('/api/review', 'GET');
    if (res.code === 'SUCCESS') {
      return res.result;
    }
    throw new Error(
      `리뷰 페이지 데이터 불러오기 실패 ${res.code}-${res.message}`,
    );
  };

아래 코드는 리뷰 페이지에서 서버 사이드 렌더링으로 보여주기 위해 리액트 쿼리로 Hydration을 적용한 코드입니다.

// src\app\reviews\page.tsx
import {
  HydrationBoundary,
  QueryClient,
  dehydrate,
} from '@tanstack/react-query';
import ReviewDashboard from './_components/ReviewDashboard';
import { getBestAndPendingReviews } from './_lib/getBestAndPendingReviews';

export default async function ReviewsPage() {
  const queryClient = new QueryClient();
  await queryClient.prefetchQuery({
    queryKey: ['reviews', 'best'],
    queryFn: getBestAndPendingReviews,
  });
  const dehydrateState = dehydrate(queryClient);
  return (
    <HydrationBoundary state={dehydrateState}>
      <ReviewDashboard />
    </HydrationBoundary>
  );
} '

 

<ReviewDashboard/> 컴포넌트에서 UserInfo 컴포넌트를 반환하도록 설정하고 useQuery 훅을 사용하려 했으나, fetchAPIServer 함수에서 next/headers 를 import하고 있어서 클라이언트 컴포넌트에서 사용할 수 없다는 에러가 발생했습니다. 그러면 SSR을 적용하기 위해서는 getQueryData를 사용해야하는 걸까요..?

import { QueryClient } from '@tanstack/react-query';
import { ReviewePageResponse } from '../_lib/getBestAndPendingReviews';

export default function UserInfo() {
  const queryClient = new QueryClient();
  const reviews = queryClient.getQueryData<ReviewePageResponse>([
    'reviews',
    'best',
  ]);

  const { total } = reviews!;
  if (!reviews) return <p>리뷰가 없습니다.</p>;

  console.log('reviews', reviews);
  return <p>작성한 리뷰 {total || 0}</p>;
} 

  또는 useQuery를 쓰되 쿼리 함수를 Promise.Resolve()로 서버에서 전달 받은 데이터를 받는게 나은가 요?

'use client';

import { useQuery } from '@tanstack/react-query';

export default function UserInfo() {
  const { data: reviews, isLoading } = useQuery({
    queryKey: ['reviews', 'best'],
    queryFn: () => Promise.resolve(), // 서버 데이터 재활용
  });

  if (isLoading) return <p>Loading...</p>;
  if (!reviews) return <p>리뷰가 없습니다.</p>;
  const { total } = reviews!;

  console.log('reviews', reviews);
  return <p>작성한 리뷰 {total || 0}</p>;
}

답변 2

0

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

제가 getUser, getUserServer 이런 식으로 나눴던 것처럼 클라이언트용 함수와 서버용 fetch 함수를 구분하시면 됩니다.

 키키님의 프로필 이미지
 키키
질문자

답변 감사합니다! 서버에서 실행할 함수와 클라이언트 환경에서 실행할 함수를 분리하니 잘 작동이 됩니다. 그럼 리뷰 페이지에서 서버 환경에서 getBestAndPendingReviewsServer를 호출하여 데이터를 패칭하고 react Query의 prefetchQuerydehydrate를 통해 데이터를 클라이언트에 전달하는 역할을 한다는 것은 이해했습니다. 그럼 <UserInfo/> 컴포넌트에서 useQuery로 쿼리 함수가 getBestAndPendingReviews로 적용되어 있지만 실제로는 해당 쿼리 함수를 실행하지 않고 Hydration된 데이터를 그대로 사용해서 SSR이 적용되는 것으로 이해했는데 이게 맞을까요?

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

네 맞습니다. 다만 staleTime도 적절하게 늘려주셔야 합니다.

 키키님의 프로필 이미지
 키키
질문자

넵 알겠습니다! 감사합니다!!

0

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

SSR(Server-Side Rendering)을 사용하여 React Query와 함께 데이터를 Fetch하고 Hydration하여 페이지를 구성하려고 하시는군요. 이 과정에서 몇 가지 고려해야 할 사항이 있습니다.

1. React Query와 SSR

React Query를 사용하여 SSR을 구현할 때 getStaticPropsgetServerSideProps와 같은 Next.js 서버 측 데이터 펫칭 방법을 사용하는 것이 일반적입니다. 이 방법을 통해 서버 측에서 데이터를 미리 가져와 클라이언트에 전달할 수 있게 됩니다.

2. HydrationBoundary와 initialData

현재 코드를 보면 queryClient.prefetchQuery로 미리 데이터를 가져오는 과정은 잘 되어있는 것 같습니다. 이 데이터는 dehydrate를 통해 지연 상태로 만들어지고, 클라이언트 측 컴포넌트(<HydrationBoundary>)에 전달됩니다.

3. fetchAPISever와 클라이언트 환경

문제의 핵심은 fetchAPISever를 통해 서버 측에서 데이터를 가져오는 부분입니다. 이 함수가 서버 전용임에도 클라이언트 컴포넌트에서 사용되면서 발생한 에러는 예상된 상황입니다. 보통 클라이언트에서 useQuery 훅을 사용하여 데이터를 다시 Fetch하도록 해야합니다. 다음과 같은 방법으로 해결해 볼 수 있습니다:

서버 사이드에서 데이터 미리 가져오기

  • 서버 측 코드 (getBestAndPendingReviews 등)에서는 서버 전용 메소드를 사용하여 데이터를 가져옵니다.
  • 클라이언트 측에서 useQuery를 사용할 때, 서버에서 받아온 데이터를 초기화 데이터(initialData)로 설정하여 네트워크 요청을 최소화할 수 있습니다.

4. SSR 효율성 체크

네트워크 탭에서 Loading..만 발생하는 경우는 데이터를 클라이언트에서 다시 요청하게 되는 상황일 수 있습니다. SSR 적용 여부를 확인하려면 브라우저 네트워크 패널에서 초기 HTML 응답에 실제 데이터가 포함되어 있는지를 살피면 됩니다.

기존 답변 참고

아래 두 게시물에서 비슷한 문제 및 해법을 다루었습니다:
- “개인 팀프로젝트 중에 NextJS + react-query 관련 궁금증입니다.”
- “react-query ssr설정”

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

 키키님의 프로필 이미지
 키키

작성한 질문수

질문하기