getStaticProps

페이지에서 getStaticProps(정적 사이트 생성) 라는 함수를 내보낸다면, Next.js는 getStaticProps로부터 반환된 props를 사용하여 이 페이지를 빌드 타임에 미리 렌더링을 합니다.

pages/index.tsx
import type { InferGetStaticPropsType, GetStaticProps } from 'next'
 
type Repo = {
  name: string
  stargazers_count: number
}
 
export const getStaticProps = (async (context) => {
  const res = await fetch('https://api.github.com/repos/vercel/next.js')
  const repo = await res.json()
  return { props: { repo } }
}) satisfies GetStaticProps<{
  repo: Repo
}>
 
export default function Page({
  repo,
}: InferGetStaticPropsType<typeof getStaticProps>) {
  return repo.stargazers_count
}
pages/index.js
export async function getStaticProps() {
  const res = await fetch('https://api.github.com/repos/vercel/next.js')
  const repo = await res.json()
  return { props: { repo } }
}
 
export default function Page({ repo }) {
  return repo.stargazers_count
}

렌더링 타입과 무관하게, 모든 props는 페이지 컴포넌트로 전달되며 초기 HTML 클라이언트 사이드에서 볼 수 있다는 것을 주의하세요. 이것은 hydrate (opens in a new tab)가 제대로 실행되기 위함입니다. 클라이언트에서 사용하면 안되는 어떠한 민감한 정보도 props에 전달해서는 안됩니다.

getStaticProps API referencegetStaticProps에서 사용할 수 있는 모든 파라미터와 props를 포함합니다.

When should I use getStaticProps?

다음과 같은 상황에서 getStaticProps 를 사용할 수 있습니다.

  • 페이지 렌더링에 필요한 데이터가 유저의 요청 이전인 빌드 타임에 사용 가능해야 할 때
  • 데이터가 headless CMS 으로부터 제공될 때
  • 페이지가 SEO를 위해서 반드시 미리 렌더링 되어야 하고 매우 빨라야 할 때 - getStaticProps는 HTMLJSON 파일을 생성합니다. 두 가지 모두 성능을 위해 CDN에 캐시를 저장합니다.
  • 데이터는 개별 사용자 별로가 아니라 공개적으로 캐시되어야 할 때. 이 조건은 경로를 재설정하기 위해 미들웨어를 사용하는 방식으로 특정 상황에서 우회될 수 있습니다.

When does getStaticProps run

getStaticProps 항상 서버에서 실행되며 클라이언트에서는 실행되지 않습니다. 이 도구 (opens in a new tab)를 사용하여 클라이언트 bundle에서 제거된 getStaticProps 내부에 작성된 코드를 검증할 수 있습니다.

  • getStaticProps 는 항상 next build 중 실행됩니다.
  • getStaticPropsfallback: true를 사용할때 백그라운드에서 실행됩니다.
  • getStaticPropsfallback: blocking을 사용할때 초기 렌더링 이전에 호출됩니다.
  • getStaticPropsrevalidate를 사용할때 백그라운드에서 실행됩니다.
  • getStaticPropsrevalidate()를 사용할때 수요에 따라 백그라운드에서 실행됩니다.

Incremental Static Regeneration와 결합할 때, getStaticProps는 오래된 페이지가 재검증 되는 동안 백그라운드에서 실행될 수 있으며 브라우저에서 새 페이지가 제공됩니다.

getStaticProps는 정적 HTML을 생성하기 때문에, 쿼리 파라미터 또는 HTTP 헤더와 같이 들어오는 요청에 접근할 수 없습니다. 만약 페이지를 위한 요청에 접근하고 싶다면, getStaticProps미들웨어 를 함께 사용하는 것을 고려해야합니다.

Using getStaticProps to fetch data from a CMS

다음 예제는 CMS로부터 어떻게 blog posts 리스트를 가져오는지 보여줍니다.

pages/blog.tsx
// posts는 getStaticProps()에 의해 빌드 타임에 생성됩니다.
export default function Blog({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li>{post.title}</li>
      ))}
    </ul>
  )
}
 
// 이 함수는 서버 사이드 빌드 타임에 호출됩니다.
// 클라이언트 사이드에서는 호출되지 않습니다. 따라서
// 직접 데이터베이스 쿼리를 수행할 수도 있습니다.
export async function getStaticProps() {
  // posts를 얻기 위해서 외부 API endpoint를 호출합니다.
  // 모든 fetching library 를 사용할 수 있습니다.
  const res = await fetch('https://.../posts')
  const posts = await res.json()
 
  // { props: { posts } }를 반환함으로써
  // Blog 컴포넌트는 빌드타임에 posts를 props로 받습니다.
  return {
    props: {
      posts,
    },
  }
}

