본문 바로가기
React

Next.js + tanstack-query(react-query)로 server-side-rendering(ssr) 구현하기

by 도현위키 2023. 6. 2.

nextjs

 

들어가며

Next.js와 tanstack-query(react-query)를 이용해서 ssr을 구현해보려고 한다. Next.js를 이용하여 데이터를 서버에서 fetch 해서 렌더링을 했을 경우에 layout shift 현상이 없어지고, 초기 로드했을 때 데이터가 바로 보이기 때문에 ux적으로 개선이 된다.

 

layout shift란 

layout shift는 데이터가 뒤늦게 로드가 되어 빈화면이 발생하고, 화면에서 ui가 밀리는 현상을 의미한다. layout shift는 ui/ux 경험을 해치고 사용자가 페이지 콘텐츠에서 갑작스러운 이동을 경험하게 된다. 간단한 예시로는 화면에서 아무것도 보이지 않고, 데이터가 로드가 된 이후에 갑자기 데이터가 보이는 현상이 layout shift이다. 이러한 layout shift를 개선하는 방법으로는 ssr과 스켈레톤 ui가 있다.

 

개발 환경 

- next.js 13.4.4 (app directory x)
- @tanstack/react-query 4.29.12
- axios 1.4.0

 

 

클라이언트 사이드 렌더링

먼저 client-side-rendering으로 데이터를 받아오면 아래와 같다.

// api/posts
const getPost = async () => {
  const res = await axios.get("https://jsonplaceholder.typicode.com/posts");
  return res.data;
};




// pages/index.tsx
export default function Home() {
    const { data } = useQuery(["posts"], getPost)
    console.log(data)
    return {
        ....
    }
}

 

 

위의 console.log(data)에 찍힌 값은 아래와 같이 나올 것이다.

// undefined

// undefined

// [{userId: 1}, {userId: 2} ....]

 

data를 fetch 하기 이전에는 undefined가 나올 것이고 data가 fetch가 완료되면 완료된 data가 찍히게 될 것이다.

이렇게 되면 위에 말한 것과 같이 layout shift현상이 발생한다.

 

layout shift

 

 

서버 사이드 렌더링

그렇다면 데이터를 서버에서 받아와서 서버에서 렌더링을 시켜보자.

먼저 react-query를 이용하여 서버에서 데이터를 fetching 하기 위해서는 provider에 아래와 같은 작업이 필요하다

// _app.tsx
<QueryClientProvider client={queryClient}>
    <Hydrate state={pageProps.dehydratedState}>
        <Component {...pageProps} />
    </Hydrate>
 </QueryClientProvider>

pageProps로 서버에서 전달받은 데이터를 Hydrate라는 컴포넌트에 주입해 주고 해당 컴포넌트로 <Componet>를 감싸주면 된다.

 

 

이제 준비는 완료되었고 페이지에서 데이터를 prefetch 하는 작업을 해보겠다.

 

// api/post

export const prefetchPost = async (qc: QueryClient) => {
  await qc.prefetchQuery(["posts"], getPost);
};



// pages/index.tsx
export const getServerSideProps = async () => {
  const qc = new QueryClient();
  await prefetchPost(qc);

  return {
    props: {
      dehydratedState: JSON.parse(JSON.stringify(dehydrate(qc))),
    },
  };
};

 

 

위와 같이 작업을 하게 되면 서버에서 data를 미리 prefetch 받아와서 query에 데이터를 미리 넣게 된다.

console.log(data)에서도 더 이상 undefined는 찍히지 않고 아래 동영상과 같이... loading 표시도 보이지 않게 된다.

 

 

 

댓글