๐Ÿค ์€์ง€log ๐Ÿค

[NEXTJS ] getStaticProps( ) ์™€ getStaticPaths( ) ๋ณธ๋ฌธ

๐ŸŒท Next JS

[NEXTJS ] getStaticProps( ) ์™€ getStaticPaths( )

Eun_zii 2023. 2. 24. 16:45

 

Next.js์˜ getStaticProps์™€ getStaticPaths api๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด static ํŽ˜์ด์ง€๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

  • getStaticProps: ๋นŒ๋“œ ์‹œ ๋ฐ์ดํ„ฐ๋ฅผ fetchํ•˜์—ฌ static ํŽ˜์ด์ง€๋ฅผ ์ƒ์„ฑ
  • getStaticPaths: pages/**/[id].tsx ํ˜•ํƒœ์˜ ๋™์  ๋ผ์šฐํŒ… ํŽ˜์ด์ง€ ์ค‘, ๋นŒ๋“œ ์‹œ์— staticํ•˜๊ฒŒ ์ƒ์„ฑํ•  ํŽ˜์ด์ง€๋ฅผ ์ •ํ•จ

 

๐Ÿ”† getStaticProps

<Page>.tsx์—์„œ export async function getStaticProps(context) ํ˜•ํƒœ๋กœ ์‚ฌ์šฉ.

context.params๋กœ ๋™์  ๋ผ์šฐํŒ…์˜ ๊ฒฝ๋กœ ์ด๋ฆ„์„ ๊ฐ€์ ธ์˜จ๋‹ค.

 

pages/posts/[id].tsx ํŽ˜์ด์ง€๋ฅผ /posts/123์œผ๋กœ ์ ‘๊ทผํ–ˆ๋‹ค๋ฉด context.params๋Š” { id: "123" }์ด ๋œ๋‹ค.

 

{ props: object }๋ฅผ ๋ฆฌํ„ดํ•˜๋ฉด, export defaultํ•œ ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ์˜ parameter๋กœ ๋„˜๊ฒจ์ง„๋‹ค.

 

import type { GetStaticProps, InferGetStaticPropsType } from "next";
// GetStaticProps๋Š” getStaticProps์˜ ํƒ€์ž…
// InferGetStaticPropsType์€ ์ปดํฌ๋„ŒํŠธ์— ์‚ฌ์šฉ๋˜๋Š” ์ œ๋„ค๋ฆญ ํƒ€์ž…

type Post = {
  title: string;
}

export const getStaticProps: GetStaticProps = async (context) => {
  // async์—ฌ์•ผ ํ•จ

  const response = await fetch("https://example.com");
  const post: Post = await response.json();
  // Next.js๊ฐ€ ํด๋ฆฌํ•„ํ•˜๋Š” Fetch API
  // https://nextjs.org/docs/basic-features/supported-browsers-features#polyfills

  return {
    props: {
      post
    }
    // props๋Š” ํ˜„์žฌ ํŽ˜์ด์ง€์˜ default export ์ปดํฌ๋„ŒํŠธ์˜ parameter๋กœ ๋„˜๊ฒจ์ง
  }
}

const function Blog = ({ post }: InferGetStaticPropsType<typeof getStaticProps>) => {
  // { post: Post }๋กœ ํƒ€์ž… ์ง€์ •๋จ
  return (
    <div>{post.title}</div>
  )
}

export default Blog;

 

getStaticProps๊ฐ€ ํ•„์š”ํ•  ๋•Œ

When should I use getstaticprops?

  • ํŽ˜์ด์ง€์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๊ฐ€ ๋นŒ๋“œ ์‹œ์— ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•  ๋•Œ
  • ๋ฐ์ดํ„ฐ๋ฅผ headless CMS์—์„œ ๊ฐ€์ ธ์˜ฌ ๋•Œ
  • ๋ชจ๋“  ์‚ฌ์šฉ์ž์—๊ฒŒ ๊ฐ™์€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด์—ฌ์ค„ ๋•Œ
  • SEO๋ฅผ ์œ„ํ•ด์„œ ์†๋„ ๋น ๋ฅธ ํŽ˜์ด์ง€๊ฐ€ ํ•„์š”ํ•  ๋•Œ
  • ๊ณต์‹ ๋ฌธ์„œ์—๋Š” ์—†์ง€๋งŒ Node api(path, fs ๋“ฑ)์„ ์‚ฌ์šฉํ•ด์•ผ ํ•  ๋•Œ
import path from "path";

export const getStaticProps = () => {
  const postDirectory = path.resolve(process.cwd(), '/posts');
  // process.cwd()๋Š” Next.js ํด๋”๋ฅผ ๊ฐ€๋ฆฌํ‚ด(package.json์ด ์žˆ๋Š” ํด๋”)
  // ... 
}

 

๐Ÿ”† getStaticPaths

๋™์  ๋ผ์šฐํŒ…์„ ์‚ฌ์šฉํ•  ๋•Œ, ์–ด๋–ค ํŽ˜์ด์ง€๋ฅผ ๋ฏธ๋ฆฌ Static์œผ๋กœ ๋นŒ๋“œํ•  ์ง€ ์ •ํ•˜๋Š” api

 

import type { GetStaticPaths } from "next";
// GetStaticPaths๋Š” getStaticPaths์˜ ํƒ€์ž…

