My Boundary As Much As I Experienced

Next.js의 getStaticPaths 정리 본문

FrontEnd/Next.js

Next.js의 getStaticPaths 정리

Bumang 2024. 4. 29. 01:04

 

getStaticPaths가 해결하려는 문제: SSG 빌드 시 동적 페이지의 구성을 파악할 수 없다.

SSG에서는 빌드 시 사전에 페이지들을 미리 생성하게 된다.

그런데 SSG 방식으로 사이트에서 동적 페이지를 만들 때, Next.js는 [id].js에 속하는 동적 페이지가 뭔지 다 알지 못한다.

그래서 SSG + 동적 라우팅을 쓰면서 getStaticPaths를 쓰지 않으면 아래와 같은 에러를 볼 수 있는 것이다. 뭔지 모른다는 말!

 

 

그렇기 때문에 발생할 수 있는 모든 패러미터들을 정리해서 Next.js에 제공하는 것이 getStaticPaths의 역할이다.

Got it? 사실 이게 다다. 나도 처음 들을 때 여기까지는 이해가 얼추 되긴 했지만, 개인적으로 든 의문점이 하나 있긴 했었다.

 

Next.js 팀은 왜 getStaticProps와 getStaticPaths를 따로 만들었을까? (getStaticProps안에서 paths를 패러미터로 받아오는 방식이 더 낫지 않나..)

라는 의문이 한 번 나서 찾아보았다.

  1. 분리된 책임: getStaticPaths와 getStaticProps는 서로 다른 역할을 한다. getStaticPaths는 동적 라우트를 가진 페이지에 대해 어떤 정적 HTML 파일이 생성될지 결정하는 반면, getStaticProps는 주어진 경로에 필요한 데이터를 불러와 해당 페이지의 props를 준비합니다. 이 분리는 함수의 책임을 명확하게 구분하여 개발자가 각 함수의 역할을 쉽게 이해하고 사용할 수 있게 도와준다.
  2. 빌드 최적화: 빌드 시 getStaticPaths를 사용하여 어떤 페이지들이 생성될지 먼저 결정함으로써, Next.js는 효율적으로 빌드 프로세스를 관리할 수 있다. 빌드 시 필요한 페이지만큼만 getStaticProps를 호출하므로, 불필요한 데이터 페칭이나 처리를 방지할 수 있다.
  3. 증분적 정적 재생성 (ISR): getStaticPaths에서 fallback 설정을 통해 ISR을 활용할 수 있다. 이는 모든 경로를 미리 생성하지 않고도 필요할 때마다 새로운 페이지를 생성할 수 있게 한다. 예를 들어, fallback이 true 또는 'blocking'인 경우, 요청된 경로가 미리 생성된 목록에 없으면, 서버가 그 자리에서 페이지를 렌더링하고 결과를 캐싱한다.

즉, 특정 페이지의 getStaticProps는 특정 routes에 대한 props를 생성하는 것이지 한꺼번에 모든 페이지의 routes를 찾는 것이 아니다. getStaticPaths가 먼저 실행되어 가능한 모든 동적 라우트를 찾아내면, 각각에 대한 getStaticProps가 실행되는 것이라 이해했다. (아니라면 댓글 피드백 환영.)

 

각설하고 사용법

1. paths라는 이름의 객체에 담겨야 한다.

2. 각 Paths의 인자는 { params: { [id]: ... } } 같은 형태에 담겨야 한다. ([id]는 해당 동적페이지의 id값이다.)

// pages/posts/[id].js

import { fetchPostIds, fetchPostData } from '../../lib/posts';

export async function getStaticPaths() {
  // 모든 포스트 ID를 가져오는 API 호출
  const ids = await fetchPostIds(); // 예를 들어, [1, 2, 3, 4, 5]
  
  // `paths` 객체를 생성하여 각 ID에 대한 경로 정보를 제공
  const paths = ids.map(id => ({
    params: { id: id.toString() }
  }));

  return {
    paths,
    fallback: false // fallback이 false이면 정의되지 않은 경로에 대해 404 페이지를 보여줍니다.
  };
}

 

이렇게 { paths: ... , fallback: ... }의 객체를 리턴하면, Next.js가 어떤 동적 라우트들이 있는지 잘 알아먹는다.

그리고 이 예시에선 api로 동적 페이지들의 패러미터 값들을 모두 불러왔다.

그런데 api설정을 하지않고도 동적 페이지의 id값을 fs를 이용해서 긁어오든, 다른 로직으로 어떻게 추출하든 상관없다.

제대로 된 동적 페이지의 목록만 불러온다면 장땡이다. 그러면 Next.js가 빌드 시에 참고해서 사전 생성을 잘 하게 된다! 끝!

 

fallback이 뭔가요?

동적 라우팅에 없는 페이지에 사용자가 접근했을 때(404) 사용자에게 404페이지를 보여줄건지, 또 다른 일반적인 대체 페이지를 보여줄건지 등등의 설정을 할 수 있는 옵션이다.

  1. false
    • 이 설정을 사용하면, getStaticPaths에서 반환된 paths 배열에 포함되지 않은 모든 경로에 대해 사용자는 404 페이지를 보게 된다. 즉, 빌드 시 생성되지 않은 경로는 접근할 수 없다.
    • 사용 예시: 고정된 수의 페이지가 있고, 빌드 시 모든 가능한 경로가 미리 생성될 수 있는 경우에 적합.
  2. true
    • true로 설정되면, getStaticPaths에서 반환되지 않은 경로에 대한 요청이 들어오면 사용자에게는 빈 페이지가 보여지거나 로더가 표시될 수 있다. 이후 Next.js는 백그라운드에서 해당 페이지를 위한 HTML을 정적으로 생성하고, 생성이 완료되면 완성된 페이지로 전환한다.
    • 이 페이지는 이후 요청에서는 정적으로 생성된 페이지처럼 즉시 제공된다.
    • 사용 예시: 대부분의 페이지를 미리 생성하지만, 일부는 요청에 따라 생성하고 싶을 때 유용.
  3. 'blocking'
    • 이 옵션을 사용하면, getStaticPaths에서 반환되지 않은 경로에 대한 요청이 들어왔을 때, 사용자는 생성 과정을 기다리는 동안 빈 페이지를 보지 않고, 서버에서 페이지를 생성할 때까지 기다린다. 페이지 생성이 완료되면 완성된 페이지가 사용자에게 제공된다.
    • 'blocking'은 새 페이지가 서버에서 생성되는 동안 사용자가 로딩 상태 없이 바로 최종적인 페이지를 볼 수 있도록 한다.
    • 사용 예시: 사용자에게 중간 상태를 보여주지 않고, 처음부터 완성된 페이지를 보여주고 싶을 때 적합.