• Next

[Next.js] getStaticPaths (Static Generation/fallback/동적 라우팅)

man_on 2023. 1. 17. 01:38
반응형

 

1. getStaticPath 예시
2. fallback

 


 

동적 라우팅 페이지에서의 pre-rendering

 

Next의 pages폴더에서 [대괄호]로 파일명을 생성하면 동적 라우팅을 할 수 있다.

이 때 주의해야 할 점은 Next는 모든 페이지를 사전생성 하지만, 동적 페이지에서는 그렇지 않다는 점이다.

동적 페이지에서 getStaticProps를 사용하여서 페이지에 진입하게 되면 아래와 같은 에러를 만나게 된다.

 

 

대괄호 [ ]로 만든 동적 페이지는 엄밀하게 따져서 하나의 페이지가 아닌 여러 페이지이다.

때문에 Next는 사전에 동적 페이지를 위해서 얼마나 많은 페이지를 미리 생성해야할지 알 수 없다.

이럴 때 비동기 함수 getStaticPaths를 이용하여 Next에게 어떤값에 대한 페이지가 pre-rendering되어야 할 지 지정해준다.

정확히 말해 동적 페이지의 어떤 구체적인 인스턴스를 사전에 생성할지 알려주는 것이다.

Multiple concrete [id] page instances (ex. id=1, id=2 etc) are pre-generated.

 

 

 

 

 


 

 

 

 

getStaticPath 예시

 

 

 

예를들어 getStaticProps에 아래의 코드대로 /p1 /p2 /3의 동적인 페이지를 만든다고 한다면,

// dummy.json
{
  "products": [
    { "id": "p1", "title": "Product 1", "description": "This is product 1" },
    { "id": "p2", "title": "Product 2", "description": "This is product 2" },
    { "id": "p3", "title": "Product 3", "description": "This is product 3" }
  ]
}
export async function getStaticProps(context) {
  const { params } = context;
  const productId = params.pid;

  const filePath = path.join(process.cwd(), 'data', 'dummy.json');
  const jsonData = await fs.readFile(filePath);
  const data = JSON.parse(jsonData);

  const product = data.products.find((product) => product.id === productId);
  return {
    props: {
      product: product,
    },
  };
}

const ProductdatailPage = ({ product }) => {
  return (
    <>
      <h1>{product.title}</h1>
      <p>{product.description}</p>
    </>
  );
};

export default ProductdatailPage;

 

 

 

해당 경로를 반환하는 paths 객체를 getStaticPaths로 지정해준다.

export async function getStaticPaths() {
  // paths가 있는 객체를 반환
  return {
    paths: [
      { params: { pid: 'p1' } },
      { params: { pid: 'p2' } },
      { params: { pid: 'p3' } },
    ],
    fallback: false,
  };
}

 

 

설정 후 다시 앱을  build해보면 getStaticPaths로 지정한 p1/p2/p3 페이지가 pre-rendering 된 것을 확인할 수 있고,

.next/server/pages폴더에도 p1~p3.html 파일이 생성된 것을 확인할 수 있다.

 

 

 

 

 

paths의 id값을 하드 코딩한 부분을 수정

 

 

 

 

 

* context 매개변수
   - params : 경로상의 동적 세그먼트에 대한 구체적인 값을 알 수 있다. {key : 값}
// pages/posts/[slug].js

export function getStaticProps(context) {
  const { params } = context;
  const { pid } = params;
  console.log('🚀 ~ file: [slug].js:21 ~ getStaticProps ~ params', params);

  ...
}

{ key : 값 } 형태로 출력

 

 

 

 

 

 

 

 

fallback

 

fallback: false

  • getStaticPaths에서 리턴하지 않는 페이지는 모두 404로 연결
  • page의 data가 자주 추가되지 않거나, 새로 생성되는 페이지의 수가 적을 때 사용한다.

 

 

fallback: true

  •   데이터에 의존하는 정적 페이지가 많아서 모든 페이지를 pre-rendering 하는것이 무리이고 불필요하다고 생각될 때,
      = 일부 페이지만 pre-rendering 하고 싶을 때 true설정한다.
  •   지정하지 않은 나머지 페이지는 pre-rendering되지 않고 request가 서버에 도달하는 순간 생성된다.
  •   빌드 시간과 사용자들의 응답 속도를 단축할 수 있다

 

fallback: true is useful if your app has a very large number of static pages that depend on data (such as a very large e-commerce site). If you want to pre-render all product pages, the builds would take a very long time.

 

 

* 주의해야 할 점은 pre-rendering하지 않은 나머지 path들이 로딩되는 순간(=props로 아직 아무값도 view로 넘어오지 않은 단계)을

고려해야한다. router.isFallback이 true일 때 혹은 props이 아직 넘어오지 않아서 false일 때로 조건을 준다.

export async function getStaticPaths() {
  return {
    paths: [{ params: { pid: 'p1' } }],
    fallback: true,
  };
}
import { useRouter } from 'next/router';
const ProductdatailPage = ({ product }) => {
  const router = useRouter();
  //isFallback 상태일 때
  if (router.isFallback) {
    return <p>Loading...<p>;
  }
  
  return (
    <>
      <h1>{product.title}</h1>
      <p>{product.description}</p>
    </>
  );
};

export default ProductdatailPage;
const ProductdatailPage = ({ product }) => {
  //props이 아직 들어오지 않음
  if (!product) {
    return <p>Loading...<p>;
  }
  ...

paths로 지정한 p1을 제외한 p2-p3의 html파일은 사라진 것을 확인할 수 있다.

 

 

 

 

 

fallback : 'blocking'

  • 최초 만들어놓지않은 path에 대한 요청이 들어온 경우 fallback 상태를 보여주지 않고 SSR로 동작 (서버에서 완전히 pre-rendering된 후 html이 생성되면) 한다.
  • SSR로 동작하기 때문에 loading/fallback 상태가 필요없다.
  • 한 번 방문한 경로는 pre-rendered pages 목록에 추가되어, 최초 build타임에 pre-rendering 되어진 경로와 동일하게 동작한다.
  • next export 사용 시 'blocking'은 지원되지 않는다.

 

 

 

 

 

* fallback : true 일 때, 사전에 정의되지 않은 경로로 진입 시  에러가 발생할 수 있으므로

   지정된 경로가 아닐 시 notFound : true로 404 페이지로 이동하도록 한다.

 

 

 
반응형