상세 컨텐츠

본문 제목

[Next.js] 동적 라우팅 페이지에 SSG 적용해서 페이지 로딩 속도 개선하기

Project/포트폴리오(NextJS + Notion API)

by yooputer 2025. 7. 16. 16:40

본문

https://my-portfolio-nextjs-lemon.vercel.app/

 

Kim Yoojin Portfolio

Built with Next.js, Tailwind CSS and shadcn/ui, Notion API. Deployed with Vercel. Contact Email : yooputer@gmail.com

my-portfolio-nextjs-lemon.vercel.app

 

최근에 Next.js와 노션 API를 사용하여 개발자 포트폴리오를 구축하였다. 

그리고 배포를 했는데, 메인, 프로젝트 목록, 스킬 페이지는 내용이 바로바로 뜨는데

프로젝트 상세 페이지에만 접속하면 유독 페이지가 늦게 떴다. (진짜 느릴 때는 20초정도?)

 

그래서 아니 늦게뜰꺼면 다 늦게 뜨고, 빨리 뜰꺼면 다 빨리 뜰 것이지

왜 일부 페이지만 이렇게 느리게 로드되는거지?라는 의문이 들었다. 

 

그러다 Next.js의 특징중 하나인 SSG(Static Site Generator)가 떠올랐고, 

프로젝트 상세 페이지는 동적 라우팅을 사용하기 때문에 SSG가 적용되지 않는구나! 라는 생각이 들었다. 

 

그래서 이번 포스팅에서는 동적 라우팅 페이지에 SSG를 적용하여

페이지 로딩 속도를 개선한 과정에 대해 정리해보려 한다. 


SSG란?

SSG(Static Site Generator)란 빌드할 때 페이지를 렌더링한 후 캐싱하여 페이지 로딩 속도를 높이는 기능이다. 

 

SSG vs SSR

내 프로젝트의 경우 app router를 사용하고 모두 서버 컴포넌트로 구현하여 대부분의 페이지가 SSG이 적용되었는데, 

프로젝트 상세 페이지(/app/projects/[slug]/page.tsx)는 동적 라우팅을 사용하여 SSR이 적용되고 있었다. 

 

SSR이 적용되는 경우 페이지에 접속할 때마다 노션API를 호출한 후 렌더링하는 과정이 반복되어, 로딩속도가 항상 느렸다. 

slug가 총 7개였어서 이 정도면 모두 SSG를 적용해도 될거 같아서 SSG를 적용하기로 했다. 


동적라우팅 페이지에 SSG 적용하기

파라미터 목록 조회 함수 구현

우선 동적 라우팅에서 path variable로 사용되는 slug 목록을 조회하는 함수를 구현하였다. 

참고로 나는 노션 API를 사용하여 노션 데이터베이스의 slug라는 property 값을 조회하는 것이다. 

export const getProjectSlugs = async () => {
    const response = await notion.databases.query({
        database_id: process.env.NOTION_PROJECT_DATABASE_ID!,
        page_size: 20,
    });

    if (!response.results){
        return [];
    }

    const slugs = response.results
        .filter((page): page is PageObjectResponse => 'properties' in page)
        .map((page) => {
            const { properties } = page;

            return getTextByPropertyName(properties, 'slug');
    });

    return slugs;
}

 

위에 코드에서 사용한 getTextByPropertyName 함수 코드는 다음과 같다. 

export function getTextByPropertyName(properties: PageObjectResponse['properties'], propertyName:string): string {
  if (!properties[propertyName]) {
    return '';
  }

  const type = properties[propertyName].type;

  if (type === 'title' && properties[propertyName].title.length > 0) {
    return properties[propertyName].title[0].plain_text ?? '';
  } else if (type === 'rich_text' && properties[propertyName].rich_text.length > 0){
    return properties[propertyName].rich_text[0].plain_text ?? '';
  }

  return '';
}

 

 

generateStaticParams 함수 구현

이제 동적 라우팅되는 페이지의 page.tsx에 generateStaticParams를 구현하면 된다. 

export async function generateStaticParams() {
    const slugs = await getProjectSlugs();

    return slugs.map(slug => ({
        params: {
            slug: slug,
        },
    }));
}

 

generateStaticParams 함수에 대한 공식문서이다. 

https://nextjs.org/docs/app/api-reference/functions/generate-static-params

 

Functions: generateStaticParams | Next.js

API reference for the generateStaticParams function.

nextjs.org

 


빌드

이제 next build 명령어를 사용하여 정상적으로 SSG가 적용되었는지 확인한다. 

 

/projects/[slug] 페이지가 generateStaticParams를 사용하여 SSG가 적용된 것을 확인할 수 있다. 

 

배포를 하여 확인해보니 프로젝트 상세 페이지도 눈깜빡할세에 로딩되는 것을 확인할 수 있다...! 

 


 

여태껏 SSG에 대해 별로 체감하고 있지 못했는데,

SSG가 적용되지 않는 페이지의 로딩속도를 보니 SSG가 얼마나 체감 로딩 속도를 줄여주는지 느낄 수 있었다. 

 

만약 포트폴리오 사이트처럼 데이터의 변경이 잦지 않은 페이지라면

SSG를 적용하여 페이지 로딩 속도를 개선할 수 있을 것 같다! 

 

관련글 더보기