들어가며
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현상이 발생한다.
서버 사이드 렌더링
그렇다면 데이터를 서버에서 받아와서 서버에서 렌더링을 시켜보자.
먼저 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 표시도 보이지 않게 된다.
'React' 카테고리의 다른 글
React 18 useSyncExternalStore를 이용하여 전역 상태 구현하기 ex) recoil, zustand, jotai (2) | 2023.06.03 |
---|---|
React 18 useDeferredValue와 useTransition 이란? (0) | 2023.05.28 |
React Testing Library를 이용한 Custom Hooks 테스팅 (1) | 2022.03.28 |
React Testing Library(RTL) 사용법 (0) | 2022.03.28 |
[컴포넌트 재활용하기] - Button (2) | 2022.02.19 |
댓글