export const getStaticPaths: GetStaticPaths = async () => {
  // getStaticProps์ฒ˜๋Ÿผ async
  
  // ...

  return {
    paths: [
      { params: {} }
    ],
    // { parmas: {} }[] ํ˜•ํƒœ๋กœ paths ๋ฆฌํ„ดํ•ด์•ผ ํ•จ
    // ๋นŒ๋“œ ์‹œ์— ํ•ด๋‹น ํŽ˜์ด์ง€๋“ค์„ static์œผ๋กœ ์ƒ์„ฑ
    fallback: true | false | 'blocking'
    // fallback์„ ๋ฆฌํ„ดํ•ด์•ผ ํ•จ
  }

  // ์˜ˆ์‹œ
  return {
    paths: [
      { params: { id: "1" }},
      { params: { id: "2" }}
    ]
    // pages/posts/[id].tsx๋ผ๊ณ  ๊ฐ€์ •
    // pages/posts/1๊ณผ pages/posts/2๋ฅผ static์œผ๋กœ ์ƒ์„ฑ
  }

  // ์˜ˆ์‹œ 2
  return {
    paths: [
      {
        params: {
          id: "1",
          title: "first post"
        }
      },
      {
        params: {
          id: "2",
          title: "second post"
        }
      }
    ]
    // pages/posts/[id]/[title].tsx๋ผ๊ณ  ๊ฐ€์ •
    // pages/posts/1/first post์™€ pages/posts/2/second post/๋ฅผ static์œผ๋กœ ์ƒ์„ฑ
  }
}

 

๐Ÿ”† fallback (required)์˜ ๋ฆฌํ„ด ๊ฐ’์— ๋”ฐ๋ฅธ ์ฐจ์ด

 

fallback: false

: getStaticPaths์—์„œ ๋ฆฌํ„ดํ•˜์ง€ ์•Š์€ ํŽ˜์ด์ง€๋Š” ๋ชจ๋‘ 404๋กœ ์—ฐ๊ฒฐ

 

fallback: true

: getStaticPaths์—์„œ ๋ฆฌํ„ดํ•˜์ง€ ์•Š์€ ํŽ˜์ด์ง€์— ์ ‘์† ์‹œ,

  1. ๋จผ์ € ์‚ฌ์šฉ์ž์—๊ฒŒ fallback ํŽ˜์ด์ง€๋ฅผ ๋ณด์—ฌ์คŒ
  2. ์„œ๋ฒ„์—์„œ staticํ•˜๊ฒŒ ํŽ˜์ด์ง€๋ฅผ ์ƒ์„ฑํ•จ
  3. ํ•ด๋‹น ํŽ˜์ด์ง€๋ฅผ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์คŒ
  4. ๋‹ค์Œ๋ถ€ํ„ฐ ํ•ด๋‹น ํŽ˜์ด์ง€๋กœ ์ ‘์†ํ•˜๋Š” ์‚ฌ์šฉ์ž์—๊ฒŒ๋Š” staticํ•œ ํŽ˜์ด์ง€๋ฅผ ๋ณด์—ฌ์คŒ
// pages/posts/[id].tsx
import { useRouter } from "next/router";
// fallback ํŽ˜์ด์ง€๋ฅผ ์œ„ํ•œ useRouter import

const Post = ({ post }) => {
  cont router = useRouter();

  if (router.isFallback) {
    return <div>Loading...</div>
  }
  // fallback = true ์‹œ, ์ ‘์†ํ•œ ํŽ˜์ด์ง€๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ๋ณด์—ฌ์ฃผ๋Š” ํŽ˜์ด์ง€

  return (
    <div>{post.title}</div>
  )
}

export default Post;

export const getStaticPaths = async () => {
  return {
    paths: [
      { params: { id: 1} }
    ],
    fallback: true
  }
}

export const getStaticProps = async ({ params }) => {
  const response = await fetch(`https://example.com/${params.id}`);
  const post = response.json();

  return {
    props: { post }
  }
}

 

๋งŽ์€ static ํŽ˜์ด์ง€๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•˜์ง€๋งŒ ๋นŒ๋“œ ์‹œ๊ฐ„์ด ๋„ˆ๋ฌด ์˜ค๋ž˜ ๊ฑธ๋ฆด ๋•Œ ์‚ฌ์šฉ

->  fallback: "blocking"

 

getStaticPaths์—์„œ ๋ฆฌํ„ดํ•˜์ง€ ์•Š์€ ํŽ˜์ด์ง€์— ์ ‘์† ์‹œ,

  1. ์‚ฌ์šฉ์ž์—๊ฒŒ server side renderingํ•œ static ํŽ˜์ด์ง€๋ฅผ ๋ณด์—ฌ์คŒ
  2. ๋‹ค์Œ๋ถ€ํ„ฐ ํ•ด๋‹น ํŽ˜์ด์ง€๋กœ ์ ‘์†ํ•˜๋Š” ์‚ฌ์šฉ์ž์—๊ฒŒ๋Š” server side renderingํ•œ static ํŽ˜์ด์ง€๋ฅผ ๋ณด์—ฌ์คŒ

์ฆ‰, fallback ํŽ˜์ด์ง€๋‚˜ ๋กœ๋”ฉ ํ™”๋ฉด์ด ์—†๋‹ค.

๋™์  ๋ผ์šฐํŒ… ํŽ˜์ด์ง€๋ฅผ static ํŽ˜์ด์ง€๋กœ ์ œ๊ณตํ•ด์•ผ ํ•  ๋•Œ ์‚ฌ์šฉ

 

 

728x90