Next.js 교재 · 17편 · 캐싱

Next.js 캐싱 완전 정리 — 4층 캐시

같은 데이터가 4번 캐시될 수 있다. 4층의 위치와 폐기 방법.

Next.js 4층 캐시 흐름 컨셉 일러스트

Next.js 가 가장 헷갈리는 이유 중 하나 — 같은 데이터가 동시에 4곳에 캐시된다. 무효화하면 한 곳만 비는데 다른 곳에 옛 데이터가 남아 화면이 안 바뀐다. "분명 fetch 했는데 옛 값이 와요" 의 정체.

16편에서 ISR·SSG·SSR 모드 차이를 봤다면, 이번은 그 뒤에서 도는 실제 캐시 4층을 본다. 한 번 외워두면 디버깅이 한결 빨라진다.

1. 4층 캐시 한눈에

위치수명목적
Request Memoization서버 · 한 요청 내요청 끝나면 폐기같은 요청에서 fetch 중복 제거
Data Cache서버 · 영구 (지정 시간)revalidate 또는 폐기 호출fetch 결과 재사용
Full Route Cache서버 · 영구revalidate 또는 재배포SSG·ISR HTML 통째 캐시
Router Cache브라우저 메모리세션 또는 5분뒤로가기·페이지 전환 빠르게

요청이 들어오면 — 위에서 아래로 검사. Router Cache 에 있으면 즉시 응답, 없으면 Full Route Cache, 그 안에서 fetch 호출은 Data Cache, 같은 요청 내 중복은 Memoization. 4단 콤보.

2. Request Memoization — 자동 중복 제거

한 페이지 렌더링 중에 같은 fetch 가 여러 번 일어나는 경우.

// app/page.tsx import { getUser } from '@/lib/api'; async function Header() { const user = await getUser(); // ① 호출 return <div>{user.name}</div>; } async function Sidebar() { const user = await getUser(); // ② 같은 호출, 자동으로 ①의 결과 재사용 return <div>{user.email}</div>; } export default function HomePage() { return ( <> <Header /> <Sidebar /> </> ); }

두 컴포넌트가 같은 getUser() 를 부르지만 실제 fetch 는 한 번만. Next 가 자동으로 캐시해서 두 번째 호출에 그대로 돌려준다. React 의 cache() 함수 + fetch 자동 동작.

비밀 — URL+옵션 키 매칭 — 같은 fetch URL + 같은 헤더·메서드면 중복 제거. fetch 가 아닌 함수(db.query·axios)는 자동 안 됨. 그 경우 React 의 cache(fn) 으로 감싸 명시.

3. Data Cache — fetch 결과 영구 저장

16편에서 본 force-cache·revalidate 의 실제 동작층.

// 영구 캐시 (수동 폐기까지) fetch(url, { cache: 'force-cache' }); // 60초마다 갱신 fetch(url, { next: { revalidate: 60 } }); // 태그 붙여서 명시적 폐기 가능 fetch(url, { next: { tags: ['posts'] } }); // 캐시 안 함 (Next 15 기본) fetch(url, { cache: 'no-store' });

위치는 빌드된 서버 메모리 또는 디스크. Vercel 같은 서버리스 환경에선 사용자 가까운 엣지에 분산 저장. 같은 fetch 가 여러 요청에 걸쳐 재사용된다.

4. Full Route Cache — 페이지 통째 HTML

SSG·ISR 페이지가 캐시되는 위치. 빌드 타임에 HTML 을 만들어 디스크에 저장.

// app/blog/[slug]/page.tsx export const revalidate = 3600; // 1시간마다 export default async function PostPage({ params }) { const { slug } = await params; const post = await fetchPost(slug); return <article>{post.body}</article>; }

한 시간 동안은 같은 HTML 이 모든 사용자에게. 사용자 별로 다른 데이터를 보여줘야 하면 페이지에 cookies()·headers() 같은 동적 함수를 부르면 자동으로 Full Route Cache 비활성화.

5. Router Cache — 브라우저 메모리

유일하게 클라이언트 측 캐시. 사용자가 한 번 본 페이지를 다시 갈 때 즉시 보여주려고 React 가 메모리에 들고 있다.

예 — 블로그 목록 → 글 클릭 → 뒤로가기. 뒤로가기 시 서버 fetch 없이 즉시 목록 표시. 5분 또는 세션 동안 유효.

가장 헷갈리는 곳 — 서버에서 revalidatePath 호출했는데 클라이언트에선 옛 데이터가 보이는 현상. Router Cache 가 클라이언트 메모리에 남아 있어서. 강제 새로고침 또는 router.refresh() 호출로 폐기.

폐기 방법 — 4가지 도구

도구대상언제
revalidatePath('/posts')해당 경로의 Data + Full Route Cache글 발행 후
revalidateTag('posts')태그 붙은 모든 Data Cache여러 페이지에 영향 주는 글 수정
router.refresh()현재 페이지의 Router Cache클라이언트에서 서버 변경 반영
재배포모든 빌드 캐시스키마 변경·전면 갱신

Server Action 안에서 revalidatePath + 클라이언트에서 router.refresh() 가 같이 일어나야 진짜 깔끔한 갱신. 한 쪽만 하면 옛 데이터가 어디선가 남아 헷갈린다.

요약 — 17편 좌표

여기까지 정리. Next.js 캐싱 4층 — Request Memoization(요청 내), Data Cache(fetch 결과 영구), Full Route Cache(페이지 HTML 통째), Router Cache(브라우저 메모리). 위에서 아래로 검사. 폐기는 revalidatePath·revalidateTag·router.refresh·재배포 4가지. "옛 데이터가 보여요" 의 90% 가 Router Cache 또는 폐기 누락. 다음 편에서 환경변수로 비밀 설정.

다음 편 예고 — 환경변수 다루기

.env.local·NEXT_PUBLIC 규칙·실수 방지. 18편.

© 2026 주나이테크(주) @JUNAITECH