넥스트js의 확장된 fetch는 서버 데이터 캐싱과 무효화 전략을 유연하게 구성할 수 있게 되었다.
cache()는 렌더링 중 최적화,unstable_cache()는 서버 캐시 + ISR + 태그 무효화,unstable_noStore()는 최신 데이터 보장을 위한 무조건 재요청용cache()
unstable_cache()
unstable_noStore()
| 항목 | cache() (React) | unstable_cache() (Next.js) | unstable_noStore() (Next.js) |
|---|---|---|---|
| 제공 주체 | React | Next.js | Next.js |
| 캐싱 범위 | 같은 렌더링 중 | 요청 간에도 재사용 (Persistent) | 없음 (항상 새로 요청) |
| 캐시 지속시간 | 1 요청 단위 | 서버 글로벌 캐시 | 없음 |
| 태그 무효화 | 불가능 | 가능 (revalidateTag) | 없음 |
| revalidate 설정 | 없음 | 가능 (revalidate: 60 등) | 없음 |
| SSR/ISR 캐싱 통합 | 없음 | 가능 | 없음 |
| 사용 대상 | 단순 메모이제이션 (e.g. getPost) | 페이지/데이터 fetch, DB | 민감하거나 최신 상태 필요할 때 |
| 클라에서 사용 가능? | 불가능 | 불가능 | 불가능 |
// getPost.ts
import { cache } from 'react';
export const getPost = cache(async (id: string) => {
return await db.post.findUnique({ where: { id } });
});
getPost(id)를 중복 호출해도 1회만 실행됨import { unstable_cache } from 'next/cache';
const fetchPopularPosts = unstable_cache(
async () => await db.post.findMany({ where: { popular: true } }),
['popular-posts'],
{ tags: ['posts'], revalidate: 3600 }
);
/api/revalidate에서 revalidateTag('posts')로 수동 무효화 가능import { unstable_noStore } from 'next/cache';
export async function getUser() {
unstable_noStore(); // 이 함수 내 모든 fetch, DB는 캐싱하지 않음
const supabase = await createClient();
const { data: { user } } = await supabase.auth.getUser();
return user;
}
| 상황 | 추천 함수 | 이유 |
|---|---|---|
| 서버 렌더링 중 같은 데이터 여러 곳에서 쓰임 | cache() | render 단위 중복 방지 |
| 인기글, 페이지 데이터 등 태그 무효화로 관리하고 싶음 | unstable_cache() | 캐시 태그 + ISR까지 가능 |
| 로그인 유저 정보처럼 절대 캐시되면 안 되는 민감한 데이터 | unstable_noStore() | 요청마다 DB를 새로 조회하게 강제 |