SSG 사전 렌더링 방식을 프로젝트에 적용을 해보겠습니다.
가장 먼저 index 페이지부터 SSG 방식으로 구현해보겠습니다.
특정 페이지를 SSG 방식으로 작동 시키는 방법은 SSR 방식과 비슷합니다.
SSR에서는 getServerSideProps였다면, SSG는 getStaticPorps 함수를 사용하면 됩니다.
export const getStaticProps = async () => {
참고로 getStatocProps 함수는 getServerSideProps 함수와 동일하게 사전 렌더링 과정에서 필요한 데이터를 불러온 다음에 props로써 컴포넌트에게 전달하는 역할을 할 수 있습니다.
return {
props: {
allBooks,
recoBooks,
},
};
페이지 함수에서도 getStaticProps 함수로부터 전달받은 데이터들을 props로 받아와서 컴퍼넌트 내부에서 자유롭게 사용하면 됩니다.
export default function Home({ allBooks, recoBooks }
그런데 대신에 props 타입을 정의할 때 InferGetServerSidePropsType를 사용하는 것이 아닌 InferGetStaticPropsType 을 사용한다음 제네릭으로는 typeof getStaticProps를 전달하면 됩니다.
export default function Home({ allBooks, recoBooks }: InferGetStaticPropsType<typeof getStaticProps>)
getStaticProps 함수 안에 console.log로 인덱스 페이지라는 메세지를 출력하도록 설정합니다.
export const getStaticProps = async () => {
console.log("인덱스 페이지")
const [allBooks, recoBooks] = await Promise.all([fetchBooks(), fetchRandomBooks()]);
return {
props: {
allBooks,
recoBooks,
},
};
SSG 방식은 빌드타임에서 딱 한번만 실행되기 때문에 getStaticProps 함수도 한 번만 실행이 되고 그렇기에 console.log도 한번만 실행이 되는 것을 확인해야 합니다.
하지만 터미널을 살펴보면

이상하게 새로고침을 할때마다 계속해서 함수가 실행되고 있는것을 확인할 수 있습니다.
그 이유는 바로 Next.js 앱을 개발 모드로 실행하고 있기 때문입니다.
Next.js 개발 모드는 개발자가 수정할때마다 편리하게 바로 보여주기 위해 SSR이던 SSG이던 그냥 요청을 받을 때마다 계속해서 새롭게 페이지를 사전 렌더링 하게 됩니다.
진짜 잘 작동하는지 확인하려면
npm run build
를 통해 살펴보면 Generating static pages에서 함수가 실행된 것을 확인할 수 있습니다.

또한 index 페이지에서는 흰색 동그라미 기호를 확인할 수 있습니다.

다른 book 페이지나 search 페이지는 f 기호를 확인할 수 있습니다.
기호의 의미는 빌드의 최하단에 의미를 살펴볼 수 있습니다.

만약 우리가 SSR이나 SSG 설정을 하지 않았다면 404나 test 페이지처럼 기본적으로 SSG 페이지로 설정이 된다고도 이해 가능합니다.
다음
npm run dev
를 통해 실행시켜주며 새로고침을 해도 함수는 한 번밖에 실행되지 않는것을 확인하고 페이지 속도 또한 매우 빠르다는 것을 알 수 있습니다.
search의 index도 똑같이
getStaticeProps로 함수를 변경합니다.
context도 GetServerSidePropsContext가 아닌 GetStaticePropsContext로 바꿔주면 SSG로 작동이 됩니다.
export const getStaticProps = async (context: GetStaticPropsContext)
이때
const q = context.query.q;
부분에서 타입 오류가 발생합니다. 오류의 내용은 "GetStaticPropsContext 형식에 query 속성이 없습니다" 입니다.
이 오류는 query라는 프로퍼티가 존재하지 않는다는 뜻입니다.
그 이유는 getStaticProps 함수는 빌드타임에 한 번만 실행되기 때문입니다.
query string은 사용자가 직접 전달하는 공간이기 때문에 빌드타임에서는 알아낼 방법이 없습니다.
결론적으로 search 페이지는 SSG 방식으로 동작시킬 수 없습니다.
만약 SSG 방식으로 만들다고 한다면 기존의 React 방식으로 구현하는 방법이 있습니다.
export default function Page() {
const [books, setBoooks] = useState<BookData[]>([]);
const router = useRouter();
const q = router.query.q;
const fetchSearchResult = async () => {
const data = await fetchBooks(q as string);
setBoooks(data);
};
useEffect(() => {
if (q) {
fetchSearchResult();
}
}, [q]);
return (
<div>
{books.map((book) => (
<BookItem key={book.id} {...book} />
))}
</div>
);
}
Page.getLayout = (page: ReactNode) => {
return <SearchableLayout>{page}</SearchableLayout>;
};
기존의 SSR이나 SSG를 설정을 안해두면 기본적으로 SSG 방식으로 동작하기 때문에 npm run build와 npm run start를 통해 확인해보시면 SSG 방식으로 구동되는 것을 확인할 수 있습니다.