프론트엔드/NextJS

[Next.js] Data Fetch 방법, 병렬 Fetch, Suspense 사용법, prefetch?

s_omi 2024. 12. 2. 09:37
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에 요청한다.
  • server component로부터 Data fetching 방법
    • Hooks 미사용
      • 프레임워크가 다 해주기 때문에 useEffect를 쓰지 않아도 된다.
    • 첫 번째 fetch만 API에 요청한다.
      • 첫 번째 fetch할 때는 fetch되는 동안 페이지가 로딩되는데 이때 로딩 상태 표시는 loading 파일로 하면 된다.
      • 한 번만 fetch하면 프레임워크가 기억하기 때문에 더이상 불러오지 않아도 되어서 로딩 상태가 없다.
    • 최신 데이터가 필요한 순간(데이터 새로고침)이 있다면 Caching이나 Revalidation 사용한다.
  • 단점 예시
    • 아래와 같은 경우, 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