Next.js에서 동적 경로를 가진 페이지를 SSG(Static Site Generation) 방식으로 사전 렌더링하는 설정 방법에 대해 살펴보도록 하자.
Next.js에서 SSG 방식을 적용하려면 getStaticProps
함수를 작성한 후 export
로 내보내기만 하면 된다. 이 함수는 빌드 타임에 한 번만 실행되며, 페이지에 필요한 데이터를 사전 렌더링할 수 있다.
// pages/book/[id].tsx
import { GetStaticPropsContext, InferGetServerSidePropsType } from "next";
import style from "./[id].module.css";
import fetchOneBook from "@/lib/fetch-one-book";
import { useRouter } from "next/router";
export const getStaticProps = async (context: GetStaticPropsContext) => {
const id = context.params!.id;
const book = await fetchOneBook(Number(id));
if (!book) {
return {
notFound: true,
};
}
return {
props: {
book
}
};
};
export default function Page({ book }: InferGetServerSidePropsType<typeof getStaticProps>) {
const router = useRouter();
const {
title,
subTitle,
description,
author,
publisher,
coverImgUrl
} = book;
return (
<>
<div className={style.container}>
<div
className={style.cover_img_container}
style={{ backgroundImage: `url('${coverImgUrl}')` }}>
<img src={coverImgUrl} />
</div>
<div className={style.title}>{title}</div>
<div className={style.subTitle}>{subTitle}</div>
<div className={style.author}>
{author} | {publisher}
</div>
<div className={style.description}>{description}</div>
</div>
</>
)
}
이렇게 하면 이 페이지는 이제 SSG방식으로 동작하게 되어서,
getStaticProps
함수는 빌드 타임에 실행되고, props
객체로 페이지 컴포넌트에 데이터를 전달한다. book 데이터가 존재하지 않으면 notFound: true
를 반환하여 404 페이지
를 보여준다.
그런데 이 상태에서 브라우저를 새로고침 하면getStaticPaths is required for dynamic SSG pages and is missing for '/book/[id]'.
이런 내용의 오류가 발생한다.
이 에러의 뜻은, 동적인 경로를 갖는 SSG 페이지에는 getStaticPaths
라는 함수가 추가로 필요하다는 내용이다.
동적 경로의 SSG 방식에서 Next.js는 사전 렌더링해야 할 모든 경로를 알아야만 빌드 타임에 각 경로에 해당하는 페이지를 미리 생성할 수 있다. getStaticPaths
없이 단순히 getStaticProps
만 있으면 빌드 타임에 어떤 경로를 대상으로 페이지를 렌더링해야 할지 알 수 없기 때문에 getStaticPaths
가 반드시 필요하다.
동적 경로는 pages/book/[id].tsx
처럼 URL 파라미터가 포함된 여러 경로를 갖기 때문에, 빌드 타임에 생성할 경로를 명확히 설정해야 한다. 이를 위해 getStaticPaths
함수를 사용한다. 이 함수는 해당 페이지에 존재할 수 있는 모든 경로를 사전에 지정하여 Next.js가 빌드 타임에 HTML 파일로 생성할 수 있도록 한다.
export const getStaticPaths = () => {
return {
paths: [
{params: {id: "1"}},
{params: {id: "2"}},
{params: {id: "3"}},
],
fallback: false,
}
}
이 코드는 예를 들어, book/1
, book/2
, book/3
과 같은 경로가 존재할 수 있다고 정의하는 과정이다.
getStaticPaths
라는 함수를 호출하면 현재 이 페이지에 존재할 수 있는 경로들을 먼저 설정한 다음에 그렇게 설정된 경로들에 해당하는 페이지들을 getStaticProps
함수를 일일이 한번씩 다 호출해서 사전에 여러개의 페이지를 렌더링 하는 방식으로 동작시킨다.
paths
는 현재 페이지에서 사용할 수 있는 모든 URL 파라미터를 정의한 배열로, Next.js가 어떤 경로를 사전 렌더링해야 하는지 알려주는 역할을 한다.
예시에서 paths 배열은 { id: "1" }
, { id: "2" }
, { id: "3" }
와 같이 각 경로를 params 객체 형태로 지정한다.
참고로 Next.js는 URL 파라미터 값을 반드시 문자열로 인식하기 때문에, id 값도 문자열 형태로 작성해야 한다.
사전 렌더링 과정에서는 이러한 경로들에 해당하는 모든 페이지들을 각각 다 생성하게 된다.
그럼 사전 렌더링 과정에서 book/1.html
, book/2.html
, /book/3.html
이라는 3개의 html문서를 사전 렌더링 하게 된다. 그리고 build가 종료된 이후에 브라우저가 book/1
페이지로 접속 요청을 보내면 앞서 만들어놨던book/1.html
페이지를 전달해 주게 된다.
fallback
옵션은 동적 경로의 SSG 페이지에서 예외 상황에 대비하는 설정이다. paths
에 지정되지 않은 경로가 요청될 경우 어떻게 처리할지 미리 정의해 두는 역할을 한다. 예를 들어, paths에 { id: "1" }
, { id: "2" }
, { id: "3" }
와 같은 경로만 설정해 두었는데 book/4
와 같은 다른 경로로 접속 요청이 들어온다면, 이 요청에 대한 대비책이 필요한데, fallback 옵션이 바로 이를 결정한다.
이 옵션의 값에 따라 paths
에 미리 정의되지 않은 경로에 대한 처리 방식이 달라지며, 사용자 경험을 적절히 관리할 수 있다.
fallback 옵션에는 false
, true
, 'blocking'
세 가지가 있다.
false
는 지정되지 않은 경로로 요청이 들어오면 404 페이지
를 반환한다. 예를 들어, /book/4
로 접속 시 Not Found
페이지가 표시된다.
fallback이 true
또는 'blocking'
일 때는 지정되지 않은 경로가 들어오면 해당 경로를 요청 시점에 SSR
방식으로 생성한다. 이후 생성된 페이지는 캐싱되어 같은 경로 요청 시 바로 응답된다.
이제 SSG설정을 완료한 book페이지의 사전 렌더링이 잘 진행되는지 프로젝트를 build하고 결과를 살펴보자
book페이지를 확인해 보면 우리가 앞서 설정한대로 book/1
, book/2
, book/3
페이지를 정적으로 잘 생성해 둔 걸 확인 할 수 있다.
그리고 빌드 결과물에서 각 페이지별 생성된 파일을 .next/server/pages/book/
디렉토리에서 확인할 수 있다. 보면 1.html
, 2.html
, 3.html
등의 파일이 각각 HTML로 생성되어 있고, 페이지가 미리 렌더링된 상태로 저장된다. 따라서 빌드 후에 사용자가 /book/1
, /book/2
경로로 접속할 때 빠르게 응답할 수 있다.
getStaticProps
와 getStaticPaths
로 동적 경로 페이지를 SSG
방식으로 설정할 수 있다.
빌드 타임에 모든 경로를 사전 렌더링하여 최적화된 정적 페이지를 생성한다.
지정된 경로 외에 요청이 들어오면 fallback
옵션에 따라 404 페이지
처리 또는 SSR
방식을 사용할 수 있다.
이 방식으로 Next.js는 동적 경로의 데이터를 사전에 렌더링하여 사용자에게 빠르게 응답할 수 있으며, 지정된 경로에 대한 최적화된 정적 페이지를 빌드 타임에 준비해 둘 수 있다.