NextJS API: getStaticProps

hwisaac·2023년 3월 13일
0

NextJS API(page router)

목록 보기
5/10

getStaticProps

getStaticProps라는 함수를 export하면 함수에서 반환한 props를 사용하여 페이지를 빌드 시에 프리렌더링할 수 있습니다:

export async function getStaticProps(context) {
  return {
    props: {}, // 페이지 컴포넌트에서 props로 전달됩니다
  }
}

getStaticProps에서는 모듈을 import하여 데이터베이스에서 데이터를 가져와 서버쪽에서 코드를 직접 작성할 수 있습니다. 사용된 import는 클라이언트 쪽에서 번들링되지 않습니다.

Context 매개변수

Context 매개변수는 다음과 같은 키를 가지는 객체입니다:

  • params는 동적 라우트를 사용하는 페이지에서 라우트 매개변수를 포함합니다. 예를 들어, 페이지 이름이 [id].js라면 params{ id: ... }와 같습니다. getStaticPaths와 함께 사용해야 합니다.
  • preview는 페이지가 미리보기 모드인지(true) 그렇지 않은지(undefined) 여부를 나타냅니다.
  • previewDatasetPreviewData에 의해 설정된 미리보기 데이터를 포함합니다.
  • locale은 활성 로캘을 포함합니다(활성화된 경우).
  • locales는 모든 지원되는 로캘을 포함합니다(활성화된 경우).
  • defaultLocale은 구성된 기본 로캘을 포함합니다(활성화된 경우).

getStaticProps 반환값

getStaticProps 함수는 props, redirect, 또는 notFound옵션으로 revalidate 속성을 포함하는 객체를 반환해야 합니다.

props

props 객체는 키-값 쌍으로, 페이지 컴포넌트에서 전달된 각 값이 포함됩니다. serialize할 수 있는 객체이어야 합니다.

export async function getStaticProps(context) {
  return {
    props: { message: `Next.js is awesome` }, // ㅜ 자페이지 컴포넌트로 props로 전달됩니다
  }
}

revalidate

revalidate 속성은 페이지 재생성이 발생할 수 있는 시간(초)을 나타냅니다(기본값은 false 또는 재검증 없음).

// 이 함수는 서버 측에서 빌드 시간에 호출됩니다.
// revalidate가 활성화되어 있고 새 요청이 들어오면
// 서버리스 함수에서 다시 호출됩니다.
export async function getStaticProps() {
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  return {
    props: {
      posts,
    },
    // Next.js는 페이지를 다시 생성하려고 시도합니다:
    // - 요청이 들어오면
    // - 10초 이내에 최대 1번
    revalidate: 10, // 초 단위
  }
}

자세한 내용은 ISR

ISR을 활용하는 페이지의 캐시 상태는 x-nextjs-cache 응답 헤더의 값을 읽어 판별할 수 있습니다. 가능한 값은 다음과 같습니다:

  • MISS - 해당 경로가 캐시에 없음 (첫 방문 시 최대 한 번 발생)
  • STALE - 해당 경로가 캐시에 있지만 다시 유효화 시간을 초과하여 백그라운드에서 업데이트됩니다.
  • HIT - 해당 경로가 캐시에 있으며 유효화 시간을 초과하지 않았습니다.

notFound

notFound 부울 값은 페이지가 404 상태와 404 페이지를 반환하도록 허용합니다. notFound: true를 사용하면 이전에 성공적으로 생성된 페이지가 있어도 페이지가 404을 반환합니다. 이는 사용자가 생성한 콘텐츠가 작성자에 의해 제거되는 경우와 같은 사용 사례를 지원하기 위한 것입니다. 참고로 notFound는 여기에서 설명하는 유효화 동작을 따릅니다.

export async function getStaticProps(context) {
  const res = await fetch(`https://.../data`)
  const data = await res.json()

  if (!data) {
    return {
      notFound: true,
    }
  }

  return {
    props: { data }, // 페이지 구성 요소로 전달됨
  }
}

