NextJS API: getStaticPaths

hwisaac·2023년 3월 13일
0

NextJS API(page router)

목록 보기
4/10

getStaticPaths

다이나믹 라우트를 사용하는 페이지에서 getStaticPaths라는 함수를 내보내면, Next.jsgetStaticPaths에서 지정된 모든 경로를 정적으로 프리 렌더링합니다.

export async function getStaticPaths() {
  return {
    paths: [
      { params: { ... } } // 아래 "paths" 섹션 참조
    ],
    fallback: true, false 또는 "blocking" // 아래 "fallback" 섹션 참조
  };
}

getStaticPaths 반환값

getStaticPaths 함수는 다음과 같은 필수 속성을 가진 객체를 반환해야 합니다.

paths

paths 키는 어떤 경로가 프리 렌더링될지를 결정합니다. 예를 들어, pages/posts/[id].js라는 다이나믹 라우트를 사용하는 페이지가 있다고 가정해보세요. 이 페이지에서 getStaticPaths를 내보내고 다음과 같이 paths에 대해 반환하면:

return {
  paths: [
    { params: { id: '1' }},
    {
      params: { id: '2' },
      // i18n이 구성된 경우 경로를 위한 locale도 반환될 수 있음
      locale: "en",
    },
  ],
  fallback: ...
}

그러면, Next.js/posts/1/posts/2pages/posts/[id].js에서 가져온 페이지 컴포넌트를 사용하여 다음 빌드에서 정적으로 생성합니다.

params 객체의 값은 페이지 이름에서 사용되는 매개변수와 일치해야 합니다.

  • 페이지 이름이 pages/posts/[postId]/[commentId]인 경우, paramspostIdcommentId를 포함해야 합니다.
  • 페이지가 pages/[...slug]와 같이 catch-all 라우트를 사용하는 경우, paramsslug(배열)을 포함해야 합니다. 이 배열이 ['hello', 'world']인 경우, Next.js/hello/world에 정적으로 생성된 페이지를 제공합니다.
  • 페이지가 선택적인 catch-all 라우트를 사용하는 경우, 루트 경로를 렌더링하려면 null, [], undefined 또는 false를 사용합니다. 예를 들어, pages/[[...slug]]에 대해 slug: false를 제공하면, Next.js는 /에 정적으로 생성된 페이지를 제공합니다.

params 문자열은 대소문자를 구분하며, 경로가 올바르게 생성되도록 정규화되어야 합니다. 예를 들어, param으로 WoRLD가 반환되면 WoRLD가 실제로 방문한 경로인 경우에만 일치하며, worldWorld와는 일치하지 않습니다.

params 객체 외에도 i18n이 구성되어 있는 경우 locale 필드를 반환하여 생성 중인 경로에 대한 로캘을 구성할 수 있습니다.

fallback: false

fallbackfalse인 경우, getStaticPaths에서 반환되지 않는 모든 경로는 404 페이지가 표시됩니다.

next build가 실행될 때, Next.jsgetStaticPathsfallback: false를 반환하는지 확인하고, getStaticPaths에서 반환된 경로만 빌드합니다. 이 옵션은 작성해야 할 경로가 적거나 새로운 페이지 데이터가 자주 추가되지 않는 경우 유용합니다. fallback: false를 가지고 있다면 더 많은 경로를 추가해야 한다는 것을 알게 되면 next build를 다시 실행하여 새 경로를 생성해야 합니다.

다음 예제는 pages/posts/[id].js라는 각각 하나의 블로그 게시물을 프리 렌더링하는 예제입니다. 블로그 게시물 목록은 CMS에서 가져와 getStaticPaths에서 반환됩니다. 그런 다음 각 페이지에 대해 getStaticProps를 사용하여 CMS에서 게시물 데이터를 가져옵니다.

// pages/posts/[id].js

function Post({ post }) {
  // 게시물 렌더링...
}

// 이 함수는 빌드 타임에 호출됩니다.
export async function getStaticPaths() {
  // 게시물을 가져오기 위해 외부 API 엔드포인트를 호출합니다.
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  // 게시물에 따라 프리 렌더링 할 경로를 가져옵니다.
  const paths = posts.map((post) => ({
    params: { id: post.id },
  }))

  // 빌드 타임에 이러한 경로만 프리 렌더링합니다.
  // { fallback: false }는 다른 경로는 404를 반환해야 함을 의미합니다.
  return { paths, fallback: false }
}

// 이것도 빌드 타임에 호출됩니다.
export async function getStaticProps({ params }) {
  // params에는 게시물 id가 포함됩니다.
  // /posts/1과 같은 경로인 경우 params.id는 1입니다.
  const res = await fetch(`https://.../posts/${params.id}`)
  const post = await res.json()

  // 게시물 데이터를 props를 통해 페이지로 전달합니다.
  return { props: { post } }
}

export default Post

fallback: true

예시: 매우 큰 정적 페이지를 생성하는 경우

