
데이터 패칭은 모든 어플리케이션에서 핵심 부분이다. 이 페이지는 어떻게 데이터를 패치하고, 캐시하고, 재검증하는지 설명한다.
데이터를 패치하는 네 가지 방법이 있다.
1. 서버에서 fetch 사용
2. 서버에서, 3rd party library 사용
3. 클라이언트에서, Route Handler를 통해
4. 클라이언트에서, thrid-party-library를 사용
nextjs는 기본 fetch Web API를 확장해 서버의 각 fetch 요청에 대한 캐싱및 revalidating 동작을 구성할 수 있게 한다. 리액트는 fetch를 확장해서 리액트 컴포넌트 트리를 렌더링하는 동안 자동적으로 fetch 요청을 메모(memoize)한다.
fetch를 async/await과 함께 서버 컴포넌트, 라우트 핸들러, 서버 액션에서 사용할 수 있다.
예를 들면
async function getData() {
const res = await fetch('https://api.example.com/...')
// 서버에서 데이터를 이렇게 패치 해 올 수 있다.
// The return value is *not* serialized
// You can return Date, Map, Set, etc.
if (!res.ok) {
// This will activate the closest `error.js` Error Boundary
throw new Error('Failed to fetch data')
}
return res.json()
}
//여기까지 getData()함수 만들기 - async/await 함수
export default async function Page() {
const data = await getData()
//await함수 활용
return <main></main>
}
Good to know:
- next.js는 서버 컴포넌트에서 데이터를 패칭할 때 유용한 함수들을 제공합니다. 예를 들면 cookies 함수와 headers 함수가 있습니다. 이들은 요청 시간 정보에 의존하므로 그 route가 동적으로 렌더되도록 합니다.
- Route Handler에서 fetch 요청은 Route Handler가 React component tree의 부분이 아니기 때문에 memoize되지 않습니다.
- async/await을 서버 컴포넌트에서 typescript와 사용하려면, 타입스크립트를 5.1.3버전 이상을 활용해야 하고 @types/react 18.2.8 그 이상으로 사용해야 합니다.
캐싱은 데이터를 저장하여 모든 요청마다 데이터 소스로부터 re-fetch할 필요 없도록 해준다.
기본값으로, next.js는 자동적으로 fetch가 리턴한 값을 서버의 Data Cache에 캐싱한다. (next.js에서는 캐싱을 하는 것이 기본값이라는 말)

이는 build 시간 또는 요청 시간에 그 데이터가 패치될 수 있으며 각 요청마다 캐시되고 재사용될 수 있다는 것을 의미한다.
// 'force-cache' 가 기본값이고, 생략할 수 있다(기본값이니까)
fetch('https://...', { cache: 'force-cache' })
POST method를 사용하는 fetch 요청은 또한 자동적으로 캐시된다. POST method를 사용하는 Route Handler 안에 있는 것이 아니라면, 캐시되지 않는다. (POST method를 사용하는 Route Handler 안에 있어야 캐시된다.)
Revalidation은 Data Cache를 깨끗이 하는 과정이며 최신 데이터를 re-fetching 하는 과정이다. 이는 당신의 데이터가 바뀌고, 바뀐 최신 정보를 볼 때 유용하다.
캐시된 데이터는 두 가지 방법으로 재검증된다.
1. 시간에 기초한 재검증(Time-based revalidation) : 특정 시간이 지나면 자동적으로 데이터를 재검증한다. 이는 데이터 변화가 자주 일어나지 않고 데이터의 freshness가 매우 중요하지 않을 때 유용하다.
2. 요청 재검증 : 어떤 이벤트(예. 폼 제출 등)에 기반하여 직접 데이터를 재검증한다. 요청 재검증은 데이터 그룹을 한 번 재검증 하기 위해 tag-based 또는 path-based 접근을 사용할 수 있다. 이는 최근 데이터가 최대한 빨리 보였으면 좋겠을 때 유용하다.
fetch('https://...', { next: { revalidate: 3600 } })
다른 방법으로, 모든 캐시 요청을 route segment에서 재검증하기위해, 당신은 Segment Config Options를 사용할 수 있다.
export const revalidate = 3600 // revalidate at most every hour
만약 당신이 정적으로 렌더링된 경로에서 여러개의 패치 요청을 가지고 있다면, 그리고 각각은 다른 재검증 빈도(캐시 시간이 다름)를 가졌다면 가장 작은 시간이 모든 요청에 사용될 것이다. 동적으로 렌더링되는 경로라면, 각 fetch 요청은 독립적으로 재검증된다.
Next.js는 경로를 통해 fetch 요청을 무효화하기위한 캐시 태깅 시스템을 가지고 있다.
예를 들면, 다음 fetch 요청은 collection이라는 캐시 태그를 더한다.
export default async function Page() {
const res = await fetch('https://...', { next: { tags: ['collection'] } })
//tags : 'collection'으로 추가한 것
const data = await res.json()
// ...
}
만약 당신이 Route Handler를 사용한다면, 당신의 Next.js 어플리케이션만 아는 secret token을 만들어야 한다. 이 secret은 인증되지 않은 revalidation 시도를 막기 위해 사용된다. 예를 들면, 당신은 그 경로에 다음과 같은 URL 구조로 접근할 수 있다.
https://<your-site.com>/api/revalidate?tag=collection&secret=<token>
//여기 토큰 자리에 시크릿 토큰을 입력하여 사용한다
import { NextRequest, NextResponse } from 'next/server'
import { revalidateTag } from 'next/cache'
// e.g a webhook to `your-website.com/api/revalidate?tag=collection&secret=<token>`
export async function POST(request: NextRequest) {
const secret = request.nextUrl.searchParams.get('secret')
const tag = request.nextUrl.searchParams.get('tag')
if (secret !== process.env.MY_SECRET_TOKEN) {
return NextResponse.json({ message: 'Invalid secret' }, { status: 401 })
}
if (!tag) {
return NextResponse.json({ message: 'Missing tag param' }, { status: 400 })
}
revalidateTag(tag)
return NextResponse.json({ revalidated: true, now: Date.now() })
}
다른 방법으로, 경로와 연관된 모든 데이터를 revalidate하기 위해 revalidatePath를 사용할 수 있다.
import { NextRequest, NextResponse } from 'next/server'
import { revalidatePath } from 'next/cache'
export async function POST(request: NextRequest) {
const path = request.nextUrl.searchParams.get('path')
if (!path) {
return NextResponse.json({ message: 'Missing path param' }, { status: 400 })
}
revalidatePath(path)
return NextResponse.json({ revalidated: true, now: Date.now() })
}
만약 데이터를 revalidate 하려고 하는데 에러가 던져진다면, 가장 마지막으로 성공적으로 만들어진 데이터가 캐시에서 계속 서비스된다. 다음 그 이후의 요청에서 next.js는 데이터 revalidation을 재시도한다.
Opting out of Data Caching부터 다음 게시물 ..
revalidate는 초단위로되면 3600이 1시간인데 , 보통 이렇게 길게 설정하는 편일까요?