한 페이지, 영역별 캐시 경계
같은 페이지 안에서도 영역마다 캐시 전략이 다릅니다. 헤더는 데이터가 없어 정적 셸에 들어가고, 상품 목록은 컴포넌트 첫 줄의 'use cache'로 렌더 결과째 캐시되며, 환율 배너는 cookies()를 읽어 요청마다 렌더하되 getRate() 함수 결과만 재사용하고, 맞춤 추천은 캐시 없이 매번 서버에서 렌더해 스트리밍됩니다. 한 번의 요청을 재생하면 네 영역의 데이터가 원천 → 캐시 계층 → 화면으로 어떤 경로를 지나 언제 도착하는지, 캐시가 비어 있을 때 무엇이 늦어지는지가 보입니다.
캐시 채워짐 (평소)—요청 도착 — 정적 셸(헤더 + 캐시된 상품 목록)이 곧바로 나간다
// app/page.tsxexport default function Page() {return (<><Header />// 데이터 없음 → 정적 셸<ProductList />// 컴포넌트 첫 줄 'use cache' → 출력 캐시, 셸에 포함<Suspense fallback={<BannerSkeleton />}><PriceBanner />// cookies() 읽어 요청마다 렌더 · getRate()만 캐시</Suspense><Suspense fallback={<ListSkeleton />}><Recommendations />// cookies() + DB → 캐시 없음, 스트리밍</Suspense></>)}
app/_components/ProductList.tsx — 캔버스·코드 지도에 마우스를 올리면 바뀝니다export async function ProductList() {'use cache'cacheLife('hours'); cacheTag('products')const items = await db.products.list()return <Grid items={items} />}
영역마다 캐시 경계가 다르다 — 항목·코드·캔버스 행은 같은 색과 호버로 연결됩니다.
- 헤더 · 내비게이션 — 정적 셸app/_components/Header.tsx · caching.md · 정적 셸
데이터를 읽지 않는 순수 마크업이라 빌드 시점에 HTML로 미리 만들어진다. 요청이 오면 정적 셸의 일부로 첫 바이트와 함께 도착한다 — 캐시 지시자를 붙일 필요조차 없다.
- 상품 목록 — 'use cache' 컴포넌트app/_components/ProductList.tsx · use-cache.md · cacheLife.md · cacheTag.md
컴포넌트 함수 첫 줄에 'use cache'를 두면 렌더 결과(RSC 페이로드) 자체가 캐시된다. cacheLife('hours')로 수명을, cacheTag('products')로 갱신 손잡이를 단다. 캐시가 채워져 있으면 정적 셸에 포함돼 헤더와 같은 순간에 도착하고, 비어 있으면 DB까지 다녀와 저장한 뒤에야 셸이 완성된다.
- 환율 배너 — 'use cache' 함수app/_components/PriceBanner.tsx · lib/rates.ts · use-cache.md:126 (cookies는 밖에서 읽어 인자로)
컴포넌트는 cookies()로 사용자의 통화를 읽어야 해서 요청마다 렌더된다(Suspense 안). 대신 비싼 데이터 함수 getRate(currency)에만 'use cache'를 붙여 반환값을 재사용한다 — 통화를 인자로 넘기므로 통화별로 캐시 키가 갈린다. cookies()를 함수 안에서 읽으면 next-request-in-use-cache 오류가 난다.
- 맞춤 추천 — 동적 · 캐시 없음app/_components/Recommendations.tsx · caching.md · Suspense 스트리밍
사용자마다 결과가 다르고 매 요청 최신이어야 해서 캐시하지 않는다. cookies()로 세션을 읽고 DB를 조회해 서버에서 렌더링한 뒤 <Suspense> 경계 안으로 스트리밍된다 — 그동안 사용자는 fallback 스켈레톤을 본다.
같은 그룹의 다른 시각화
정적 셸과 스트리밍
Next.js · Cache Components정적 셸에 포함되는 영역과 요청 시 스트리밍되는 영역을 구분합니다.
use cache 경계와 키
Next.js · Cache Componentsuse cache 경계와 인자에 따른 캐시 키·HIT·MISS를 확인합니다.
cacheLife의 세 시간
Next.js · Cache Components클라이언트 stale과 서버 revalidate·expire의 시간축을 비교합니다.
태그와 갱신 방식
Next.js · Cache ComponentsupdateTag와 revalidateTag 이후의 읽기·갱신 방식을 비교합니다.
쇼핑몰로 보는 캐시 설정
Next.js · Cache Components상품·상세·장바구니 요청에서 캐시와 원본 서버를 지나는 경로를 추적합니다.