키모스토리

#8. fetch - Promise.all, Suspense 본문

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>
}

 

반응형

'Web Devlopment > NextJs' 카테고리의 다른 글

#10. global css  (0) 2025.03.29
#9. Error handling  (0) 2025.03.28
#7. fetch  (0) 2025.03.28
#6. Dynamic Routes  (0) 2025.03.27
#5. metadata  (0) 2025.03.27