Next.js는 SSR과 SSG를 지원하는 강력한 프레임워크이며, React Query는 API 호출 및 캐싱을 자동으로 처리해주는 매우 강력한 상태 관리 라이브러리입니다. 이 둘의 조합은 매우 강력하지만, 서버에서 가져온 데이터를 클라이언트로 자연스럽게 넘기기 위한 고민은 여전히 존재합니다.
React Query의 Hydrate
컴포넌트를 활용하면 이 문제를 깔끔하게 해결할 수 있습니다. 이번 글에서는 Hydrate의 개념, 동작 원리, 그리고 실제로 어떻게 Next.js 프로젝트에 적용하는지를 상세하게 설명합니다.
서버 사이드 렌더링을 사용하는 경우, 서버에서 데이터를 미리 받아와 화면을 렌더링합니다. 그러나 클라이언트는 이 상태를 알지 못하므로, React Query는 동일한 데이터를 클라이언트에서 다시 요청하게 됩니다. 이로 인해 불필요한 중복 요청과 느린 사용자 경험이 발생할 수 있습니다.
Hydrate
를 사용하면 서버에서 가져온 데이터를 클라이언트 React Query의 QueryClient
상태에 미리 주입할 수 있으므로, 다음과 같은 이점이 있습니다:
Hydrate는 서버에서 React Query의 상태(QueryClient 내부 상태)를 dehydrate()
함수를 통해 JSON 직렬화 가능한 형태로 변환한 뒤, 클라이언트에서 Hydrate
컴포넌트를 통해 이를 QueryClient
에 복원하는 방식으로 동작합니다.
이 과정을 요약하면 다음과 같습니다:
dehydrate
함수로 직렬화getServerSideProps
나 getStaticProps
를 통해 props
로 전달Hydrate
컴포넌트로 역직렬화 후 QueryClient
에 주입이렇게 주입된 초기 캐시는 클라이언트에서 useQuery
훅으로 접근 시 바로 사용되며, 같은 queryKey
와 동일한 fetch 함수를 사용하는 경우 새로운 요청 없이 즉시 캐시 데이터를 보여줍니다.
// pages/index.tsx
import { dehydrate, QueryClient, useQuery } from '@tanstack/react-query';
import { GetServerSideProps } from 'next';
const fetchData = async () => {
const res = await fetch('https://api.example.com/data');
return res.json();
};
export const getServerSideProps: GetServerSideProps = async () => {
const queryClient = new QueryClient();
await queryClient.prefetchQuery(['data'], fetchData);
return {
props: {
dehydratedState: dehydrate(queryClient),
},
};
};
export default function Home() {
const { data, isLoading } = useQuery(['data'], fetchData);
return <div>{isLoading ? 'Loading...' : JSON.stringify(data)}</div>;
}
_app.tsx
에서 Hydrate로 상태 복원// pages/_app.tsx
import { Hydrate, QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { useState } from 'react';
import type { AppProps } from 'next/app';
export default function MyApp({ Component, pageProps }: AppProps) {
const [queryClient] = useState(() => new QueryClient());
return (
<QueryClientProvider client={queryClient}>
<Hydrate state={pageProps.dehydratedState}>
<Component {...pageProps} />
</Hydrate>
</QueryClientProvider>
);
}
Hydrate
는 반드시 QueryClientProvider
내부에 위치해야 합니다.dehydrate
로 직렬화된 데이터는 JSON으로 직렬화 가능한 값이어야 합니다.queryKey
와 fetch 함수의 구현
이 서버와 클라이언트에서 동일해야 캐시가 재활용됩니다.getStaticProps
와 함께 사용하여 정적 페이지도 빠르게 구성 가능persistQueryClient
와의 차이: Hydrate
는 SSR 데이터 복원에 사용되며, persistQueryClient
는 로컬 스토리지 등을 통한 캐시 지속에 활용됨React Query와 Next.js의 조합에서 Hydrate
는 단순한 옵션이 아니라 꼭 활용해야 할 기능입니다. 서버에서 가져온 데이터를 클라이언트와 자연스럽게 이어주어 중복 요청을 방지하고, UX를 극대화하며, 성능까지 향상시켜주는 고마운 존재입니다.
Next.js 프로젝트에서 SSR을 적용하고 있다면, Hydrate
를 반드시 고려해 보세요. 서버 상태 관리의 끝판왕으로, 더 빠르고 안정적인 웹 애플리케이션을 만들 수 있습니다.
링크 드라퍼는 단순한 저장 툴이 아닙니다.
정리하고, 수정하고, 다시 꺼내보게 만드는 링크 관리 도구를 지향하고 있습니다.
• 🔗 빠르고 간편한 링크 저장
• 🧠 저장한 링크를 폴더별로 정리
• 🌐 폴더를 친구에게 공유 가능
• ⚡ 크롬 익스텐션 원클릭 저장
👉 링크 드라퍼 베타 체험하러 가기
👉 크롬 웹스토어에서 설치하기
서비스 업데이트
기능 꿀팁
카카오톡 채널을 통해 빠르게 받아보세요!
👉 카카오톡 채널 추가하기