개발/Next.js

[Docs]동적 라우트 - getStaticProps 구현 & 세부사항

yoosmg 2023. 5. 10. 16:09

우선 lib/posts.js 하단에 getPostData 함수를 추가한다. 이 함수는 id를 기준으로 게시물 데이터를 반환할 것이다.

export function getPostData(id) {
  const fullPath = path.join(postsDirectory, `${id}.md`);
  const fileContents = fs.readFileSync(fullPath, 'utf8');

  // Use gray-matter to parse the post metadata section
  const matterResult = matter(fileContents);

  // Combine the data with the id
  return {
    id,
    ...matterResult.data,
  };
}

 

pages/posts/[id].js를 열고 아래와 같이 코드를 업데이트한다.

getStaticProps 함수 내부에서 getPostData를 사용해 데이터를 가져오고 postData에 할당한다.

그리고 그것을 props로 반환한다.

import { getAllPostIds, getPostData } from '../../lib/posts';

export async function getStaticProps({ params }) {
  const postData = getPostData(params.id);
  return {
    props: {
      postData,
    },
  };
}

 

Post 컴포넌트도 아래와 같이 업데이트해준다.

export default function Post({ postData }) {
  return (
    <Layout>
      {postData.title}
      <br />
      {postData.id}
      <br />
      {postData.date}
    </Layout>
  );
}

 

아래 url에 접속하면 각 페이지의 블로그 데이터를 확인할 수 있다.


http://localhost:3000/posts/ssg-ss

http://localhost:3000/posts/pre-rendering

 

과정을 그림으로 정리하면 다음과 같다.

 

 

 

동적 라우트 세부사항

다음은 동적 라우트에 대해 알아야 할 몇 가지 필수 정보이다.

 

Fetch External API or Query Database

getStaticProps와 마찬가지로 getStaticPaths도 어떤 데이터 소스에서든 데이터를 페치 할 수 있다.

우리 예제에서 getStaticPaths에서 사용되는 getAllPostIds는 외부 API 엔드포인트에서 페치할 수도 있다.

export async function getAllPostIds() {
  // Instead of the file system,
  // fetch post data from an external API endpoint
  const res = await fetch('..');
  const posts = await res.json();
  return posts.map((post) => {
    return {
      params: {
        id: post.id,
      },
    };
  });
}

 

 

Development vs. Production

개발 모드에서는 모든 요청에 대해 getStaticPaths가 실행되고, 프로덕션에서는 빌드 시점에 getStaticPaths가 실행된다.

 

Fallback

getStaticPaths에서fallback: false로 반환했던걸 떠올려보자. 이게 무엇을 의미할까?

fallback이 false면 getStaticPaths에서 반환되지 않은 모든 경로는 404 페이지가 된다.

fallback이 true면 getStaticProps의 동작이 변경된다:

  • getStaticPaths에서 반환된 경로는 빌드 시 HTML로 렌더링 된다.
  • 빌드 시점에 생성되지 않은 경로는 404 페이지가 생성되지 않는다. 대신 Next.js는 해당 경로에 대한 첫 번째 요청 시 페이지의 "fallback" 버전을 제공한다.
  • 백그라운드에서 Next.js는 요청된 경로를 정적으로 생성한다. 동일한 경로에 대한 후속 요청은 빌드 시점에 프리 렌더링된 다른 페이지와 마찬가지로 생성된 페이지를 제공한다.

fallback이 blocking이면, 새 경로는 getStaticProps를 사용하여 서버 사이드에서 렌더링 되고 향후 요청을 위해 캐시 되므로 경로당 한 번만 발생한다.

 

 

Catch-all Routes

동적 라우트는 괄호 안에 점(...) 세 개를 추가하여 모든 경로를 포착하도록 확장할 수 있다.

예를 들면 pages/posts/[...id].js는 /posts/a뿐만 아니라 /posts/a/b, /posts/a/b/c 등 과 매치된다.
이렇게 할 경우 getStaticPaths에서 다음과 같이 id 키의 값으로 배열을 반환해야 한다.

return [
  {
    params: {
      // Statically Generates /posts/a/b/c
      id: ['a', 'b', 'c'],
    },
  },
  //...
];

 

그리고 params.id는 getStaticProps의 배열이 된다.

export async function getStaticProps({ params }) {
  // params.id will be like ['a', 'b', 'c']
}

 

 

Router

Next.js 라우터에 액세스 하려면, next/router에서 useRouter 훅을 임포트 하여 액세스 할 수 있다.

 

 

404 Pages

사용자 정의 404 페이지를 만들려면 pages/404.js를 생성한다. 이 파일은 빌드 시점에 정적으로 생성된다.

// pages/404.js
export default function Custom404() {
  return <h1>404 - Page Not Found</h1>;
}

자세한 내용은 오류 페이지 문서를 참조.