다이나믹 라우트를 사용하는 페이지에서 getStaticPaths
라는 함수를 내보내면, Next.js
는 getStaticPaths
에서 지정된 모든 경로를 정적으로 프리 렌더링합니다.
export async function getStaticPaths() {
return {
paths: [
{ params: { ... } } // 아래 "paths" 섹션 참조
],
fallback: true, false 또는 "blocking" // 아래 "fallback" 섹션 참조
};
}
getStaticPaths
함수는 다음과 같은 필수 속성을 가진 객체를 반환해야 합니다.
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/2
를 pages/posts/[id].js
에서 가져온 페이지 컴포넌트를 사용하여 다음 빌드에서 정적으로 생성합니다.
각 params
객체의 값은 페이지 이름에서 사용되는 매개변수와 일치해야 합니다.
pages/posts/[postId]/[commentId]
인 경우, params
는 postId
및 commentId
를 포함해야 합니다.pages/[...slug]
와 같이 catch-all
라우트를 사용하는 경우, params
는 slug
(배열)을 포함해야 합니다. 이 배열이 ['hello', 'world']
인 경우, Next.js
는 /hello/world
에 정적으로 생성된 페이지를 제공합니다.catch-all
라우트를 사용하는 경우, 루트 경로를 렌더링하려면 null
, []
, undefined
또는 false
를 사용합니다. 예를 들어, pages/[[...slug]]
에 대해 slug: false를 제공하면, Next.js
는 /에 정적으로 생성된 페이지를 제공합니다.params
문자열은 대소문자를 구분하며, 경로가 올바르게 생성되도록 정규화되어야 합니다. 예를 들어, param
으로 WoRLD
가 반환되면 WoRLD
가 실제로 방문한 경로인 경우에만 일치하며, world
나 World
와는 일치하지 않습니다.
params
객체 외에도 i18n
이 구성되어 있는 경우 locale 필드를 반환하여 생성 중인 경로에 대한 로캘을 구성할 수 있습니다.
fallback
가 false
인 경우, getStaticPaths
에서 반환되지 않는 모든 경로는 404
페이지가 표시됩니다.
next build
가 실행될 때, Next.js
는 getStaticPaths
가 fallback: 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
인 경우, getStaticProps
의 동작 방식이 다음과 같이 변경됩니다:
getStaticPaths
에서 반환된 경로들은 getStaticProps
에서 build
시간에 HTML
로 렌더링됩니다.build
시간에 생성되지 않은 경로들은 404
페이지가 아닌 대신에 "fallback"
버전의 페이지를 첫 요청 시 서빙합니다. 구글과 같은 웹 크롤러는 fallback
을 받지 않고, 대신 fallback: 'blocking'
과 같은 동작을 보입니다.fallback: true
인 페이지에 next/link
나 next/router
를 통해 (클라이언트 사이드에서) 접근할 때, Next.js
는 fallback
을 제공하지 않고 대신 fallback: 'blocking'
처럼 동작합니다.Next.js
는 백그라운드에서 요청된 경로의 HTML
과 JSON
을 정적으로 생성합니다. 이 과정에는 getStaticProps
가 실행됩니다.JSON
을 수신합니다. 이를 사용하여 필요한 props
로 페이지를 자동으로 렌더링합니다. 사용자의 관점에서는 페이지가 fallback
페이지에서 전체 페이지로 바뀌었다는 것을 알 수 있습니다.Next.js
는 이 경로를 미리 렌더링된 페이지 목록에 추가합니다. 동일한 경로에 대한 후속 요청은 빌드 시간에 미리 렌더링된 다른 페이지와 마찬가지로 생성된 페이지를 제공합니다.참고:
fallback: true
는next export
를 사용할 때 지원되지 않습니다.
fallback: true
는 앱이 데이터에 의존하는 매우 많은 정적 페이지를 가지고 있을 때 유용합니다(예: 대규모 전자상거래 사이트). 모든 제품 페이지를 사전 렌더링하려면 빌드 시간이 매우 오래 걸릴 수 있습니다.
대신, 소수의 정적 페이지를 생성한 후 나머지는 fallback: true
를 사용할 수 있습니다. 아직 생성되지 않은 페이지를 요청하면 사용자는 로딩 인디케이터 또는 스켈레톤 컴포넌트가 있는 페이지를 볼 수 있습니다.
getStaticProps
가 완료되면 요청된 데이터를 사용하여 페이지가 렌더링됩니다. 이제 이 페이지를 요청하는 모든 사용자는 정적으로 미리 렌더링된 페이지를 받게 됩니다.
이렇게 함으로써 사용자가 항상 빠른 경험을 할 수 있으며 정적 생성의 이점과 빠른 빌드를 유지할 수 있습니다.
fallback: true
는 생성된 페이지를 업데이트하지 않습니다. 이 경우 Incremental Static Regeneration
을 살펴보세요.
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"
버전 페이지에서는:
props
는 비어 있습니다.router
를 사용하여 fallback
이 렌더링되는지 여부를 감지할 수 있습니다. router.isFallback
은 true
가 됩니다.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
에서는 next
에서 제공하는 GetStaticPaths
타입을 사용할 수 있습니다.
import { GetStaticPaths } from 'next'
export const getStaticPaths: GetStaticPaths = async () => {
// ...
}