Next.js - Data Fetching

tunggary·2022년 1월 17일
1

Next.js

목록 보기
3/7
post-thumbnail

next.js의 data를 fetching 방식에는 여러가지가 있는데 이 방식들을 알아보기 전 Pre-rendering 개념을 살펴보자.

Pre-rendering

앞에서 배웠듯이 next.js는 페이지를 이동 할 때 React처럼 CSR 방식으로 js를 이용하고, 필요한 정보만 추가적으로 더 받아와 빠르게 페이지를 전환한다. 또한 SSR 방식으로 서버는 페이지들의 Pre-rendering 된 정보도 가지고 있다.

이는 크롬 설정에서 disable javascript를 하였을 때(js를 받지 않음) 페이지를 로드해보면 확인할 수 있는데

이처럼 순수 React의 경우 CSR 방식이라 js를 다운하지 않으면 빈페이지만 보여야 하지만 next.js에서 기본적으로 SSR 방식의 Pre-rendering 도 지원하기 때문에 서버에서 이미 렌더링된 새로운 페이지의 정보를 받아와 화면을 보여준다.

hydration
Server로부터 받은 렌더링된 정적페이지와 번들링된 js파일을 클라이언트에서 정적페이지의 html 코드와 React인 js 코드를 서로 매칭시켜 페이지가 인터렉티브하게 동작할 상태가 되는 과정

Two Forms of Pre-rendering

next.js에서는 위와 같은 Pre-renderingStatic Generation, Server-side Rendering 방식으로 제공한다.

Static Generation

Static Generation은 build time에 HTML을 생성하는 Pre-rendering 방식으로 이 때 생성된 HTML은 사용자가 요청할 때 마다 재사용된다.

Server-side Rendering

Server-side Rendering은 사용자가 요청할 때 마다 서버에서 HTML을 생성하여 제공하는 Pre-rendering 방식이다.

이러한 두가지 형태의 Pre-rendering 방식을 사용자는 각 페이지마다 개별적으로 적용할 수 있다.

Static Generation vs Server-side Rendering

기본적으로 매 요청마다 서버가 페이지를 렌더링 하는 것보다 한 번 만들고 재사용하는 것이 성능이 좋음으로 Static Generation 사용이 권장된다.

사용자의 요청 전에 Pre-rendering을 할 수 있다면 Static Generation 을 사용해야 한다. 예를 들어 이러한 페이지들이 있다.

  • Marketing pages
  • Blog posts
  • E-commerce product listings
  • Help and documentation

하지만 페이지가 자주 업데이트 되고, 페이지의 컨텐츠가 매 요청마다 바뀐다면
Server-side Rendering(or Client-side Rendering) 을 사용해야 한다. 이 방식은 속도는 Static Generation 보다 느리지만 Pre-rendering된 페이지가 항상 최신 상태로 유지된다.

Client-side Rendering 은 클라이언트에서 페이지가 렌더링되는 방식으로 데이터를 가져올 때 useEffect를 사용하여 가져온다. 이 경우 렌더링 된 후 데이터를 가져오기 때문에 최초의 렌더링 때는 데이터가 없는 상태로 렌더링이 된다.

Static Generation

Static Generation without Data

모든 페이지에서 데이터를 fetching 할 필요는 없다. 이러한 페이지의 경우 build time에 자동으로 정적으로 생성된다.

Static Generation with Data

일부 페이지는 데이터를 fetching 하지 않으면 HTML 파일을 렌더링할 수 없는데, Static Generation 방법의 경우 build time에 파일시스템 혹은 API로 부터 데이터를 fetching 한다.

getStaticProps

위와 같이 Static Generation 방식으로 데이터를 fetching 할 때 getStaticProps 함수를 사용한다.

이 함수는 build time에 실행되며 이 함수 내부에서 데이터를 fetching 한 후, 페이지의 컴포넌트의 props로 전달할 수 있다. 따라서 이 함수가 페이지를 구성하는 코드에 있으면 이 페이지는 데이터를 fetching 해야 렌더링 할 수 있으므로 build time에 Pre-Rendering 할 때 처리해야 한다.

