Today Sangmin Learned
728x90

Next.js에서 사전 렌더링을 하는 방법은 크게 두 가지가 있다: Static Generation과 Server Side Rendering(SSR)이 그것이다.

1. Static Generation

  • 유저의 요청(request)이 있기 전에 렌더링 대상이 되는 페이지를 사전에 렌더링해야되는 경우 사용한다.
  • 보통 build time에 사전 렌더링을 해둔다.

1-1. 데이터가 없는 경우의 Static Generation

데이터가 없는 경우는, 서버로부터 fetch해 올 어떠한 데이터도 없기 때문에 Next.js에서는 build time에 HTML 형태로 사전 렌더링을 해둔다.

function About() {
  return <div>About</div>
}

export default About

1-2. 데이터가 있는 경우의 Static Generation

  1. 페이지 컨텐츠가 외부 데이터에 의존할 경우: getStaticProps를 사용한다.
  2. 페이지 경로가 외부 데이터에 의존할 경우: getStaticPaths를 사용하는데, 보통 getStaticProps와 함께 사용한다.

1-2-1. 페이지 컨텐츠가 외부 데이터에 의존하는 경우: getStaticProps 사용하기

예를 들면, CMS로부터 블로그 글들의 리스트를 가져오고 싶은 경우

const Blog = ({ posts }) => {
  return (
    <ul>
      {posts.map((post) => (
        <li>{post.title}</li>
      ))}
    </ul>
  );
};

// getStaticProps를 build time에 불러오기
export async function getStaticProps() {
  // posts를 얻기위해 외부 API를 호출함
  const res = await fetch("https://.../posts");
  const posts = await res.json();

  // { props: { posts } } 형태로 불러옴으로써 Blog 컴포넌트는 build time에 posts를 prop으로서 받게 된다.
  return {
    props: {
      posts,
    },
  };
}

export default Blog;

1-2-1. 페이지 경로가 외부 데이터에 의존하는 경우: getStaticPaths 사용하기

function Post({ post }) {
  // Render post
}

// getStaticPaths 함수는, 사전 렌더링 하고싶은 path를
// build time에 특정할 수 있게 해줌
export async function getStaticPaths() {
  // 외부 API 엔드포인트를 불러와서 posts를 얻음
  const res = await fetch("http://.../posts");
  const posts = await res.json();

  // posts에 기반하여, 사전 렌더링하고싶은 path를 얻음
  const paths = posts.map((post) => ({
    params: { id: post.id },
  }));

  // build time에만 이 path들을 (post.id) 사전 렌더링 할 것임
  // { fallback: false }는 다른 라우트는 404를 띄워야 된다는 뜻
  return { paths, fallback: false };
}

export async function getStaticProps({ params }) {
  // params는 post의 id를 포함한다.
  // 라우트가 '/posts/1'의 형태라면 params.id는 1인 것임
  const res = await fetch(`https://.../posts/${params.id}`);
  const post = await res.json();

  // props를 통해 post 데이터를 페이지로 넘긴다.
  return { props: { post } };
}

1-3. 어떤 경우에 Static Generation을 써야할까?

공식문서에서는 데이터가 있든 없든, 가능하다면 Static Generation을 사용할 것을 추천한다. 왜냐면 build time에 한 번 만들어지고나서 CDN에 의해 served 되는데, 이 경우는 매 요청시마다 페이지를 렌더링하는 SSR보다 더 빠르기 때문.. 예를 들면

  • Marketing pages (판매 페이지)
  • Blog posts (블로그 글)
  • E-commerce product listings (온라인 커머스 및 상품 나열)

스스로에게 물어봤을 때, 유저의 요청 이전에 이 페이지를 띄워야되는지? 가 맞다면 Static Generation을 쓰면 되고, 그게 아니라면 SSR을 쓰면 된다.

  • 예를 들면, 지속적으로 업데이트되는 페이지의 경우 유저의 요청이 있기 전에 사전 렌더링을 할 수 없으므로 이 경우에 Static Generation은 좋은 아이디어가 아니다. 이 경우 두 가지 방법 중 하나를 사용해야 한다.
    • 페이지의 일부 부분에 대해 사전 렌더링을 스킵하고 클라이언트 사이드의 JavaScript 또는 TypeScript를 사용할 수 있다.2) SSR을 사용하기
  • -> 2. Server Side Rendering(바로아래)에서
  • 1) Static Generation과 Clien Side Rendering(CSR)을 사용하기

2. Server Side Rendering(SSR)

  • 서버 사이드 렌더링을 사용할 경우, 각 요청시 마다 페이지를 사전 렌더링한다. 페이지가 CDN에 의해 캐싱될 수 없으므로 Static Generation에 비해서는 더 느릴 것이다.
  • 그렇지만, 사전에 렌더링된 페이지들은 항상 최신 상태를 유지한다.
  • For example, suppose that your page needs to pre-render frequently updated data (fetched from an external API). You can writegetServerSidePropswhich fetches this data and passes it toPagelike below:
  • 만약 페이지가 (외부 API로부터 fetch해 오는) 업데이트되는 데이터를 항상 사전 렌더링해야 할 경우, 이 데이터를 받아와서 Page로 넘기는 getServerSideProps를 사용해야한다.
function Page({ data }) {
  // Render data
}

// 매 요청시마다 아래 getServerSideProps 함수가 호출된다.
export async function getServerSideProps() {
  // 외부 API로부터 값을 fetch 해온다.
  const res = await fetch(`https://.../data`);
  const data = await res.json();

  // 이전과 마찬가지로, props를 통해 페이지에 데이터를 전송한다.
  return { props: { data } };
}

export default Page;

getServerSidePropsgetStaticProps랑 비슷하긴 한데, 전자는 build time에 사전 렌더링이 되는 것이 아니라 매 요청시마다 사전 렌더링 된다는 차이점이 있다.

그래서 요악하자면..

1. Static Generation(추천): HTML이 build time에 생성이 되고, 매 요청시마다 재사용된다. Static Generation을 사용하려면 페이지 컴포넌트를 export하거나, getStaticProps를(+ 필요하다면 getStaticPaths까지) export해야 한다. 유저의 요청이 있기 전에 사전 렌더링이 될 수 있는 페이지들에 적절한 방식이다. 추가적으로 데이터를 가져오기 위해 Client Side Rendering을 사용할 수도 있음!

2. Server Side Rendering(SSR): HTML이 매 요청시마다 생성된다. 서버사이드 렌더링을 사용하는 페이지를 만들기 위해서는, getServerSideProps를 export해야 된다. SSR의 퍼포먼스가 Static Generation보다 안좋기때문에, 진짜 꼭 필요한 경우에만 사용하자.

 

출처

Next.js 공식문서

profile

Today Sangmin Learned

@steadily-worked

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!