Web Devlopment/NextJs
#8. fetch - Promise.all, Suspense
키모형
2025. 3. 28. 14:34
반응형
페이지에서 여러개의 api를 호출해야 하는 경우 동시에 병렬요청하는 방법
import { API_URL } from "../../../(home)/page";
export const metadata = {
title: "Movie Detail",
}
async function getMovie(id:string) {
console.log(`Fetching movies: ${Date.now()}`);
await new Promise((resolve) => setTimeout(resolve, 2000));
const response = await fetch(`${API_URL}/${id}`);
return response.json();
}
async function getVideos(id:string) {
console.log(`Fetching movies: ${Date.now()}`);
await new Promise((resolve) => setTimeout(resolve, 2000));
const response = await fetch(`${API_URL}/${id}/videos`);
return response.json();
}
export default async function MovieDetail({
params: {id},
}: {
params: {id:string};
}) {
console.log("========================");
console.log("start fetching");
// const movie= await getMovie(id);
// const videos= await getVideos(id);
const [movie, videos] = await Promise.all([getMovie(id), getVideos(id)]);
console.log("end fetching");
return (
<div>
<h1>{movie.title}</h1>
</div>
)
}
Promise.all
// API를 각각 fetch 하는 경우 순서대로 fetch가 완료되기를 기다려서 처리
const movie= await getMovie(id);
const videos= await getVideos(id);
// Promise.all 을 사용하여 동시에 fetch를 요청할 수 있음
const [movie, videos] = await Promise.all([getMovie(id), getVideos(id)]);
Suspense
2개의 fetch 요청을 각각 component 로 분리 하고, Suspense 사이에 compent를 import
- fallback : fetch 가 완료 되기 전까지 표시해줄 메시지
- Suspense로 분리된 fetch 요청은 각각 별도로 fetch를 진행하고 완료되는 대로 각각 결과를 리턴함
import { Suspense } from "react";
import MovieInfo from "../../../components/movie-info";
import MovieVideos from "../../../components/movie-videos";
export const metadata = {
title: "Movie Detail",
}
export default async function MovieDetail({
params,
}: {
params: Promise<{ id: string }>
}) {
// 내부에서 구조 분해 할당
const { id } = await params;
return (
<div>
<h1>Movie Detail Page</h1>
<Suspense fallback={<h3>Loading movie info</h3>}>
<MovieInfo id={id} />
</Suspense>
<h2>Videos</h2>
<Suspense fallback={<h3>Loading movie videos</h3>}>
<MovieVideos id={id} />
</Suspense>
</div>
)
}
components/movie-info.tsx
import { API_URL } from "../(movies)/movies/page";
async function getMovie(id:string) {
// console.log(`Fetching movies: ${Date.now()}`);
// await new Promise((resolve) => setTimeout(resolve, 5000));
const response = await fetch(`${API_URL}/${id}`);
return response.json();
}
export default async function MovieInfo({id}: {id:string}) {
const movie = await getMovie(id);
return <h6>{JSON.stringify(movie)}</h6>
}
components/movie-video.tsx
import { API_URL } from "../(movies)/movies/page";
async function getVideos(id:string) {
// console.log(`Fetching movies: ${Date.now()}`);
// await new Promise((resolve) => setTimeout(resolve, 3000));
const response = await fetch(`${API_URL}/${id}/videos`);
return response.json();
}
export default async function MovieVideos({id}: {id:string}) {
const videos = await getVideos(id);
return <h6>{JSON.stringify(videos)}</h6>
}
반응형