여러 API 요청을 한 번에 병렬로 처리하기 위해 useQueries를 사용
const results = useQueries({
queries: [
{ queryKey: ["posts", postId], queryFn: () => fetchPosts(postId) },
{ queryKey: [queryKey, postId], queryFn: () => fetchComments({ postId, tableName }) }
]
});
모든 렌더링의 시간을 맞추기 위해 Promise.all을 사용하여 비동기 작업을 동시에 끝낼 수 있도록 함.
await Promise.all([
queryClient.prefetchQuery({
queryKey: ["posts", params.id],
queryFn: () => fetchPosts(params.id)
}),
queryClient.prefetchQuery({
queryKey: ["comments", params.id],
queryFn: () => fetchComments({ postId: params.id, tableName: "comments" })
})
]);
서버 컴포넌트에서 데이터를 prefetching해서 프리렌더링해주어 SEO와 UX도 모두 향상될 수 있도록 함.
<HydrationBoundary state={dehydrate(queryClient)}>
<Post params={params} />
<Comment params={params} />
</HydrationBoundary>
cache: 'no-store'
설정으로 매 요청마다 최신 데이터 확보export const fetchComments = async ({ postId, tableName }: FetchCommentProps): Promise<CommonCommentType[]> => {
try {
const response = await fetch(`https://music-community-pearl.vercel.app/api/${tableName}/${postId}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
cache: 'no-store'
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
return data as CommonCommentType[];
} catch (error) {
console.error("댓글 불러오기 실패", error);
return [];
}
};
SSG 서버 컴포넌트에서 route handler 호출 방법
SSG 컴포넌트는 build 시 실행되지만, build 상황에서 route handler는 활성화되어 있지 않기 때문에 api url을 변경해줘야 한다.
Bad Practice 🤔
export default async function Home() {
const data = await fetch("http://localhost:3000/api/json").then(
(res) => res.json(),
);
return <>{data.title}</>;
}
Good Practice 🤩
export default async function Home() {
const data = await fetch("https://jsonplaceholder.typicode.com/todos/1").then(
(res) => res.json(),
);
return <>{data.title}</>;
}
일관성 있는 로딩으로 로딩 상태 관리 개선!