Next.js의 getStaticProps
와 getStaticPaths
api를 사용하면 static 페이지를 생성할 수 있다.
getStaticProps
: 빌드 시 데이터를 fetch하여 static 페이지를 생성getStaticPaths
:pages/**/[id].tsx
형태의 동적 라우팅 페이지 중, 빌드 시에 static하게 생성할 페이지를 정함
getServerSideProps
라는 것도 있는데, static이 아니라 server side rendering이므로 제외함
getStaticProps
페이지.tsx
에서 export async function getStaticProps(context)
형태로 사용.
context.params
로 동적 라우팅의 경로 이름을 가져온다.
pages/posts/[id].tsx
페이지를/posts/123
으로 접근했다면context.params
는{ id: "123" }
이 된다.
{ props: object }
를 리턴하면, export default
한 리액트 컴포넌트의 parameter로 넘겨진다.
import type { GetStaticProps, InferGetStaticPropsType } from "next";
// GetStaticProps는 getStaticProps의 타입
// InferGetStaticPropsType은 컴포넌트에 사용되는 제네릭 타입
type Post = {
title: string;
}
export const getStaticProps: GetStaticProps = async (context) => {
// async여야 함
const response = await fetch("https://example.com");
const post: Post = await response.json();
// Next.js가 폴리필하는 Fetch API
// https://nextjs.org/docs/basic-features/supported-browsers-features#polyfills
return {
props: {
post
}
// props는 현재 페이지의 default export 컴포넌트의 parameter로 넘겨짐
}
}
const function Blog = ({ post }: InferGetStaticPropsType<typeof getStaticProps>) => {
// { post: Post }로 타입 지정됨
return (
<div>{post.title}</div>
)
}
export default Blog;
getStaticProps
가 필요할 때
When should I use getstaticprops?
- 페이지에 필요한 데이터가 빌드 시에 사용 가능할 때
- 데이터를 headless CMS에서 가져올 때
- 모든 사용자에게 같은 데이터를 보여줄 때
- SEO를 위해서 속도 빠른 페이지가 필요할 때
- 공식 문서에는 없지만 Node api(
path
,fs
등)을 사용해야 할 때
import path from "path";
export const getStaticProps = () => {
const postDirectory = path.resolve(process.cwd(), '/posts');
// process.cwd()는 Next.js 폴더를 가리킴(package.json이 있는 폴더)
// ...
}
getStaticPaths
동적 라우팅을 사용할 때, 어떤 페이지를 미리 Static으로 빌드할 지 정하는 api
import type { GetStaticPaths } from "next";
// GetStaticPaths는 getStaticPaths의 타입
export const getStaticPaths: GetStaticPaths = async () => {
// getStaticProps처럼 async
// ...
return {
paths: [
{ params: {} }
],
// { parmas: {} }[] 형태로 paths 리턴해야 함
// 빌드 시에 해당 페이지들을 static으로 생성
fallback: true | false | 'blocking'
// fallback을 리턴해야 함
}
// 예시
return {
paths: [
{ params: { id: "1" }},
{ params: { id: "2" }}
]
// pages/posts/[id].tsx라고 가정
// pages/posts/1과 pages/posts/2를 static으로 생성
}
// 예시 2
return {
paths: [
{
params: {
id: "1",
title: "first post"
}
},
{
params: {
id: "2",
title: "second post"
}
}
]
// pages/posts/[id]/[title].tsx라고 가정
// pages/posts/1/first post와 pages/posts/2/second post/를 static으로 생성
}
}
fallback
(required)의 리턴 값에 따른 차이
fallback: false
getStaticPaths
에서 리턴하지 않은 페이지는 모두 404로 연결
fallback: true
getStaticPaths
에서 리턴하지 않은 페이지에 접속 시,
- 먼저 사용자에게
fallback
페이지를 보여줌 - 서버에서 static하게 페이지를 생성함
- 해당 페이지를 사용자에게 보여줌
- 다음부터 해당 페이지로 접속하는 사용자에게는 static한 페이지를 보여줌
// pages/posts/[id].tsx
import { useRouter } from "next/router";
// fallback 페이지를 위한 useRouter import
const Post = ({ post }) => {
cont router = useRouter();
if (router.isFallback) {
return <div>Loading...</div>
// fallback = true 시, 접속한 페이지를 생성할 때 보여주는 페이지
}
return (
<div>{post.title}</div>
)
}
export default Post;
export const getStaticPaths = async () => {
return {
paths: [
{ params: { id: 1} }
],
fallback: true
}
}
export const getStaticProps = async ({ params }) => {
const response = await fetch(`https://example.com/${params.id}`);
const post = response.json();
return {
props: { post }
}
}
많은 static 페이지를 생성해야 하지만 빌드 시간이 너무 오래 걸릴 때 사용
fallback: "blocking"
getStaticPaths
에서 리턴하지 않은 페이지에 접속 시,
- 사용자에게 server side rendering한 static 페이지를 보여줌
- 다음부터 해당 페이지로 접속하는 사용자에게는 server side rendering한 static 페이지를 보여줌
즉 fallback
페이지나 로딩 화면이 없다.
동적 라우팅 페이지를 static 페이지로 제공해야 할 때 사용