728x90
반응형
SMALL
Next.js에서 Data Fetch 하는 방법에 대해 알아보겠습니다.
1. Data Fetch
원래 Front랑 DB 사이를 연결하려면 API가 필수적으로 필요하며 API가 사이에서 데이터를 주고 받을 수 있게 도와줬는데 Next.js를 사용하면 API가 더이상 필요없다.
- client component에서 Data fetching 방법
- Hooks 사용
- 기본 React만 쓸 때처럼 useEffect를 쓰면서 해야된다.
- fetch할 때마다 API에 요청한다.
- Hooks 사용
- server component로부터 Data fetching 방법
- Hooks 미사용
- 프레임워크가 다 해주기 때문에 useEffect를 쓰지 않아도 된다.
- 첫 번째 fetch만 API에 요청한다.
- 첫 번째 fetch할 때는 fetch되는 동안 페이지가 로딩되는데 이때 로딩 상태 표시는 loading 파일로 하면 된다.
- 한 번만 fetch하면 프레임워크가 기억하기 때문에 더이상 불러오지 않아도 되어서 로딩 상태가 없다.
- 최신 데이터가 필요한 순간(데이터 새로고침)이 있다면 Caching이나 Revalidation 사용한다.
- Hooks 미사용
- 단점 예시
- 아래와 같은 경우, getMovie 함수가 끝나고 getVideos 함수가 실행된다.
- getMovie 함수가 시간이 오래 걸린다면 getVideos 함수 실행시간이 어떻든 오래 걸리게 된다.
- 해결 방법: 병렬 Fetch
async function getMovie(id: string) {
const response = await fetch(`${API_URL}/${id}`);
return response.json();
}
async function getVideos(id: string) {
const response = await fetch(`${API_URL}/${id}/videos`);
return response.json();
}
const movie = await getMovie(id);
const videos = await getVideos(id);
2. 병렬 Fetch
- Promise.all()
- 자바스크립트에서 여러 비동기 작업을 동시에 실행하고, 모든 작업이 완료될 때까지 기다렸다가 결과를 배열 형태로 반환하는 함수이다.
- 여러 Promise를 모두 이행할 때까지 기다린 후 그 결과를 한꺼번에 받아볼 수 있게 해준다.
const [movie, videos] = await Promise.all([getMovie(id), getVideos(id)]);
- 단점 : 두 개의 함수가 다 끝나야 정보를 보여줄 수 있다.
- 해결 방법: Suspense
3. Suspense
- 데이터 소스가 여러 개라면 Suspense를 사용하는 게 좋다.
- 방법
- 데이터를 fetch하기 위해 Suspense 내의 component를 await하고 fetch 중에는 fallback의 내용을 render한다.
- 끝나면 component의 실제 UI를 보여준다.
- 장점
- 하나의 요청이 완료되면 즉시 component가 render된다 굳이 다른 걸 기다릴 필요가 없다.
- 각각의 데이터 fetch에 대해 각각 따로 로딩 상태로 보여줄 수 있다.
- fetch 해야하는 component만 로딩 상태를 가진다.
- loading 페이지는 하나만 fetch 중이더라도 페이지 전체가 loading 상태였음
- 각각의 페이지에서 fetch 하므로 fetch된 데이터를 보여주는 페이지에는 await를 쓸 필요(기다릴 필요 x)가 없다.
- 예시
app/(movies)/movies/[id]/page.tsx
import { Suspense } from "react";
import MovieInfo from "../../../../components/movie-info";
import MovieVideos from "../../../../components/movie-videos";
export default async function MovieDetail({ params: { id }}: { params: { id: string }}) {
return (
<div>
<Suspense fallback={<h1>Loading movie info</h1>}>
<MovieInfo id={id} />
</Suspense>
<Suspense fallback={<h1>Loading movie videos</h1>}>
<MovieVideos id={id} />
</Suspense>
</div>
);
}
components/movie-info.tsx
import { API_URL } from "../app/(home)/page";
async function getMovie(id: string) {
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-videos.tsx
import { API_URL } from "../app/(home)/page";
async function getMovie(id: string) {
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>;
}
4. prefetch
- prefetch를 하면 사이트는 prefetch 내용을 빌드하고 우리가 홈페이지에 도착하는 순간 추가한 prefetch라는 prop 때문에 Next.js는 페이지들을 미리 로드하게 된다.
- 장점 : 사용자가 클릭하기 전부터 fetch를 하게 되어 로딩 상태는 존재하지 않게된다.
<Link prefetch href={`/movies/${id}`}>{title}</Link>
728x90
반응형
LIST
'프론트엔드 > NextJS' 카테고리의 다른 글
[Next.js] "use client"를 왜 쓰는 걸까? (1) | 2024.12.01 |
---|---|
[Next.js] 사용법과 Route (0) | 2024.02.06 |