ㅇㅇㅈ Blog

프론트엔드 수행중

0%

nextjs-getStaticPaths

getStaticProps와 getStaticPaths

Nextjs 수련중.. 맞이한 에러

일단 코드를 보자

index.tsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// index.tsx
import path from 'path'
import fs from 'fs/promises'
import { GetStaticProps } from 'next'
import Link from 'next/link'

export type Products = { id: string; title: string; description: string }
export interface HomePageProps {
products: Products[]
}
function HomePage({ products }: HomePageProps) {
return (
<ul>
{products.map((item) => (
<li key={item.id}>
<Link href={`/${item.id}`}>{item.title}</Link>
</li>
))}
</ul>
)
}

export default HomePage

export const getStaticProps: GetStaticProps = async (contex) => {
const filePath = path.join(process.cwd(), 'data', 'dummy-backend.json')
const res = await fs.readFile(filePath, 'utf-8')
const data: HomePageProps = JSON.parse(res)

// redirect
if (!data) {
return {
redirect: {
destination: '/no-data',
permanent: false,
},
}
}

// notFound 페이지 출력
if (data.products.length === 0) {
return { notFound: true }
}
return {
props: {
products: data.products,
},
revalidate: 10,
}
}

[pid].tsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import path from 'path'
import fs from 'fs/promises'
import { GetStaticPaths, GetStaticProps } from 'next'
import React from 'react'
import { HomePageProps, Products } from '.'

interface ProductDetailPageProps {
loadedProduct: Products | null
}

const ProductDetailPage = ({ loadedProduct }: ProductDetailPageProps) => {
return (
<>
<h1>{loadedProduct?.title}</h1>
<p>{loadedProduct?.description}</p>
</>
)
}

export default ProductDetailPage

const getFile = async () => {
const filePath = path.join(process.cwd(), 'data', 'dummy-backend.json')
const res = await fs.readFile(filePath, 'utf-8')
const response: HomePageProps = JSON.parse(res)
return response
}

export const getStaticProps: GetStaticProps = async (context) => {
const { params } = context
const productId = params && params.pid
const data = await getFile()
const product = data.products.find((product) => product.id === productId)

return {
props: {
loadedProduct: product || null,
},
}
}

대충 에러메세지를 읽어보면 동적 SSG페이지에는 getStaticPaths가 필요하단다.

NextJs에서는 기본적으로 모든 페이지를 사전 생성한다. 하지만 동적 페이지([id].tsx처럼 생긴 페이지)에서는 그렇지가 않다.
해당 페이지로 연결되는 동적 세그먼트가 있는 경우 페이지를 사전 생성하지 않는다.
-> 이 페이지는 입력된 주소값에 따라 다른 페이지에 프레임 및 HTML컨텐츠는 같지만 데이터가 다르기 때문에 서버에서 그때그때 생성한다.
[pid].tsx에서 getStaticProps를 사용했기 때문에 NextJs에 사전에 페이지를 렌더링하도록 요청하는것과 같지만 동적페이지이기 때문에 오류가 나는 것.
그렇기에 Next에게 어떤 값에 대한 페이지가 사전 생성되어야 하는지 알아야 그 페이지의 인스턴스를 사전 생성 할 수 있다.

getStaticPaths

GPT에게 물어본 getStaticPaths


getStaticPaths 함수는 빌드 시점에 실행되며, 사전 정의된 동적 경로를 반환해야 합니다. 이 반환된 경로는 Next.js가 빌드 시에 어떤 동적 페이지를 사전 렌더링할 지를 결정하는 데 사용됩니다.
getStaticPaths 함수는 다음과 같은 역할을 수행합니다

  1. 동적 경로의 매개변수에 대한 가능한 값 목록을 반환합니다. 이는 사전 렌더링할 동적 페이지의 경로를 결정하는 데 사용됩니다.
  2. 반환된 경로에 대해 정적 페이지를 사전 렌더링합니다. 각 경로에 대해 해당하는 동적 페이지를 사전에 생성하여 정적 HTML 파일로 빌드합니다.
  3. 정적 페이지가 생성되고 빌드된 후에는 해당 경로로의 요청이 정적 파일로 서비스되므로 서버 측에서 처리할 필요가 없습니다.

getStaticPaths 함수는 반드시 fallback 속성을 포함하는 객체를 반환해야 합니다. fallback 속성은 동적 경로의 누락된 경우 어떻게 처리할지를 설정합니다. 다음 세 가지 옵션 중 하나를 가질 수 있습니다:

  • fallback: false: 사전 정의된 동적 경로 외에는 접근할 수 없으며, 누락된 경로로의 요청은 404 페이지로 이동합니다.
  • fallback: true: 사전 정의된 동적 경로 이외의 요청은 서버 측에서 동적으로 처리됩니다. 이 경우, Next.js는 해당 동적 페이지를 생성하지 않은 상태에서 요청에 맞는 새로운 정적 페이지를 생성하고 반환합니다. 이후 요청에서는 사전 렌더링된 정적 페이지로 제공됩니다.
  • fallback: ‘blocking’: 사전 정의된 동적 경로 이외의 요청은 서버 측에서 동적으로 처리됩니다. 이 경우, Next.js는 해당 동적 페이지를 생성하지 않은 상태에서 요청에 맞는 새로운 정적 페이지를 생성하고 반환합니다. 이후 요청에서는 사전 렌더링된 정적 페이지로 제공됩니다. 다른 페이지의 생성이 완료될 때까지 요청은 차단됩니다.

getStaticPaths 함수는 주로 동적 경로를 가지는 페이지에 대한 사전 렌더링을 구현할 때 사용됩니다. 이를 통해 SEO 최적화, 성능 개선, 초기 로딩 속도 향상 등의 이점을 얻을 수 있습니다.


[pid].tsx에 getStaticPaths를 추가해준다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* @return 객체를 return한다
* paths는 객체로 이루어진 배열이며 params를 추가해야한다.
* params는 키-값으로 되어있는 다른 객체가 될 수 있다.
*/
export const getStaticPaths: GetStaticPaths = async () => {
const data = await getFile()
const paths = data.products.map((product) => ({ params: { pid: product.id } }))


return {
paths,
fallback: false,
}
}