Next.js에서는 fetch함수를 자체적으로 확장하여 제공하고 있다. 이 fetch는 Next.js에서 제공하고 있는 렌더링 기법들을 사용하는데에 중요한 역할들을 하고 있다.
export default async function Page() {
let data = await fetch('https://api.vercel.app/blog')
let posts = await data.json()
return (
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
)
}
기본 사용 예시는 일반 fetch함수와 별반 다를게 없다. 똑같이 fetch하고 .json()을 통해 json형식으로 돌려받고 한다. 다른점이 있다면 Next.js에서 캐싱을 이 fetch함수를 통해 조절할 수 있다는 점이다.
이전 포스팅에 Next.js에서 fetch를 통해 렌더링 기법을 다르게 하는 방식을 포스팅 했었는데 이번에는 여러 함수에서 데이터를 재사용하는 부분이나 캐시를 revalidate하는 방식을 써볼까 한다.
Next.js에서는 페이지에서 가져온 데이터를 동일하게 사용해야할 때 generateMetadata 및 generateStaticParams와 같은 API를 사용한다. fetch를 사용할 경우 이 요청은 자동으로 메모이제이션이 되고 다시 한번 이 요청을 실행 할 때 옵션이 동일하다면 캐시된 값을 그대로 사용할 수 있다고한다.
import { notFound } from 'next/navigation'
interface Post {
id: string
title: string
content: string
}
async function getPost(id: string) {
let res = await fetch(`https://api.vercel.app/blog/${id}`)
let post: Post = await res.json()
if (!post) notFound()
return post
}
export async function generateStaticParams() {
let posts = await fetch('https://api.vercel.app/blog').then((res) =>
res.json()
)
return posts.map((post: Post) => ({
id: post.id,
}))
}
export async function generateMetadata({ params }: { params: { id: string } }) {
let post = await getPost(params.id)
return {
title: post.title,
}
}
export default async function Page({ params }: { params: { id: string } }) {
let post = await getPost(params.id)
return (
<article>
<h1>{post.title}</h1>
<p>{post.content}</p>
</article>
)
}
Revalidate는 ISR(Incremental Static Regeneration)을 하겠다는 뜻이다. ISR은 SSG와 똑같이 전체 사이트를 미리 빌드하여 정적 페이지를 제공하는데 revalidate 시간이 지나면 지금 사용하고 있는 캐시 데이터를 사용하지 않고 다음 요청에 대한 데이터를 캐시에 저장하고 사용하게된다.
interface Post {
id: string
title: string
content: string
}
// Next.js will invalidate the cache when a
// request comes in, at most once every 60 seconds.
export const revalidate = 60
// We'll prerender only the params from `generateStaticParams` at build time.
// If a request comes in for a path that hasn't been generated,
// Next.js will server-render the page on-demand.
export const dynamicParams = true // or false, to 404 on unknown paths
export async function generateStaticParams() {
const posts: Post[] = await fetch('https://api.vercel.app/blog').then((res) =>
res.json()
)
return posts.map((post) => ({
id: String(post.id),
}))
}
export default async function Page({ params }: { params: { id: string } }) {
const post = await fetch(`https://api.vercel.app/blog/${params.id}`).then(
(res) => res.json()
)
return (
<main>
<h1>{post.title}</h1>
<p>{post.content}</p>
</main>
)
}
page에서 export const revalidate = 60
을 하였으니 60초에 한번 데이터를 갱신해 줄 것이다.
처음에 과제를 진행할 때 평소처럼 자연스레 axios를 다운 받고 axios를 사용하려 했으나 이런 캐시 기능들 때문에 next.js에서는 굳이 axios를 사용하지 않아도 된다는 점을 알게되어 api호출 부분을 다시 다 갈아엎게 되었다. ㅜ 그래도 오후동안 다 갈아 엎었는데에 성공을 하였고 Next.js의 렌더링 방식에 조금 더 알게 된 느낌이었다. 아이템 만드는 부분만 남았는데 요점을 고려하면서 후딱 해치워버리자.
/** @type {import('next').NextConfig} */
const nextConfig = {
logging: {
fetches: {
fullUrl: true,
},
},
};
export default nextConfig;
nextConfig에 위와 같이 세팅을 하게 되면
요렇게 캐시를 사용을 하고 있는지 안하고있는지 터미널에서 확인할 수 있다고 한다!