export async function getStaticProps() {
  //data fetching
  const res = await fetch("https://api.spacexdata.com/v3/capsules/C112");
  const data = await res.json();

  //확인을 위한 console.log
  console.log("\n\n\nExecute getStaticProps()\n\n\n");

  //data를 Post로 넘겨줌
  return {
    props: { data },
  };
}

export default function Post({ data }) {
  return (
    <Layout>
      <div>{data.capsule_serial}</div>
      <div>{data.capsule_id}</div>
      <div>{data.status}</div>
      <div>{data.original_launch}</div>
    </Layout>
  );
}

위와 같이 getStaticProps를 이용하여 데이터를 fetching 하고 npm run build 를 하면 console.log 가 터미널에 찍히는 것을 확인할 수 있는데, 즉 build time에 getStaticProps 함수가 실행되었음을 알 수 있다.

개발 환경(npm run dev)에서는 getStaticProps는 매 request마다 수행된다.
Production 에서는 getStaticProps는 build time에 실행된다. 하지만 getStaticPaths 에서 반환되는 fallback 값의 따라 바뀔 수 있다.

Incremental Static Re-Generation (ISR)

위에서 보았듯이 Static Generation 의 방식은 build 타임에만 데이터를 받아와 화면을 구성하는 정적인 페이지로 보일 수 있다. 하지만 ISR을 이용하면 일정 주기마다 데이터의 최신 여부를 검사하고 업데이트된 데이터로 페이지를 다시 구성할 수 있다.

export async function getStaticProps(context) {
  ...
  return {
    props: { data },
    // revalidate 속성을 사용해 해당 주기마다 업데이트를 검사할 수 있다.
    revalidate: 15, // (서버시간 기준 15초마다 갱신여부를 검사함.)
  };
}

위와 같이 getStaticProps가 return 하는 객체에 revalidate라는 속성과 갱신 주기(초)를 추가해주면 된다. 이러면 build하고 배포한 이후에도 설정한 주기마다 데이터의 갱신여부를 검사하고 업데이트된 데이터로 페이지를 다시 정적으로 생성한다. 따라서 Static Generation 방식을 이용하더라도 최신 데이터를 유지할 수 있다.

Server-side Rendering

getServerSideProps

Server-side Rendering 방식으로 데이터를 fetching 할 때 getServerSideProps 함수를 사용한다. 이 방식은 매 요청마다 서버에서 처리해야 하는 일이 생김으로 앞에서 살펴본 getStaticProps 함수보다 느리다.

export async function getServerSideProps(context) {
  return {
    props: {},
  }
}

이 함수는 사용자가 request를 보낼 때 마다 수행되며, 사용자가 request를 보내면 서버에서 Pre-rendering 한 후 클라이언트에게 보내주게 된다. 따라서 이 함수는 파라미터(context)를 가지는데 이 파라미터는 여러가지 속성을 가지고 있다. 자세한 내용은 문서를 참고해서 확인해보자.

export async function getServerSideProps() {
  //data fetching
  const res = await fetch("https://api.spacexdata.com/v3/capsules/C112");
  const data = await res.json();

  //확인을 위한 console.log
  console.log("\n\n\nExecute getServerSideProps()\n\n\n");

  //data를 Post로 넘겨줌
  return {
    props: { data },
  };
}

export default function Post({ data }) {
  return (
    <Layout>
      <div>{data.capsule_serial}</div>
      <div>{data.capsule_id}</div>
      <div>{data.status}</div>
      <div>{data.original_launch}</div>
    </Layout>
  );
}

위와 같이 getServerSideProps를 이용하여 데이터를 fetching 하고 npm run build 를 한 후 npm start 하여 확인해보면, 페이지를 새로고침(new request)할 때 마다 console.log 가 찍히는 것을 확인할 수 있다.

Client-side Rendering

데이터 fetching을 아예 클라이언트 쪽에서 할 수도 있다. 이 경우 Pre-rendering 된 페이지는 외부 데이터를 필요로 하지 않는 페이지이고, 페이지가 로드된 후 데이터를 fetching하여 페이지를 재구성 하게된다.

getStaticPropsgetServerSideProps 함수에 대한 더 자세한 내용은 공식문서에 있는 API Reference를 참고하면 될 것 같다.

References

  1. https://nextjs.org/learn/basics/data-fetching

0개의 댓글