thumbnail

next13 동적 경로 설정을 해두자! feat.Dynamic paths

생성일2023. 4. 3.
태그
작성자지한솔

안녕하세요!
 
next13은 기본적으로 ssr, ssg, csr을 섞어가면서 사용하는 것을 추구하고있습니다. 그게 또 next.js의 장점이 아닐까 싶기도 하구요. 하지만 server components to client component 의 props 전달 등과 같은 많은 문제점들이 생기게 됩니다. seo에 친화적으려면 또 부득이하게 ssr을 기반으로 csr을 구성해야 하죠..
 
저도 ssr 기반으로 csr 컴포넌트를 섞어서 사용하여 나만의 blog를 만들고 있습니다. 오늘로 blog 포스팅 3번째인데, 오늘은 동적 경로 설정으로 blog의 속도를 높이는 방법에 대해 공유하고자 합니다.

동적 경로?

동적 경로가 왜 필요할까요? 기본적으로 크지 않은 프로젝트, 연산이 크게 필요하지 않는 프로젝트들은 비교적 fetch와 연산 자체가 오래걸리지 않습니다. 하지만 지금 작업하고있는 notion API를 활용한 나만의 blog는 이야기가 다릅니다. 왜??
 
notion API에서는 나의 포스팅을 search해주는 method가 따로 없기때문입니다. 예를들어 100개의 포스팅이 있고, 그 중 31번째 포스팅의 정보를 얻고싶다면 지금의 구조상 100개의 포스팅을 전부 가져와 slug(경로)와의 일치를 통해 id를 가져온 후 다시한번 block 을 get 해오는 구조입니다. 이렇게 구현할 수밖에 없던 이유는 notion에서 한 페이지에 여러 페이지 정보를 담기위해서는 어쩔 수 없는 테이블 구조로 이루어져 있기 때문입니다.
 
그럼, 포스팅 디테일이나, 포스팅 검색 등에 많은 시간을 사용하게 될 것입니다. 지금 당장 포스팅이 30개뿐인 저의 블로그도 디테일 페이지로 이동하는데 6초정도의 시간이 걸리더라구요.. 6초면 사용자에게 정말 좋지 않은 경험이 될 것이라 생각합니다. 프론트엔드 개발자가 사용자에게 좋지 않은 경험을 주는 ui를 개발한다? 이건 좀…
 
그렇게 알아보다 보니 ssr을 통한 동적 경로 설정이 있는것을 알게되었습니다. 우리가 가지고 있는 모든 포스팅의 경로를 미리 알고있다면, 그 경로들을 동적 경로 세팅을 통해 디테일로의 진입 속도를 줄일 수 있습니다. 그럼 이제 어떻게 설정하고, next12에선 어떻게 사용했는지에 대해 알아보도록 하겠습니다.

generateStaticParams 로 동적 경로 설정

Next13 동적 경로 공식문서 를 보면 다음과 같이 나와있습니다.
In the pages directory, the getStaticPaths function is used to define the dynamic paths that should be pre-rendered at build time.
 
위 내용에서 pages는 next13에서 app 디렉토리로, getStaticPaths는 next13에서 generateStaticParams로 변경되었고, 내용을 해석하자면
 
빌드 시 미리 렌더링해야 하는 동적 경로를 정의하는 데 사용됩니다.
 
로 해석할 수 있습니다.
 
이게 무슨말이냐면, 우리가 하나의 포스팅 디테일에 들어가려면 나의 모든 포스팅에서 경로와 일치하는 포스팅을 찾고, 그 포스팅 id를 통해서 notion block을 받아와야 합니다. 하지만 나의 모든 포스팅 경로를 미리 알고있다면 그 경로들을 설정, 빌드 시에 미리 데이터를 불러올 수 있다는 겁니다.
 
그럼 우리가 하나의 포스팅 디테일에 들어가는 6초를 줄일 수 있다는 말이죠! 그럼 이제 여기서 어떻게 설정하는지에 대해 알아보도록 하겠습니다.

generateStaticParams 사용 예시

지금 개발하고있는 notion 블로그를 예시로들 예정입니다.
 
// src/app/page/[slug]/page.tsx export async function generateStaticParams() { const posts = await getPosts(); // 모든 포스팅 불러오기 return posts.map((post) => ({ slug: post.slug, // 모든 포스팅의 경로를 미리 저장하기 })); }
 
위 처럼 우리는 모든 포스팅을 불러오는 api를 미리 만들어두었고, 그로인해 모든 포스팅의 경로를 미리 알 수 있습니다. 그 경로는 slug에 들어있기에, map을 통해 {slug: post/slug} 형식의 배열들을 생성 할 수 있습니다.
 
이러면 빌드 시 해당 slug의 api를 미리 불러와 페이지 로딩 시간을 줄일 수 있게 되는 겁니다. 여기서 옵션을 몇개 추가할 수 있습니다. 예를들어, 우리가 미리 설정한 동적 경로 이외에 경로가 오게된다면 어떻게 처리할 것인가? 에 대한 옵션도 추가할 수 있습니다.
 
export const dynamicParams = true;
 
daynamicParams를 추가하면 우리는 동적 경로 이외에 경로 진입때의 로딩을 제어할 수 있습니다.
  • true : (기본값) generateStaticParams 에 포함되지 않은 동적 세그먼트는 요청 시 생성됩니다.
  • false : generateStaticParams 에 포함되지 않은 동적 세그먼트는 404를 반환합니다.

next12에서 설정한 동적 경로 next13으로 마이그레이션 하기

생각보다 간다하고, 공식문서에도 잘 나와있기에 공식문서 내용을 인용하도록 하겠습니다.
 
// `pages` directory export async function getStaticPaths() { return { paths: [{ params: { id: '1' } }, { params: { id: '2' } }] }; } export async function getStaticProps({ params }) { const res = await fetch(`https://.../posts/${params.id}`); const post = await res.json(); return { props: { post } }; } export default function Post({ post }) { return <PostLayout post={post}> }
 
위 내용은 next12에서 사용하는 동적경로 입니다. 큰 차이점은 getStaticPaths 가 generateStaticParams 로 변경되었고, return 에 paths와 callback으로 구성되어있던 next12와 달리 next13에서는 return에 paths와 callback 없이 반환하게 되어있습니다. 예시는 아래와 같습니다.
 
// `app` directory export async function generateStaticParams() { return [{ id: '1' }, { id: '2' }] } async function getPost(params) { const res = await fetch(`https://.../posts/${params.id}`); const post = await res.json(); return post; } export default async function Post({ params }) { const post = await getPost(params); return <PostLayout post={post}> }
 
그럼 여기서 바뀐 callback은 위에 설명한 daynamicParams을 통해서 설정이 가능해 졌습니다. 생각보다 크게 변한건 없죠?

결과

생각보다 블로그를 만들면서 많은 벽을 느끼고 있습니다.. 지난주에 ddd 아키텍처를 설계하였으나,, api fetch가 매우 오래 걸려서 잠시 멈춰두고 동적 경로 세팅을 먼저 하고있으니..
 
그래도 동적경로 세팅이란걸 통해서 ssr의 렌더 시간을 줄일 수 있어서 매우 뜻깊었던 것 같습니다. 다른 사람들이 나의 블로그에 오는데.. 포스팅당 5~6초씩 걸린다면.. 어우 끔찍하다..
 
쨋든 이번에 완성될 notion 블로그를 위해.. 좀 더 노력해보도록 하겠습니다. 감사합니다.