stale-while-revalidate

1 개의 포스트

cloudflare

이제 Worker 앞에 자체 캐시를 둘 수 있습니다 (새 탭에서 열림)

Cloudflare의 **Workers Cache**는 Worker 앞에 계층형 캐시를 배치해, 캐시 적중 시 Worker를 실행하지 않고 응답을 반환하는 기능이다. Wrangler 설정 한 줄과 기존 HTTP `Cache-Control` 헤더만으로 사용할 수 있으며, 캐시 적중 시 CPU 비용과 렌더링 지연을 줄인다. 서버 렌더링 애플리케이션은 정적 사전 생성과 매 요청 렌더링 사이에서, 필요할 때만 렌더링하고 결과를 캐시하는 세 번째 선택지를 얻게 된다. ## 서버 렌더링 앱에 필요한 캐시 - 기존 Workers 구조에서는 Worker가 캐시와 원본 앞에 위치했다. - 요청 변환, URL 재작성, A/B 테스트, 트래픽 필터링 등에 적합했다. - 하지만 Worker 자체가 애플리케이션 서버이자 원본이 되면, 캐시할 대상이 없어 모든 요청이 코드를 실행한다. - Astro, TanStack Start, Next.js, Remix, SvelteKit 같은 프레임워크는 Cloudflare용 어댑터를 통해 앱을 Worker로 배포할 수 있다. - 동일한 응답을 반복 생성하더라도 매번 렌더링해야 하므로: - 페이지 로드마다 렌더링 지연이 발생한다. - Worker CPU 실행 비용이 계속 발생한다. - Workers Cache는 캐시를 Worker 앞에 배치한다. - 캐시 적중: Worker를 실행하지 않고 응답 반환, CPU 비용 0. - 캐시 실패: Worker가 실행되어 응답을 생성하고 캐시에 저장. - 이후 전 세계 어디서든 캐시된 응답을 받을 수 있다. ## 정적 생성과 매 요청 렌더링 사이의 선택지 - 빌드 시점 사전 생성(SSG)은 빠르지만 콘텐츠 변경마다 전체 빌드와 재배포가 필요하다. - 대규모 문서나 전자상거래 사이트에서는 빌드 시간이 길어질 수 있다. - 매 요청 서버 렌더링은 최신 데이터를 반영하지만, 모든 방문자가 렌더링 비용과 지연을 부담한다. - Workers Cache는 요청 시 생성한 결과를 TTL 동안 저장한다. - 새 페이지의 첫 요청만 렌더링한다. - 이후 요청은 정적 페이지처럼 캐시에서 제공한다. - TTL 만료 후 필요할 때 다시 렌더링한다. - 프레임워크별 ISR 구현 없이 표준 HTTP 캐싱 방식으로 동작한다. ## Wrangler 설정과 HTTP 헤더 기반 제어 - Wrangler 설정에서 캐시를 활성화한다. ```json { "name": "my-worker", "main": "src/index.ts", "compatibility_date": "2026-05-01", "cache": { "enabled": true } } ``` - 응답의 `Cache-Control` 헤더로 캐시 정책을 지정한다. ```ts return new Response(body, { headers: { "Cache-Control": "public, max-age=300, stale-while-revalidate=3600", "Cache-Tag": "products,product:123" } }); ``` - 별도의 Zone 설정, 규칙 엔진, 캐시 프로비저닝 없이 Worker 코드와 HTTP 헤더만으로 구성한다. - 커스텀 도메인, `workers.dev`, 서비스 바인딩, 프리뷰, Workers for Platforms 테넌트 등 Worker가 실행되는 여러 진입점에서 동일한 방식으로 사용할 수 있다. ## `stale-while-revalidate`로 만료 시에도 지연 방지 - `max-age=300`은 응답을 5분 동안 신선한 상태로 유지한다. - `stale-while-revalidate=3600`은 만료 후 최대 1시간 동안 오래된 응답을 즉시 제공하면서 백그라운드에서 새 응답을 생성하도록 한다. - 이 설정이 없으면 TTL 만료 직후 첫 요청이 Worker 렌더링을 기다려야 한다. - 설정이 있으면: - 사용자는 오래된 페이지를 즉시 받는다. - 응답에는 `Cf-Cache-Status: UPDATING`이 표시될 수 있다. - Worker는 백그라운드에서 캐시를 갱신한다. - 갱신을 유발한 요청자도 캐시 수준의 응답 속도를 얻는다. ## 캐시 무효화와 고급 기능 - 콘텐츠가 변경되면 Worker에서 직접 캐시를 제거할 수 있다. ```ts await ctx.cache.purge({ tags: ["product:123"] }); ``` - `Cache-Tag`를 사용하면 특정 상품이나 콘텐츠 그룹 단위로 캐시를 무효화할 수 있다. - 글에서 언급한 추가 기능은 다음과 같다. - 네트워크 전반의 계층형 캐싱 - `Vary`를 이용한 콘텐츠 협상 - `ctx.props` 기반의 멀티테넌트 안전 캐시 키 - 태그 또는 경로 접두사 기반 프로그래밍 방식 purge - 공개 엔드포인트뿐 아니라 모든 Worker 진입점 앞에 캐시 배치 - 진입점별 캐시 활성화 여부 제어 ## 적용 범위와 의의 - Workers Cache는 모든 요금제의 Worker에서 사용할 수 있으며 Wrangler로 활성화한다. - 캐시는 애플리케이션 구조에 맞춰 여러 진입점 사이에 배치할 수 있다. - 결과적으로 서버 렌더링 앱은 정적 사이트에 가까운 응답 속도와 동적 서버 렌더링의 최신성, 두 가지를 함께 얻을 수 있다. - 실무에서는 페이지 특성에 따라 `max-age`와 `stale-while-revalidate` 값을 정하고, 데이터 변경 시 `Cache-Tag` 기반 purge를 함께 사용하는 방식이 적합하다.