티스토리 뷰
Next.js에서 API 요청 결과를 캐싱하는 방법: unstable_cache, revalidate, revalidatePath, revalidateTags (Legacy API)
als982001 2024. 11. 2. 15:081. 개요
캐싱은 성능 최적화와 사용자 경험 개선에 있어 중요하다. 왜냐하면 캐시를 사용하는 것으로 반복적인 요청을 줄이고, 서버의 부하를 낮출 수 있으며 사용자에게 보다 빠르고 일관적인 데이터를 제공할 수 있기 때문이다. 예를 들어 아래와 같이 상품의 상세 정보를 보여주는 페이지가 있다고 하자.
// 상품의 상세 정보를 받아오는 함수
async function getProduct(id: number) {
console.log("getProduct!!!");
const product = await db.product.findUnique({
where: {
id,
},
include: {
user: {
select: {
username: true,
avatar: true,
},
},
},
});
return product;
}
// 메타데이터를 위한 title을 받아오는 함수
const getProductTitle = async (id: number) => {
console.log("getProductTitle!!!");
const product = await db.product.findUnique({
where: {
id,
},
select: { title: true },
});
return product;
};
여기서 상품의 정보를 불러오는 함수와 메타데이터를 위해 정보를 불러오는 함수가 2개가 있다. 이 때, 새로고침을 계속 누르면 상품의 정보가 변한 것이 없더라도 같은 요청을 계속 시도한다.
물론 로컬 개발 환경에서는 크게 문제가 없지만 실제 상황에서는 사용자에게 좋지 않은 경험을 남겨줄 수도 있다. 그렇기에 필요없는 요청을 방지하기 위한 방법 중 캐싱이라는 것이 있는데, 이를 적용해보려 한다.
2. revalidate
우선 Next.js에서 캐싱을 이용하기 위해서는 use cache를 이용할 수 있다. 하지만 이 글은 노마드 코더 강의에서 배운 unstable_cache에 대해 기록하는 글이기에 여기서는 unstable_cache를 이용하려 한다. (unstable_cache는 공식 문서에서 legacy api라고 한다.) unstable_cache는 첫 번째 인자로 api 요청을 하는 함수를, 두 번째 인자로는 해당 함수의 결과를 유니크하게 구별할 수 있는 key값을 담은 배열이 필요하다.
const getCachedProduct = nextCache(getProduct, ["product-detail"]);
const getCachedProductTitle = nextCache(getProductTitle, ["product-title"]);
그리고 세 번째 인자로는 캐싱 옵션을 넣을 수 있다. validate라는 옵션은 데이터를 저장하고 있는 시간, 즉 만료 기간을 초 단위로 설정할 수 있다. 예를 들어, { validate: 30 }으로 설정하면 30초동안 캐싱하고 있는다는 의미이다.
const getCachedProduct = nextCache(getProduct, ["product-detail"], {
revalidate: 10,
});
const getCachedProductTitle = nextCache(getProductTitle, ["product-title"], {
revalidate: 10,
});
validate를 10(10초)으로 설정한 후, 계속 새로고침을 해보았다. 그리고 실제로 10초 후에 새로 고침을 하니 다시 데이터를 받아오는 것을 확인할 수 있었다.
3. revalidatePath
revalidatePath는 특정 path에 연결되어 있는 모든 데이터를 새로고침할 수 있는 방법이다. 이는 버튼 등과 연결해서 직접 실행할 수 있다.
const getCachedProduct = nextCache(getProduct, ["product-detail"], {})
const getCachedProductTitle = nextCache(getProductTitle, ["product-title"]);
... 생략
export default async function ProductDetail({
params,
}: {
params: { id: string };
}) {
... 생략
const revalidate = async () => {
"use server";
revalidatePath("/products/5");
};
return (
<div className="pb-40">
... 생략
<div>
{isOwner ? (
<form action={revalidate}>
<button className="bg-red-500 px-5 py-2.5 rounded-md text-white font-semibold">
Revalidate title cache
</button>
</form>
) : null}
</div>
</div>
);
}
revalidate라는 함수를 생성한 후, revalidatePath에 "/products/5"라는 path를 인자로 주었다. 현재 확인해볼 상품의 id가 5이기에 편의상 하드코딩으로 작성하였다.
새로고침을 계속 해도 api를 요청하는 함수가 실행되지 않다가 ravalidate라는 함수를 동작시키게 하는 버튼을 클릭하였더니 현재 path(/products/5)와 연결되어 있던 두 함수가 다시 실행되는 것을 확인할 수 있었다.
4. revalidateTags
마지막은 revalidateTags로, path 대신 작성한 tags가 설정된 함수들을 다시 받아오게 할 수 있는 방법이다.
const getCachedProduct = nextCache(getProduct, ["product-detail"], {
tags: ["product-detail", "xxx"],
});
const getCachedProductTitle = nextCache(getProductTitle, ["product-title"], {
tags: ["product-title", "xxx"],
});
... 생략
export default async function ProductDetail({
params,
}: {
params: { id: string };
}) {
... 생략
const revalidate = async () => {
"use server";
revalidateTag("product-detail");
};
return (
<div className="pb-40">
... 생략
<div>
{isOwner ? (
<form action={revalidate}>
<button className="bg-red-500 px-5 py-2.5 rounded-md text-white font-semibold">
Revalidate title cache
</button>
</form>
) : null}
</div>
</div>
);
}
getChacedProduct는 tag로 product-detail, xxx를, getCachedProductTitle은 tag로 product-title, xxx를 가지고 있다. 그리고 revalidate라는 함수는 product-detail라는 tag만 다시 불러오게 한다.
버튼을 클릭한 순간, product-detail라는 tag를 가지고 있는 getChacedProduct의 getProductTitle만 다시 실행되는 것을 확인할 수 있다.
5. fetch 함수에서는
const testFunc = async () => {
fetch("https://~~~", {
next: {
revalidate: 60,
tags: ["test-tag"],
},
});
};
위 함수들은 Prisma를 이용한 함수들이었다. 그리고 외부 api를 이용할 경우에는 위 코드처럼 next라는 옵션에서 revalidate, tags 등을 설정할 수 있다.
unstable-cache: https://nextjs.org/docs/app/api-reference/legacy-apis/unstable_cache
Legacy APIs: unstable_cache | Next.js
API Reference for the unstable_cache function.
nextjs.org
use-cache: https://nextjs.org/docs/app/api-reference/directives/use-cache
'기록' 카테고리의 다른 글
Prisma의 Composite Id 간단 기록 (0) | 2024.11.09 |
---|---|
Next.js의 routing 관련: Route Segment Config, generateStaticParams, dynamicParams (0) | 2024.11.03 |
Next.js의 Soft/Hard Refresh, Intercepting Routes, Parallel Routes 간단하게 기록 (0) | 2024.10.27 |
Next.js next/image 컴포넌트의 'Invalid src prop' 에러 (1) | 2024.10.26 |
Next.js의 params, loading (1) | 2024.10.20 |
- Total
- Today
- Yesterday
- 스택
- 자바스크립트
- 비트마스킹
- 완전탐색
- 구현
- 브루트포스
- react
- CSS
- 리액트
- 백준
- 동적계획법
- SQL
- themoviedb
- C++
- 코드스테이츠
- 프로그래머스
- 넥스트js
- BFS
- Next.js
- 다이나믹프로그래밍
- 알고리즘
- 햄버거버튼
- Redux
- 순열
- async
- 타입스크립트
- typescript
- NextJS
- aws
- 카카오맵
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |