SSG(Static Site Generation, 정적 사이트 생성)
SSR의 단점을 해결하기 위한 사전 렌더링 방식
빌드 시 API등으로 부터 데이터를 얻어, 페이지를 미리 사전 렌더링 해두는 방식
SSG 빌드시 흐름
빌드 시 getStaticProps()라는 함수가 호출되며, 그 함수 안에서 API 호출 등을 수행하고, 페이지를 그리는데 필요한 props를 반환합니다. 그 뒤 이 props를 페이지 컴포넌트에 전달해서 화면을 그립니다.
화면을 그린 결과는 정적 파일의 형태로 빌드 결과로 저장합니다.
빌드 결과는 .next 폴더 → server 폴더에서 확인 가능합니다.
기본 골격
SSG가 필요한 Page에 아래와 같은 getStaticProps() 함수를 추가해 준다.
// 기본 골격
export const getStaticProps = async (context: GetStaticPropsContext) => {
return {
props: { }
}
}
SSG로 배포된 프로젝트 흐름
SSG로 배포된 프로젝트가 배포되어 아래와 같이 접속 요청을 했을때,
페이지에 접근이 발생하면, 미리 생성한 정적 파일을 클라이언트에 보내고 브라우저는 그것을 기반으로 화면을 그립니다
그렇기 때문에 사전 렌더링에 많은 시간이 소요되는 페이지더라도 사용자의 요청에는 매우 빠른속도로 응답 가능하다는 장점이 존재하고,
매번 요청이 있더라도 동일한 페이지(완성된 페이지)를 보여주기 때문에 실시간 최신 데이터 반영은 어렵다라는 단점이 존재합니다.
동적(Dynamic) SSG
블로그의 상세 화면을 만든다고 생각해보자.
각 상세 페이지마다 존재하는 ID들이 있을것이고, 그 ID에 맞춰 동적으로 데이터를 가져와야할 것 이다.
Next서버측에서 빌드 타임에 SSG방식으로 렌더링하기 위해서는 먼저 선수 과정으로 각 페이지에 어떤 Params들이 존재할 수 있는지, 그러므로써 어떠한 경로들이 존재할 수 있는지 설정하는 과정이 반드시 필요하다 (SSG 이기 때문에!)
이때 이 역할을 하는 함수가 getStaticPaths() 이다.
기본 골격
getStaticPaths는 getStaticProps 가 실행전에 호출되는 함수로, 생성할 페이지의 경로 파라미터의 조합(path)과 폴백(fallback)을 반환합니다.
- paths ⇒ 경로 파라미터의 조합
- fallback ⇒ 생성하는 페이지가 존재하지 않는 경우의 처리를 기술
// 기본 골격
export const getStaticPaths = () => {
return {
paths: [
{ params: { ... } }
],
fallback: true | false | 'blocking'
}
}
fallback에는 3가지 옵션이 있다.
- false: 없는 옵션경로로 요청시 404 에러 발생
- true: 없는 옵션경로로 요청이 오면 페이지를 먼저 보여주고 getStaticProps를 실행하여 페이지를 만들어줌, isFallback이 상태로 로딩화면 추가 가능
- "blocking": true와 비슷하지만 페이지 생성중에 fallback 페이지를 보여주지 않고(이전화면이 멈춘것처럼 보임), SSR처럼 동작해서 아무것도 미리 보여주지 않게 된다. isFallback이 상태로 로딩화면 불가
예제
export const getStaticPaths = () => {
return {
// 리턴으로 배열의 params 객체에 문자열만 가능
paths: [
{ params: { id: "1" } },
{ params: { id: "2" } },
{ params: { id: "3" } },
],
// fallback(대비책)
fallback: true,
};
};
export const getStaticProps = async (context: GetStaticPropsContext) => {
console.log("Context", context.params!.id);
const id = Number(context.params!.id);
const book = await fetchOneBook(id);
if (!book) {
return {
notFound: true,
};
}
return {
props: {
book,
},
};
};
export default function Page({
book,
}: InferGetStaticPropsType<typeof getStaticProps>) {
const router = useRouter();
if (router.isFallback) {
return <div>로딩중...</div>;
}
if (!book) {
return <div>문제가 발생하였습니다. 다시 시도해주세요.</div>;
}
const { id, title, subTitle, description, author, publisher, coverImgUrl } =
book;
return (
<div className={style.container}>
{...}
</div>
);
}
따라서, 실시간성 콘텐츠에는 적합하지 않고 정적 데이터를 다루는데 적합합니다.
성능이 뛰어나므로 SSR보다 SSG를 권장합니다.