[Next.JS] 정적 사이트 생성 SSG

Simon·2024년 5월 30일
0
post-thumbnail

Static Site Generation(SSG)

페이지에서 정적 생성(Static Generation)을 사용하는 경우 페이지 HTML은 빌드(build) 시 생성된다. 즉, production에서는 next build를 실행할때 HTML이 생성된다. 이 HTML은 각 요청마다 재사용 된다. CDN으로 캐시할 수 있다.

Next.js에서는 데이터 있거나 없는 페이지를 정적으로 생성할 수 있다. 각각의 경우를 살펴보자.

데이터 없는 정적 생성

기본적으로 Next.js는 데이터를 가져오지 않고 정적 생성을 사용하여 페이지를 사전 렌더링(pre-rendering)한다. 다음은 예시이다.

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

이 페이지는 사전 렌더링하기 위해 외부 데이터를 가져올 필요가 없다. 이런 경우 Next.js는 빌드 시간 동안 페이지당 단일 HTML 파일을 생성한다.

데이터 있는 정적 생성

일부 페이지에서는 사전 렌더링을 위해 외부 데이터를 가져와야 한다. 두 가지 시나리오가 있으며 하나 또는 둘 다 적용될 수 있다. 각 경우에 Next.js가 제공하는 함수를 사용할 수 있다.

  1. 페이지 콘텐츠가 외부 데이터에 따라 다르다면 getStaticProps를 사용.

  2. 페이지 경로(path)는 외부 데이터에 따라 다르다면 getStaticPaths사용(일반적으로 getStaticProps와 함께)

Scenario 1: 페이지가 콘텐츠가 외부 데이터에 따라 달라짐

예시: 블로그 페이지는 CMS(content management system)에서 블로그 게시물 목록을 가져와야 할 수 있다.

// TODO: Need to fetch `posts` (by calling some API endpoint)
//       before this page can be pre-rendered.
export default function Blog({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li>{post.title}</li>
      ))}
    </ul>
  )
}

사전 렌더링 시 이 데이터를 가져오기 위해서 NEXT.JS를 사용하면 동일한 파일에 getStaticProps라는 비동기 함수를 export할 수 있다.

이 함수는 빌드 시 호출되며 사전 렌더링 시 가져온 데이터를 페이지 props에 전달할 수 있다.

export default function Blog({ posts }) {
  // Render posts...
}
 
// This function gets called at build time
export async function getStaticProps() {
  // Call an external API endpoint to get posts
  const res = await fetch('https://.../posts')
  const posts = await res.json()
 
  // { props: { post } }를 반환함으로써 Blog 컴포넌트는 빌드 시 'posts'를 prop으로 전달 받는다. 
  return {
    props: {
      posts,
    },
  }
}

Scenario 2: 페이지 경로(path)가 외부 데이터에 따라 달라짐

Next.js를 사용하면 동적 경로가 있는 페이지를 만들 수 있다. 예를 들어 /pages/posts/[id].js라는 파일을 만들어 id를 기반으로 단일 블로그 게시물을 표시할 수 있다. 이렇게 하면 posts/1에 접근할 때 id가 1인 블로그 게시물을 표시할 수 있다.

그러나 빌드 시 사전 렌더링하려는 id는 외부 데이터에 따라 달라질 수 있다.

예: 데이터베이스에 id가 1인 하나의 블로그 게시물만 추가했다고 가정하자. 이 경우 빌드 시 posts/1만 사전 렌더링 하면 된다.

나중에 id가 2인 두 번째 게시물을 추가할 수 있다. 그런 다음 posts/2도 사전 렌더링을 하고 싶을 것이다.

따라서 사전 렌더링된 페이지 경로는 외부 데이터에 따라 달라진다. 이를 처리하기 위해Next.js를 사용하면 동적 페이지(pages/posts/[id].js)에서 getStaticPaths라는 비동기 함수를 export할 수 있다. 이 함수는 빌드 시 호출되며 사전 렌더링할 경로를 지정할 수 있다.

// 함수는 빌드 시에 호출
export async function getStaticPaths() {
  // 게시물 데이터를 얻기 위해 외부 데이터 호출
  const res = await fetch('https://.../posts')
  const posts = await res.json()
 
  // 게시물에 기반하여 사전 렌더링 할 paths 얻음
  const paths = posts.map((post) => ({
    params: { id: post.id },
  }))
 
  // 이러한 경로들만 사전 렌더링
  // { fallback: false } 은 다른 경로들은 404라는 의미
  return { paths, fallback: false }
}

또한 pages/posts/[id].js에서 getStaticProps를 export해야 이 id가 있는 게시물에 대한 데이터를 가져오고 사전 렌더링할 수 있다.

export default function Post({ post }) {
  // Render post...
}
 
export async function getStaticPaths() {
  // ...
}
 
// 빌드 시 호출
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 을 통해 게시물 데이터를 페이지에 전달
  return { props: { post } }
}

언제 정적 생성을 사용해야 할까?

페이지가 한번 만들어지고 CDN에 의해 제공될 수 있으므로 가능하면 정적 생성을 사용하는 것을 권장한다. 서버가 모든 요청에 대해 페이지를 렌더링하도록 하는 것보다 훨씬 빠르다.

다양한 유형의 페이지에 정적 생성을 사용할 수 있다.

  • 마케팅 페이지
  • 블로그 게시물 및 포트폴리오
  • 전자상거래 제품 목록
  • 도움말 및 문서

사용자의 요청에 앞서 페이지를 미리 렌덩할 수 있다면 정적 생성을 선택해야 한다.

반면에, 사용자 요청에 앞서 페이지를 렌더링할 수 없다면 정적 생성은 좋은 생각이 아니다. 페이지에 자주 업데이트 되는 데이터가 표시되고 요청이 있을 때마다 페이지 콘텐츠가 변경될 수 있다.

이런 경우에는 다음 중 하나를 수행할 수 있다.

  • 클라이언트 측 데이터 fetching과 함께 정적 생성을 사용: 페이지의 일부 부분을 사전 렌더링 하지 않고 클라이언 측 JavaScript를 사용하여 채울 수 있다.

  • 서버 측 렌더링(SSR) 사용: Nextjs는 각 요청마다 페이지를 사전 렌더링한다. CDN에서 페이지를 캐시할 수 없기 때문에 속도가 느려지지만 페이지는 항상 최신 상태로 유지된다.

요약

  • 가능하면 정적 생성을 사용하는 것을 권장
  • 동적 경로라면 getStaticPaths라는 비동기 함수 사용 고려
  • 상황에 맞게 사용할 것

Next.js Static Site Generation (SSG) 공식문서

profile
포기란 없습니다.

0개의 댓글