문제의 발생

image.png

Next 프로젝트에서 위 페이지의 댓글 영역을 SSR 처리를 했었다. 그때는 다른 팀원들 코드를 볼 여유가 크게 없었는데 이제 와서 내 코드와 SSR을 구현한 방식이 다르다는걸 알았다.

import { getUserReviews } from "@/libs/gatherDetail";
import CommentsSection from "../../components/detail/comments-section/CommentsSection";
import ClientGather from "./ClientGather";
import { Review } from "@/types/reviews";

export default async function Detail({ params }: { params: { id: number } }) {
  const { id } = params;
  const initialReviews: { data: Review[] } = await getUserReviews({
    pageId: id,
    offset: 0,
    limit: 4,
  });

  return (
    <div className="min-h-screen-minus-nav bg-gray-100">
      <div className="min-h-screen-minus-nav mx-auto container max-w-[1200px] px-6 md:px-[102px] pt-10 bg-white">
        <ClientGather pageId={id} />
        <CommentsSection pageId={id} initialReviews={initialReviews} />
      </div>
    </div>
  );
}

이 코드는 내가 구현한 일부로, 초기 데이터를 props로 컴포넌트에 전달해 SSR을 구현한 방식이다.

간단하며 별도의 추가 설정이 필요 없다는 점이 장점이다. 다만, React Query를 사용하는 프로젝트에서는 SSR을 위해 Hydration이라는 기능을 제공하지만, 당시에는 이를 잘 알지 못해 적용하지 않았다.


문제에 접근하기

우선 Hydration이라는 기능을 적용하면 다음과 같은 이점을 얻을 수 있다

그러한 이점이 있다고 GPT가 설명하지만, 같은 프로젝트에서 다른 방식으로 기능을 적용하고 있다는 것이 마치 한국어로 쓰여진 책에 영어로 쓰여진 챕터가 끼어있는 것 같은 이질감을 주는 듯하여 더 일관된 방식으로 변경을 시도하려고 한다.

본격적으로 Hydration을 적용하기 전에 아래 네 가지 개념에 대해 이해할 필요가 있다.

  1. QueryClient: 서버에서 데이터를 가져오고, 캐시에 저장하는 객체
  2. prefetchQuery: 특정 데이터를 미리 가져와 캐시에 저장하는 함수.
  3. dehydrate: prefetch된 데이터를 직렬화하여 SSR/SSG 환경에서 클라이언트로 전달
  4. HydrationBoundary: queryClient.prefetchQuery를 통해 미리 가져온 데이터를 클라이언트에서 그대로 이어서 사용할 수 있도록 준비해주고, 기존 데이터와 병합해 중복 호출을 감소.

https://tanstack.com/query/latest/docs/framework/react/guides/ssr