Next.js

NextJS에서 react-query SSR 데이터 사용하기

Kir93 2022. 6. 7. 15:18
728x90
반응형

react-query는 개인적으로 요즘 가장 핫한 라이브러리라고 생각한다.

redux의 thunkAPI 등을 많이 사용했던 이전의 방식에서 react-query를 통해 get과 post방식의 query를 손쉽게 사용할 수 있으면서 데이터를 손쉽게 cache 할 수 있다는 점에서 무척이나 매력적인 라이브러리라고 할 수 있다.

 

nextJS는 요즘에는 react개발자라면 모두 알 정도로 유명한 프레임워크이다.

그리고 nextJS를 유명하게 만든 가장 큰 요소 중 하나는 SSR이라고 생각하는데, 아쉽게도 react-query의 hook의 경우 SSR이 아닌 CSR방식으로 데이터를 가지고 온다.

 

이제 본격적으로 react-query의 데이터를 SSR로 사용할 수 있는 2가지 방법에 대해 설명하겠다.

 

1. InitialData

가장 먼저 초기에 생각했고, 지금도 많이 사용하고 있는 방법인 initialData를 사용하는 방법이다.

이 방법의 경우 무척 직관적인 방법으로 작업하는 프로젝트에서 SSR이 적은 경우 자주 사용하고 있다.

react-query의 기본값으로 SSR의 데이터를 넣어주는 것으로 데이터를 사용하는 간단한 방법이다.

// apis.ts
...
export const getFeeds = () => axios.get('https://api.test.com/feeds');
...

// pages/feed-list.tsx

const Test = (props) => {
  const { data } = useQuery('feeds', getFeeds, { initialData: props.feeds });
  ...
}

export async function getServerSideProps() {
  const feeds = await getFeeds();
  return { props: { feeds } };
}

 

2. Hydration

본격적으로 SSR이 중요하고 다양한 곳에서 사용되는 프로젝트의 경우 많이 사용하는 방법으로 한 번의 설정 뒤로는 간편하게 SSR을 사용할 수 있다는 장점이 있다.

redux를 사용했던 사람들이라면 이 방법이 더욱 익숙할 수도 있을 것 같다.

// pages/_app.tsx

function MyApp({ Component, pageProps }) {
  const [client] = useState(() => new QueryClient());
  
  return (
    <QueryClientProvider client={client}>
       <Hydrate state={pageProps.dehydratedState}>
         <Component {...pageProps} />
       </Hydrate>
     </QueryClientProvider>
  );
};

// apis.ts

export const getFeeds = () => axios.get('https://api.test.com/feeds');

// pages/feed-list.tsx

const Test = (props) => {
  const { data } = useQuery('feeds', getFeeds);
  ...
}

export async function getServerSideProps() {
  const queryClient = new QueryClient();
  await queryClient.prefetchQuery('feeds', getFeeds);
  
  return {
     props: {
       dehydratedState: dehydrate(queryClient),
     },
   }
 }

_app.tsx에 SSR 설정을 한 번 해두면 다른 모든 페이지에서 위와 같은 방법으로 사용할 수 있다.

 

PS. Hydration에서 serializing error 해결하기

Error serializing `.dehydratedState.queries[0].queryKey[1]` returned from `getServerSideProps` in "/feed-list". Reason: `undefined` cannot be serialized as JSON. Please use `null` or omit this value.

두 번째 방법을 사용할 경우 가끔 위와 같은 에러가 생기는 경우가 많다.

이 에러가 생기는 이유는 dehydrate(queryClient)의 값 중에 undefined인 값이 있어서 발생하는 에러로 생각보다 간단하게 해결 가능하다.

...
dehydratedState: JSON.parse(JSON.stringify(dehydrate(queryClient))),
...

위와 같이 코드를 수정해 주면 undefined였던 요소들이 모두 null값으로 변경되어 에러가 해결된다.

 

반응형
반응형