getStaticProps API referencegetStaticProps에서 사용할 수 있는 모든 파라미터와 props를 포함합니다.

Write server-side code directly

getStaticProps는 서버 사이드에서만 실행되고 클라이언트 사이드에서는 절대로 실행되지 않습니다. 브라우저용 JS 번들에 포함되지 않기 때문에 이를 브라우저에 보내지 않고 직접 데이터베이스 쿼리를 작성할 수 있습니다.

이것은 getStaticProps 로 부터 API 라우트를 가져오는 대신 외부 소스로부터 데이터를 가져오는 getStaticProps 에서 직접 서버 사이드 코드를 작성할 수 있다는 것을 의미합니다.

다음 예제를 살펴보면 API 라우트는 CMS로부터 데이터를 가져오기 위해 사용됩니다. 해당 API 라우트는 getStaticProps 에서 직접 호출됩니다. 이렇게 하면 추가적인 호출이 발생하여 성능이 저하됩니다. 대신 CMS에서 데이터를 가져오는 로직을 lib/ 폴더를 사용하여 공유할 수 있습니다. 그리고 이것은 getStaticProps와 함께 공유할 수 있습니다.

lib/load-posts.js
// 이 함수는
// getStaticProps 와 API 라우트와 함께
// `lib/` 폴더 에서 공유됩니다.
export async function loadPosts() {
  // Call an external API endpoint to get posts
  const res = await fetch('https://.../posts/')
  const data = await res.json()
 
  return data
}
pages/blog.js
// pages/blog.js
import { loadPosts } from '../lib/load-posts'
 
// 이 함수는 서버 사이드에서만 실행됩니다.
export async function getStaticProps() {
  // `/api` 라우트에서 가져오는 대신에
  // 동일한 함수를 `getStaticProps`안에서 직접 호출할 수 있습니다.
  const posts = await loadPosts()
 
  // 반환된 props는 page 컴포넌트로 전달됩니다.
  return { props: { posts } }
}

또는, 데이터를 가져오기 위해 API 라우트를 사용하지 않을경우, fetch() (opens in a new tab) API 는 데이터를 가져오기 위해 getStaticProps안에서 직접 사용될 수 있습니다.

클라이언트 사이드 bundle에서 Next.js가 무엇을 제거하는지 확인하기 위해서, next-code-elimination tool (opens in a new tab)를 사용할 수 있습니다.

Statically generates both HTML and JSON

getStaticProps를 사용하는 페이지가 빌드 타임에서 미리 렌더링 될 때, HTML 파일을 추가하기 위해서, Next.js는 getStaticProps를 실행한 결과를 담은 JSON 파일을 생성합니다.

이 JSON 파일은 next/link (opens in a new tab) 나 next/router (opens in a new tab) 를 통해 클라이언트 사이드에서 사용될 수 있습니다. getStaticProps를 사용하여 미리 렌더링된 페이지로 이동할때, Next.js는 빌드 타임에 미리 계산된 JSON 파일을 가져옵니다. 이것은 클라이언드 사이드 페이지 전환은 내보낸 JSON만 사용하므로 getStaticProps를 호출하지 않는다는 것을 의미합니다.

Incremental Static Generation를 사용할때, 클라이언트 사이드 이동에 필요한 JSON을 생성하기 위해 getStaticProps 가 백그라운드에서 실행됩니다. 동일한 페이지에 대한 요청이 여러번 이루어지는 것으로 볼 수도 있지만, 이것은 의도된 것이며 최종 사용자 성능에는 영향을 미치지 않습니다.

Where can I use getStaticProps

getStaticProps 은 오직 페이지에서 export 되어야 합니다. 페이지가 아닌 파일, _app, _document, 또는 _error. 에서는 export 할 수 없습니다.

이러한 제약의 이유 중 하나는 React는 페이지가 렌더링되기 전에 필요한 모든 데이터를 가지기를 원하기 때문입니다.

또한, getStaticProps는 독립 함수으로써 내보내야합니다. - 만약 getStaticProps를 페이지 컴포넌트의 속성으로 추가한다면 작동하지 않습니다.

알아두면 좋은 점: 만약 custom app 를 생성한다면, 연결된 문서에 나와있는 것처럼 페이지 컴포넌트로 pageProps 를 전달하세요. 그렇지 않으면 props는 비어있을 것입니다.

Runs on every request in development

개발 환경(next dev)에서, getStaticProps는 각 요청마다 호출됩니다.

Preview Mode

미리보기 모드를 사용하여 일시적으로 정적 생성을 우회하고 빌드 타임 대신 요청 타임에 페이지를 렌더링할 수 있습니다. 예를 들어 headless CMS 를 사용 중이거나 출시되기 이전에 초안을 미리 보고싶을 때 해당 모드를 사용할 수 있습니다.