참고: fallback: false 모드에서는 getStaticPaths에서 반환된 경로만 사전 렌더링됩니다.

redirect

redirect 객체를 사용하면 내부 또는 외부 리소스로 리디렉션할 수 있습니다. { destination: string, permanent: boolean } 형태와 일치해야 합니다.

일부 드문 경우에는 이전 HTTP 클라이언트가 올바르게 리디렉션하려면 사용자 정의 상태 코드를 할당해야 할 수 있습니다. 이러한 경우에는 permanent 속성 대신 statusCode 속성을 사용할 수 있지만 둘 다 사용할 수는 없습니다. 또한 next.config.js에서 리디렉션을 수행하는 경우 basePath: false를 설정할 수도 있습니다.

export async function getStaticProps(context) {
  const res = await fetch(`https://...`)
  const data = await res.json()

  if (!data) {
    return {
      redirect: {
        destination: '/',
        permanent: false,
        // statusCode: 301
      },
    }
  }

  return {
    props: { data }, // 페이지 구성 요소로 전달됨
  }
}

리디렉션은 빌드 타임에 알려진 경우 next.config.js에 추가해야 합니다.

파일 읽기: process.cwd() 사용

getStaticProps에서 파일을 직접 파일 시스템에서 읽을 수 있습니다.

이를 위해서는 파일의 전체 경로를 가져와야 합니다.

Next.js는 코드를 별도의 디렉토리로 컴파일하므로 pages 디렉토리와 다른 경로를 반환하는 __dirname을 사용할 수 없습니다.

대신 process.cwd()를 사용하면 Next.js가 실행되는 디렉토리를 얻을 수 있습니다.

import { promises as fs } from 'fs'
import path from 'path'

// getStaticProps에 의해 빌드 타임에 post가 생성됩니다.
function Blog({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li>
          <h3>{post.filename}</h3>
          <p>{post.content}</p>
        </li>
      ))}
    </ul>
  )
}

// 이 함수는 서버 사이드에서 빌드 타임에 호출됩니다.
// 클라이언트 사이드에서는 호출되지 않으므로
// 직접 데이터베이스 쿼리를 수행할 수 있습니다.
export async function getStaticProps() {
  const postsDirectory = path.join(process.cwd(), 'posts')
  const filenames = await fs.readdir(postsDirectory)

  const posts = filenames.map(async (filename) => {
    const filePath = path.join(postsDirectory, filename)
    const fileContents = await fs.readFile(filePath, 'utf8')

    // 일반적으로 내용을 파싱/변환합니다.
    // 예를 들어 마크다운을 HTML로 변환할 수 있습니다.

    return {
      filename,
      content: fileContents,
    }
  })
  // { props: { posts } }를 반환함으로써
  // Blog 컴포넌트가 빌드 타임에 `posts`를 prop으로 전달받게 됩니다.
  return {
    props: {
      posts: await Promise.all(posts),
    },
  }
}

export default Blog

TypeScript에서 getStaticProps 사용하기

getStaticProps의 타입은 next에서 제공하는 GetStaticProps를 사용하여 지정할 수 있습니다:

import { GetStaticProps } from 'next'

type Post = {
  author: string
  content: string
}

export const getStaticProps: GetStaticProps<{ posts: Post[] }> = async (
  context
) => {
  const res = await fetch('https://.../posts')
  const posts: Post[] = await res.json()

  return {
    props: {
      posts,
    },
  }
}

props의 추론 타입을 얻으려면 InferGetStaticPropsType<typeof getStaticProps>를 사용할 수 있습니다:

import type { InferGetStaticPropsType, GetStaticProps } from 'next'

type Post = {
  author: string
  content: string
}

export const getStaticProps: GetStaticProps<{ posts: Post[] }> = async () => {
  const res = await fetch('https://.../posts')
  const posts: Post[] = await res.json()

  return {
    props: {
      posts,
    },
  }
}

function Blog({ posts }: InferGet

0개의 댓글