[Next.js] SSG과 ISR (feat. 병렬라우팅에서의 SSG)

강경서·2024년 7월 11일
0
post-thumbnail

Intro

SSG(Static Site Generation)는 빌드 시 정적인 HTML을 미리 생성합니다. 이는 요청마다 HTML을 생성하는 SSR보다 더 빠른 페이지 로딩을 제공하는 장점이 있습니다. 다만 데이터를 업데이트하더라도 페이지가 빌드 시 이미 생성되었으므로 새로운 페이지를 받아 볼 수 없습니다. 만약 SSG를 사용하면서 업데이트된 페이지가 필요하다면 설정한 시간마다 HTMl을 생성하는 ISR(Incremental-Static-Regeneration)을 사용할 수 있습니다.

진행 중인 프로젝트에서 매장별 매뉴를 보여주는 페이지는 데이터가 자주 변경되지 않으므로 SSG 또는 ISR로 구현하면 사용자에게 더 빠른 페이지를 보여줄 수 있다고 생각하여 이를 구현해 보았습니다.


SSG(generateStaticParams)

Next.js는 기본적으로 정적 사이트 생성(SSG)을 지원합니다. 다만 동적인 콘텐츠를 생성해야 하는 경우에는 SSR을 이용하여 페이지를 랜더링합니다. 즉 동적 라우트를 사용하는 상세 페이지 같은 경우에는 SSR을 통해 페이지를 랜더링하게 됩니다. 이를 정적 사이트를 생성하기 위해서는 generateStaticParams를 사용해야 합니다.

// src/app/cafe/[id]
export async function generateStaticParams() {
  const querySnapshot = await getDocs(collection(db, 'brand'));
  const brands = querySnapshot.docs.map(doc => {
    return { id: doc.id, ...doc.data() } as BrandType;
  });

  return brands.map(brand => ({
    id: brand.id,
  }));
}

export default async function CafeDetail({
  params: { id },
}: {
  params: { id: string };
}) {
  const menus = await fetchData(id);
  return (
    <div className='absolute right-0 top-0 z-[100] flex h-dvh w-screen items-center justify-center bg-black/80'>
      <ModalContainer menus={menus} />
    </div>
  );
}

위와 같이 generateStaticParams를 이용하여 동적 라우팅의 세그먼트를 반환하면 정적 사이트를 생성할 수 있습니다.


ISR(revalidate)

동적 라우팅 페이지를 SSG로 구현했다면 초기 로딩 시간이 단축을 통해 사용자 경험이 개선됐을지도 모릅니다. 하지만 해당 페이지의 데이터가 업데이트됐다 하더라도 해당 페이지는 이미 빌드 시 생성된 페이지이므로 사용자는 새로 업데이트된 데이터를 확인할 수 없습니다. 이런 상황에서는 revalidate를 통해 페이지의 데이터를 재검증하여 새로운 페이지를 랜더링하는 ISR을 사용할 수 있습니다.

// src/app/cafe/[id]
export async function generateStaticParams() {
  const querySnapshot = await getDocs(collection(db, 'brand'));
  const brands = querySnapshot.docs.map(doc => {
    return { id: doc.id, ...doc.data() } as BrandType;
  });

  return brands.map(brand => ({
    id: brand.id,
  }));
}

export const revalidate = 10;

export default async function CafeDetail({
  params: { id },
}: {
  params: { id: string };
}) {
  const menus = await fetchData(id);
  return (
    <div className='absolute right-0 top-0 z-[100] flex h-dvh w-screen items-center justify-center bg-black/80'>
      <ModalContainer menus={menus} />
    </div>
  );
}

export const revalidate = 10; 이는 처음 페이지가 요청되고 10초가 지나면 다음 요청이 들어올때까지 데이터를 재검증하고 재생성합니다.


병렬 라우트에서 SSG 구현

병렬 라우팅을 사용하는 페이지에서 generateStaticParams를 사용하여 SSG을 구현하려고 했지만, 빌드 시 SSG로 생성되지 않았습니다.

이는 병렬 라우팅이 작동되는 같은 층의 layout 에서 generateStaticParams를 사용하여 세그먼트를 반환해야 SSG로 정상적으로 생성됩니다.


🧾 Reference

profile
기록하고 배우고 시도하고

0개의 댓글