๐ก ๋ ๊ฐ์ ๋ฐ์ดํฐ ์์ค๋ก๋ถํฐ fetchํด์ค๋ ๋ฐฉ์์ ์ต์ ํ ํ๋ ๋ฐฉ๋ฒ.
- ํํ์ด์ง์ ๋ฐ์ดํฐ๋ฅผ fetch ํด์จ ํ ์ฝ๋
// app/(home)/page.tsx async function getMovies() { const response = await fetch(API_URL); const json = await response.json(); return json; } export default async function HomePage() { const movies = await getMovies(); return ( <div> {movies.map((movie) => ( <li key={movie.id}> <Link href={`/movies/${movie.id}`}>{movies.title}</Link> </li> ))} </div> ); }
- ์ ํํ์ด์ง์์ ๋งํฌ๋ฅผ ํด๋ฆญํ ๊ฒฝ์ฐ, ๋ฐ์ดํฐ๋ฅผ fetch ํด์จ ํ ์ํ ์ธ๋ถ์ฌํญ ๋ณด์ฌ์ฃผ๊ธฐ
// app/(movies)/movies/[id]/page.tsx async function getMovie(id: string) { console.log(`Fetching movie with id: ${Date.now()}`); // ์์ ์๊ฐ์ ์ฒดํฌํ๊ธฐ ์ํ ์ฝ๋ await new Promise((resolve) => setTimeout(resolve, 2000)); // ํจ์๋ฅผ 5์ด๊ฐ ๋๋ ์ด ํ๋ ์ฝ๋ const response = await fetch(`${API_URL}/${id}`); return response.json(); } async function getVideos(id: string) { console.log(`Fetching movie with id: ${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 }; }) { const movie = await getMovie(id); const videos = await getVideos(id); return ( <div> <h1> {movie.title} </h1> </div> ); }const movie = await getMovie(id); const videos = await getVideos(id);
- ๋ค์๊ณผ ๊ฐ์ด ์ฝ๋๋ฅผ ์์ฑํ๋ฉด, ์๋ฐ์คํฌ๋ฆฝํธ๋ ์์ ์ฝ๋๋ฅผ ์คํ์ํค๊ณ ๋ค์ ์ฝ๋๋ฅผ ์คํ์ํค๊ธฐ ๋๋ฌธ์ ๋๊ธฐ์ ์ผ๋ก ์คํ์ํค๊ธฐ ๋๋ฌธ์ ๋ ๋ฐ์ดํฐ๋ค์ ๋ชจ๋ fetch ํด์ค๋๋ฐ๋ ์ค๋ ์๊ฐ์ด ์์๋ ๊ฒ์.
- ์ ์ฝ๋๋ฅผ ์คํ์ํฌ ๊ฒฝ์ฐ ์ถ๋ ฅ๋๋ ๊ฐ๋ค, ๋ค์๊ณผ ๊ฐ์ด ์๊ฐ์ฐจ๋ฅผ ๋๋ฉฐ ๋ฐ์ดํฐ๊ฐ fetch๋จ.
// app/(movies)/movies/[id]/page.tsx export default async function MovieDetail({ params: { id }, }: { params: { id: string }; }) { const [movie, videos] = await Promise.all([getMovie(id), getVideos(id)]); return ( <div> <h1> {movie.title} </h1> </div> ); }
- Promise.all ์ ์ฌ์ฉํด์ฃผ๋ฉด ๋ ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ๋์์ ๋ณ๋ ฌ์ ์ผ๋ก fetchํ๊ธฐ ์์ํ๋ค.
๐ฃ๏ธ ์ง๊ธ๊น์ง๋ page ์ปดํฌ๋ํธ์์ ๋ ๊ฐ์ ๋ฐ์ดํฐ๋ค์ ๋ชจ๋ fetch ํด์ค๊ณ ์์์, ์ง๊ธ๋ถํฐ๋ getMovie, getVideos๋ฅผ ๊ฐ๊ฐ์ ํ์ผ์์ ๊ฐ๋ณ์ ์ผ๋ก ๊ฐ๊ฐ render ํ๊ฒ๋ ์ฝ๋๋ฅผ ์์ ํจ.
// components/movie-videos.tsx async function getVideos(id: string) { console.log(`Fetching movie with id: ${Date.now()}`); await new Promise((resolve) => setTimeout(resolve, 2000)); const response = await fetch(`${API_URL}/${id}/videos`); return response.json(); } export default async function MovieVideos({ id }: { id: string }) { const video = await getVideos(id); return <h6>{JSON.stringify(video)}</h6>; } // components/movie-infos.tsx async function getMovie(id: string) { console.log(`Fetching movie with id: ${Date.now()}`); await new Promise((resolve) => setTimeout(resolve, 2000)); const response = await fetch(`${API_URL}/${id}`); return response.json(); } export default async function MovieInfos({ id }: { id: string }) { const movie = await getMovie(id); return <h6>{JSON.stringify(movie)}</h6>; }
- ๋ค์๊ณผ ๊ฐ์ด page์ปดํฌ๋ํธ์์ ๊ด๋ฆฌํ๋ fetch ํจ์๋ค์ ๊ฐ๊ฐ์ ์ปดํฌ๋ํธ ํ์ผ๋ก ๋ถ๋ฆฌํ์ฌ ๊ด๋ฆฌ.
// app/(movies)/movies/[id]/page.tsx export default async function MovieDetail({ params: { id }, }: { params: { id: string }; }) { return ( <div> <Suspense fallback={<h1>Loading movie info</h1>}> // fallback : ๋ฐ์ดํฐ๊ฐ fetch๋๋ ๋์ค์ ๊ทธ๋ ค์ง๋ UI <MovieInfos id={id} /> </Suspense> <Suspense fallback={<h1>Loading movie videos</h1>}> <MovieVideos id={id} /> </Suspense> </div> ); }
- ๊ทธ๋ฆฌ๊ณ ํ์ด์ง ์ปดํฌ๋ํธ์์๋ ๊ฐ๊ฐ์ ๊ฐ๋ณ ์ปดํฌ๋ํธ๋ฅผ Suspense ํค์๋๋ก ๊ฐ์ธ์ค.
![]()
- ๊ฒฐ๊ณผ -> ๋ค์๊ณผ ๊ฐ์ด ๋ณ๋ ฌ์ ์ผ๋ก ๋๊ฐ์ง๋ฅผ ๋์์ fetch ํ ์ ์๊ณ ํ๋์ ์์ฒญ์ด ์๋ฃ๋๋ฉด ๊ทธ ์ฆ์ ํด๋น ์ปดํฌ๋ํธ๊ฐ render๋จ.
- Promise.all ๊ณผ๋ ๋ค๋ฅด๊ฒ Suspense๋ฅผ ์ฌ์ฉํ๋ฉด ๊ตฌ์ฒด์ ์ผ๋ก ํ์ด์ง์ ์ด๋ ๋ถ๋ถ์ด ๋ก๋ฉ ์ํ์ฌ์ผ ํ๋์ง๋ฅผ ๋ช ์ํด ์ค ์ ์๋ค.