fallbacktrue인 경우, getStaticProps의 동작 방식이 다음과 같이 변경됩니다:

  • getStaticPaths에서 반환된 경로들은 getStaticProps에서 build 시간에 HTML로 렌더링됩니다.
  • build 시간에 생성되지 않은 경로들은 404 페이지가 아닌 대신에 "fallback" 버전의 페이지를 첫 요청 시 서빙합니다. 구글과 같은 웹 크롤러는 fallback을 받지 않고, 대신 fallback: 'blocking'과 같은 동작을 보입니다.
  • fallback: true인 페이지에 next/linknext/router를 통해 (클라이언트 사이드에서) 접근할 때, Next.jsfallback을 제공하지 않고 대신 fallback: 'blocking'처럼 동작합니다.
  • Next.js는 백그라운드에서 요청된 경로의 HTMLJSON을 정적으로 생성합니다. 이 과정에는 getStaticProps가 실행됩니다.
  • 생성이 완료되면, 브라우저는 생성된 경로에 대한 JSON을 수신합니다. 이를 사용하여 필요한 props로 페이지를 자동으로 렌더링합니다. 사용자의 관점에서는 페이지가 fallback 페이지에서 전체 페이지로 바뀌었다는 것을 알 수 있습니다.
  • 동시에, Next.js는 이 경로를 미리 렌더링된 페이지 목록에 추가합니다. 동일한 경로에 대한 후속 요청은 빌드 시간에 미리 렌더링된 다른 페이지와 마찬가지로 생성된 페이지를 제공합니다.

참고: fallback: truenext export를 사용할 때 지원되지 않습니다.

fallback: true 가 언제 유용한가요?

fallback: true는 앱이 데이터에 의존하는 매우 많은 정적 페이지를 가지고 있을 때 유용합니다(예: 대규모 전자상거래 사이트). 모든 제품 페이지를 사전 렌더링하려면 빌드 시간이 매우 오래 걸릴 수 있습니다.

대신, 소수의 정적 페이지를 생성한 후 나머지는 fallback: true를 사용할 수 있습니다. 아직 생성되지 않은 페이지를 요청하면 사용자는 로딩 인디케이터 또는 스켈레톤 컴포넌트가 있는 페이지를 볼 수 있습니다.

getStaticProps가 완료되면 요청된 데이터를 사용하여 페이지가 렌더링됩니다. 이제 이 페이지를 요청하는 모든 사용자는 정적으로 미리 렌더링된 페이지를 받게 됩니다.

이렇게 함으로써 사용자가 항상 빠른 경험을 할 수 있으며 정적 생성의 이점과 빠른 빌드를 유지할 수 있습니다.

fallback: true는 생성된 페이지를 업데이트하지 않습니다. 이 경우 Incremental Static Regeneration을 살펴보세요.

fallback: 'blocking'

fallback'blocking'인 경우, getStaticPaths에서 반환하지 않는 새 경로는 SSR과 동일하게 HTML 생성을 기다린 후(따라서 블로킹) 해당 경로에 대한 캐시를 만들어 미래의 요청에 대해 한 번만 실행됩니다.

getStaticProps는 다음과 같이 작동합니다.

  • getStaticPaths에서 반환된 경로는 getStaticProps에 의해 빌드 시간에 HTML로 렌더링됩니다.
  • 빌드 시간에 생성되지 않은 경로는 404 페이지가 아닙니다. 대신, Next.js는 첫 번째 요청에서 SSR을 수행하고 생성된 HTML을 반환합니다.
  • 완료되면 브라우저는 생성된 경로의 HTML을 받습니다. 사용자의 관점에서는 "브라우저가 페이지를 요청 중"에서 "전체 페이지가 로드됨"으로 전환됩니다. 로딩/폴백 상태의 플래시가 없습니다.
  • 동시에, Next.js는 이 경로를 사전 렌더링된 페이지 목록에 추가합니다. 동일한 경로에 대한 후속 요청은 빌드 시간에 미리 렌더링된 다른 페이지와 마찬가지로 생성된 페이지를 제공합니다.

fallback: 'blocking'은 기본적으로 생성된 페이지를 업데이트하지 않습니다. 생성된 페이지를 업데이트하려면 fallback: 'blocking'과 함께 Incremental Static Regeneration을 사용하세요.

Fallback 페이지

"fallback" 버전 페이지에서는:

  • 페이지의 props는 비어 있습니다.
  • router를 사용하여 fallback이 렌더링되는지 여부를 감지할 수 있습니다. router.isFallbacktrue가 됩니다.
    다음 예제는 isFallback을 사용하는 방법을 보여줍니다.
// pages/posts/[id].js
import { useRouter } from 'next/router'

function Post({ post }) {
  const router = useRouter()

  // 페이지가 아직 생성되지 않았으면, getStaticProps()가 실행될 때까지
  // 이 메시지가 표시됩니다.
  if (router.isFallback) {
    return <div>Loading...</div>
  }

  // 포스트 렌더링...
}

// 이 함수는 빌드 타임에 호출됩니다.
export async function getStaticPaths() {
  return {
    // `/posts/1`과 `/posts/2`만 빌드 타임에 생성됩니다.
    paths: [{ params: { id: '1' } }, { params: { id: '2' } }],
    // 추가적인 페이지를 정적으로 생성합니다.
    // 예를 들어, `/posts/3`
    fallback: true,
  }
}

// 이 함수도 빌드 타임에 호출됩니다.
export async function getStaticProps({ params }) {
  // params에는 포스트 `id`가 포함됩니다.
  // 예를 들어, 라우트가 /posts/1이면 params.id는 1입니다.
  const res = await fetch(`https://.../posts/${params.id}`)
  const post = await res.json()

  // 포스트 데이터를 props를 통해 페이지로 전달합니다.
  return {
    props: { post },
    // 요청이 들어오면 최대 1초마다 포스트를 다시 생성합니다.
    revalidate: 1,
  }
}

export default Post

TypeScript에서 getStaticPaths 사용하기

TypeScript에서는 next에서 제공하는 GetStaticPaths 타입을 사용할 수 있습니다.

import { GetStaticPaths } from 'next'

export const getStaticPaths: GetStaticPaths = async () => {
  // ...
}

0개의 댓글