Next.js 서버 컴포넌트와 Tanstack Query를 활용해 성능 최적화하는 방법에 대해 소개해보려고 합니다.
서버 - 클라이언트 데이터 최적화 📖
✨ Next.js의 서버 컴포넌트에서 데이터를 미리 패치해 클라이언트 컴포넌트로 넘겨준다면 초기 렌더링을 개선할 수 있습니다. ✨
기존 코드
기존에는 클라이언트 컴포넌트에서 `Tanstack Query`를 사용해 데이터를 패칭을 했습니다.
const MainComponent = () => {
const userId = useUserId();
const { data: tourismList, isPending isError } = useGetTourismListQuery(userId);
...
}
리팩토링 코드
`HydrationBoundary`와 `dehydrate`를 활용해 스탬프 페이지를 최적화한 코드입니다.
// layout.tsx
export default async function StampLayout({ children }: { children: React.ReactNode }) {
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 1000
}
}
});
const user = await getUser();
if (user) {
await queryClient.prefetchQuery({
queryKey: QUERY_KEY.STAMP_LIST(user.id),
queryFn: () => getStampList(user.id)
});
}
return (
<HydrationBoundary state={dehydrate(queryClient)}>
<MapProvider>{children}</MapProvider>
</HydrationBoundary>
);
}
핵심 코드 📖
1. 서버에서 데이터 미리 패치
const user = await getUser();
if (user) {
await queryClient.prefetchQuery({
queryKey: QUERY_KEY.STAMP_LIST(user.id),
queryFn: () => getStampList(user.id)
});
}
로그인한 사용자의 스탬프 데이터를 서버에서 `prefetchQuery`합니다. 이 데이터는 `queryClient`의 캐시에 저장됩니다.
2. 데이터 직렬화
<HydrationBoundary state={dehydrate(queryClient)}>
`dehydrate`: Tanstack Query의 `queryClient`상태를 JSON으로 직렬화해 클라이언트로 전달합니다.
❓직렬화란 무엇이고 왜 필요한가
서버에서 데이터를 패치하고 Tanstack Query 캐시에 저장하더라도 클라이언트는 해당 데이터를 직접 접근할 수 없기 때문에 데이터를 전달하려면 JSON 형식으로 변환해야 합니다.
직렬화란 객체 형태를 문자열(JSON) 형식으로 변환하는 과정입니다.
✅ 예시 코드
const data = { name: "Alice", age: 30 };
const serializedData = JSON.stringify(data); // '{"name":"Alice","age":30}'
✨ 간단하게 `queryClient`데이터를 JSON 형식으로 변환한다는 이야기입니다~!
3. 클라이언트에서 데이터 복원
<HydrationBoundary state={dehydrate(queryClient)}>
`HydrationBoudary`: Tanstack Query의 상태를 서버에서 클라이언트로 복원하는 데 사용되는 컴포넌트입니다.
그래서 클라이언트 컴포넌트에서는 새로 데이터를 패치하지 않고 바로 사용할 수 있습니다!
리팩토링 후 장점 📖
초기 렌더링 성능 향상
서버에서 미리 데이터를 준비하기 때문에 클라이언트에서 데이터를 기다릴 필요가 없습니다.
불필요한 API 요청 방지
서버와 클라이언트 간 데이터 공유로 동일 데이터를 중복 요청하지 않습니다.
회고 🧐
서버에서 데이터를 미리 패치해 클라이언트로 전달해 주는 과정에서 초기 렌더링 성능을 개선할 수 있었고 사용자 경험을 향상할 수 있었던 좋은 경험이었습니다!
'공부 > Next' 카테고리의 다른 글
Supabase에서 타입 설정하기 (0) | 2024.11.11 |
---|---|
[리팩토링] queries 폴더 구조 변경 및 메서드명 수정 (1) | 2024.11.07 |
[리팩토링] Icon 컴포넌트 리팩토링 (0) | 2024.11.02 |
Next 커스텀 훅을 사용한 모달창 기능 구현 (1) | 2024.11.01 |
[리팩토링] 데이터 로직 분리 및 서버 상태 관리 최적화 (0) | 2024.10.28 |
Next 카카오맵을 활용한 시도별 가로 스크롤 버튼 이동 구현 (0) | 2024.10.28 |
[리팩토링] Next 카카오 맵 폴리곤 렌더링 리팩토링 - 커스텀 훅, 유틸 함수 구조 개선 (0) | 2024.10.24 |
Next 카카오 맵 행정구역 나누기 (1) | 2024.10.23 |