inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

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

react-query SSR 설정하기

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

해결된 질문

289

 키키

작성한 질문수 5

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>;
}

react next.js react-query next-auth msw

답변 2

0

제로초(조현영)

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

0

 키키

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

0

제로초(조현영)

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

0

 키키

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

0

인프런 AI 인턴

안녕하세요, 인프런 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설정”

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

캡처링부분 질문있습니다.

0

76

2

깃에 소스코드를 찾을 수 없습니다.

0

113

2

useInfiniteQuery promise와 react use 사용시 페이지 무한 로딩

0

98

1

import 파일 경로를 찾지 못 해서 에러가 발생합니다.

0

111

2

css 라이브러리 추천 부탁드립니다

0

141

2

팔로우 추천 목록이 빈 배열로 들어옵니다.

0

133

1

게시물 업로드 시 userId가 undefined로 들어가는 오류

0

119

1

useSuspenseQuery 사용 시 SSR 401 이슈 관련

0

172

1

리액트 쿼리 useinfinitequery 무한스크롤 구현 시 페이지가 이동할 경우 데이터가 보존되게 할 수 있나요??

0

184

3

폴링이 필요없는 이유

0

93

2

next Request Memoization과 react cache

0

110

2

seo 최적화 기준은 데이터 fetching인가요 아님 데이터 렌더링인가요?

0

84

2

next.js 서버fetch 에러 fallback ui 구현 방법

0

173

2

프레임워크 여론 파악법

0

125

2

필터옵션이 많은 페이지에서 서버 fetch를 하는게 맞는걸까요??

0

103

2

서버 fetch suspense 로 감싸고 새로고침 시 잠시 빈 화면이 노출된 후 fallback ui가 노출됩니다.

0

102

2

template.tsx 내 서버fetch 응답값과 클라이언트 컴포넌트 상태값 싱크가 맞지 않는 이슈

0

66

2

Auth.js 사용 시 authorize 함수가 호출되지 않습니다

0

132

2

next.js 에서 로그인에 관하여

0

139

1

Next의 route handler에 대한 질문이 있습니다.

0

101

2

게시판 리스트 만들때 use client를 어디서부터 집어넣어야할지 모르겠습니다

0

98

2

프라이빗 폴더를 해야 하는 이유가 모호한 것 같아요.

0

85

2

vanilla-extract 못찾는 문제

0

230

2

fetch 캐싱과 revalidate 관련

0

85

2