Cache 심화 실습

Cache Configuration 전기능 — 35개 시나리오

엔지니어 교육용 · 발표자 덱 · 2026

Lab Setup

실습 환경 구성

항목
Cache Lab Origincache.cflarekr.dev (GCP VM, europe-west3)
Origin IP34.185.205.86 (DNS-only A 레코드)
학생 DNS 설정CNAME cache.<student-zone> → cache.cflarekr.dev (Proxied ON)
$ZONE 변수export ZONE="cache.<student-zone>"
서버 인덱스https://test-cache.cflarekr.dev/ (전체 엔드포인트 목록)
모든 실습은 CF 대시보드 설정만 변경. Origin 서버 수정 불필요.
Lab Setup

Origin 서버 주요 엔드포인트

경로반환 특성시나리오
/s05/cc?val=no-cacheCache-Control: no-cacheS05, S10
/s06/nonexistHTTP 404 (3분 TTL 테스트)S06
/s08/resourcepublic, max-age=10 (Serve Stale)S08
/s09/resource.jsStrong ETag + 304 지원S09, S31
/s13/landingab_group 쿠키별 다른 HTMLS13
/s15/user/profile.csstext/html at .css URLS15
/s19/product/123Cache-Tag: product-123, ...S19
/s25/api/catalogCache-Control + CDN-Cache-ControlS25
/s26/down?always=1항상 503 (서버 다운 시뮬레이션)S26
/s30/hero.jpgAccept 기반 WebP/JPEG 분기S30
/large/10mb10 MB 바이너리 (Cache Reserve)S23
Reference

cf-cache-status 전체 값

의미언제 보이나
HIT캐시에서 서빙두 번째 요청부터
MISS캐시 없어 origin fetch 후 저장첫 번째 요청
EXPIREDTTL 만료, origin 재검증 중TTL 초과 직후
REVALIDATED304 응답 → 캐시 갱신ETag/Last-Modified 일치
UPDATINGStale 서빙 중 (백그라운드 fetch)Serve Stale ON + TTL 만료
STALETTL 만료 + origin 불가Always Online
BYPASSCF가 명시적 우회Set-Cookie, Cache Rule Bypass
DYNAMIC캐시 비대상 (HTML 등)기본 미캐시 콘텐츠
Reference

공통 검증 curl 패턴

# 캐시 상태 한 줄 확인
curl -sI "https://$ZONE/path" | grep -i "cf-cache-status\|age\|cache-control"

# 반복 확인 (HIT 전환 대기)
for i in 1 2 3; do
  echo "=== $i ===" && curl -sI "https://$ZONE/path" | grep cf-cache-status
  sleep 2
done

# TTL 만료 후 상태 확인
sleep 35 && curl -sI "https://$ZONE/path" | grep -i "cf-cache-status\|age"

# CF-Ray로 데이터센터 확인 (Tiered Cache)
curl -sI "https://$ZONE/path" | grep -i "cf-ray"
Overview

35개 시나리오 전체 목록

Part I — 기초

S01 Default Cache Behavior   S02 Default Edge TTL

Part II — Cache Rules

S03 Cache Everything   S04 Bypass   S05 Edge TTL 3모드
S06 Status Code TTL   S07 Browser TTL   S08 Serve Stale
S09 Strong ETags   S10 Origin Cache Control   S11 Error Passthrough

Part III — Cache Key

S12 Query String   S13 Cookie 분기   S14 User Features
S15 Cache Deception Armor   S16 Bypass on Cookie

Part IV — Purge

S17 Single File   S18 Prefix   S19 Cache Tags
S20 Custom Cache Key   S21 Everything

Part V — 고급

S22 Tiered Cache   S23 Cache Reserve   S24 QS Sort
S25 CDN-Cache-Control   S26 Always Online   S27 Dev Mode
S28 Early Hints   S29 Crawler Hints   S30 Vary for Images

Part VI~VIII

S31 Revalidation   S32 Cache Poisoning   S33 CORS
S34 Cache Analytics   S35 Rule Priority

Part I — Cache 기초

Default Cache Behavior · Default Edge TTL
Part I

S01Default Cache Behavior

기본 캐시 대상 (파일 확장자 기반)

# CSS → HIT (기본 캐시)
curl -sI "https://$ZONE/static/style.css" | grep cf-cache-status
# → MISS 첫 요청 후 HIT

# HTML → DYNAMIC (기본 미캐시)
curl -sI "https://$ZONE/html/page.html" | grep cf-cache-status
# → DYNAMIC

# Set-Cookie → BYPASS
curl -sI "https://$ZONE/s13/set-cookie?group=A" | grep cf-cache-status
# → BYPASS
확장자기본 캐시
css, js, png, jpg, gif✅ 캐시
woff, woff2, svg, ico✅ 캐시
mp4, pdf, zip✅ 캐시
html, json, xml❌ DYNAMIC
Set-Cookie 있는 응답❌ BYPASS
💡 HTML/JSON 캐시는 Cache Rule에서 Eligible 명시 필요
Part I

S02Default Edge TTL — Status Code별

HTTP Status기본 Edge TTL
200, 206, 301120분
302, 30320분
404, 4103분
기타 (500, 503 등)캐시 안 함
Cache-Control 헤더 없을 때 CF가 적용하는 기본값
# 200 → 120분 캐시
curl -sI "https://$ZONE/s02/asset.js" | grep -i "age\|cf-cache-status"

# 404 → 3분 캐시
curl -sI "https://$ZONE/s06/nonexist"
sleep 10
curl -sI "https://$ZONE/s06/nonexist" | grep cf-cache-status
# → HIT (3분 내)

sleep 190
curl -sI "https://$ZONE/s06/nonexist" | grep cf-cache-status
# → EXPIRED (3분 초과)

Part II — Cache Rules 핵심 설정

Cache Eligibility · Edge/Browser TTL · Serve Stale · ETag · Origin CC
Part II

S03Cache Everything — HTML/JSON 캐싱

Cache Rule 설정

When: URI Path contains /s03/
Then: Cache eligibility → Eligible for cache
      Edge TTL: Ignore origin CC → 30 seconds
# 적용 전: DYNAMIC
curl -sI "https://$ZONE/s03/page" | grep cf-cache-status

# 규칙 적용 후: MISS → HIT
curl -sI "https://$ZONE/s03/page" | grep cf-cache-status  # MISS
curl -sI "https://$ZONE/s03/page" | grep cf-cache-status  # HIT

# 30초 후 → EXPIRED
sleep 35 && curl -sI "https://$ZONE/s03/page" | grep cf-cache-status
💡 HTML/JSON은 Eligible for cache로 명시해야 캐시됨. Edge TTL override로 origin CC 무관하게 TTL 지정.
Part II

S04Bypass Cache

Cache Rule

When: URI Path contains /s04/
Then: Cache eligibility → Bypass cache
# Bypass 규칙 적용 후
curl -sI "https://$ZONE/s04/page" | grep cf-cache-status
# → DYNAMIC (항상 origin 요청)
BYPASS vs DYNAMIC
• BYPASS: 명시적 우회 규칙 적용
• DYNAMIC: 기본 미캐시 콘텐츠
Bypass 규칙 적용 시 DYNAMIC으로 표시됨
💡 로그인 페이지, API 엔드포인트 등에 적용
Part II

S05Edge TTL — 3가지 모드

모드API값동작
Use CC if present, default if notrespect_originorigin CC 따름, 없으면 CF 기본 TTL
Ignore CC, use this TTLoverride_originorigin 헤더 무시, 지정 TTL 강제
Use CC if present, bypass if notbypass_by_defaultCC 없으면 캐시 안 함
# override_origin 테스트 (10초 강제)
# Rule: URI=/s05/cc, Edge TTL: Ignore CC → 10s
curl -sI "https://$ZONE/s05/cc?val=public,max-age=3600"
# MISS (origin은 3600초 반환)
sleep 12
curl -sI "https://$ZONE/s05/cc?val=public,max-age=3600" | grep cf-cache-status
# EXPIRED (CF는 10초만 캐시)

# bypass_by_default: CC 없는 경로
curl -sI "https://$ZONE/s05/no-cc" | grep cf-cache-status
# DYNAMIC (CC 없음 → bypass)
Part II

S06Status Code TTL — 상태코드별 캐시 시간

# Rule: URI=/s03/page
# Edge TTL: Status Code TTL
#   200 → 300s
#   404 → 10s
#   5xx → 0s (no-cache)
# 200 페이지
curl -sI "https://$ZONE/s03/page" | grep cf-cache-status
# HIT → age 증가 (300초 기준)

# 404 페이지 (10초)
curl -sI "https://$ZONE/s06/nonexist"  # MISS
sleep 5 && curl -sI ... | grep cf-cache-status  # HIT
sleep 8 && curl -sI ... | grep cf-cache-status  # EXPIRED
⚠️ 404 캐시 운영 이슈
없는 페이지를 오래 캐시하면
새로 생성 후에도 구 404가 서빙됨.
Status Code TTL로 짧게 설정 권장.
💡 Error 페이지 캐시 = 흔한 운영 실수
5xx는 0 또는 -1(no-store)로 설정
Part II

S07Browser TTL

설정의미
Bypassmax-age=0 (브라우저 캐시 없음)
Respect originorigin Cache-Control 그대로
Override origin직접 지정한 초 수
# Rule: URI ends with .css
# Browser TTL: Override → 86400s
curl -sI "https://$ZONE/s07/style.css" | grep -i cache-control
# Cache-Control: max-age=86400
Edge TTL vs Browser TTL
• Edge TTL: CF 엣지 보관 시간
• Browser TTL: 방문자 브라우저 보관
둘은 독립적으로 설정
💡 Browser TTL을 너무 길게 설정하면
Purge해도 브라우저엔 구 버전 잔류
Part II

S08Serve Stale While Revalidating

# Rule: URI=/s08/resource, Edge TTL: 10s
# Serve stale: ON (기본값)
curl -sI "https://$ZONE/s08/resource"  # MISS
sleep 12
curl -sI "https://$ZONE/s08/resource" | grep cf-cache-status
# UPDATING (stale 서빙 + 백그라운드 fetch)
curl -sI "https://$ZONE/s08/resource" | grep cf-cache-status
# HIT (새 콘텐츠 저장 완료)
Serve StaleTTL 만료 시 동작
ON (기본)UPDATING → 이전 캐시 즉시 서빙 백그라운드에서 origin fetch
OFFEXPIRED → origin fetch 완료까지 대기
💡 Serve Stale OFF = 캐시 만료마다
사용자가 origin 응답 대기 → 레이턴시 증가
Part II

S09Respect Strong ETags

# Rule: URI=/s09/resource.js
# Respect Strong ETags: ON

# 1) ETag 확인
curl -sI "https://$ZONE/s09/resource.js" | grep -i etag
# ETag: "f1418e1e8c06cc233cd2ce40fd9340ca"

# 2) If-None-Match 조건부 요청
ETAG=$(curl -sI "https://$ZONE/s09/resource.js" | grep -i etag | awk '{print $2}')
curl -sI "https://$ZONE/s09/resource.js" -H "If-None-Match: $ETAG"
# HTTP/2 304 + cf-cache-status: REVALIDATED
ETag 종류형식CF 기본
Strong"abc123"OFF (Weak으로 변환)
WeakW/"abc123"ON (기본값)
Respect Strong ETags OFF(기본) →
CF가 Strong → Weak으로 변환.
ON 설정 시 byte-for-byte 비교 활성화.
Part II

S10Origin Cache Control

Origin Cache-ControlCF 동작서버 경로
no-cache매 요청 revalidate 필요/s10/no-cache
no-store캐시 저장 자체 금지/s10/no-store
private개인 캐시만, CF 캐시 거부/s10/private
public, max-age=3600공개 1시간 캐시/s10/public
# private → DYNAMIC
curl -sI "https://$ZONE/s10/private" | grep -i "cache-control\|cf-cache-status"

# Edge TTL override로 private 무시 강제
# Rule: URI=/s10/private, Edge TTL: Ignore CC → 60s
curl -sI "https://$ZONE/s10/private" | grep cf-cache-status
# HIT (private 무시 → 강제 캐시)
💡 override_origin = origin의 no-cache/private 무시. API 응답 잘못 캐시 위험 주의!
Part II

S11Origin Error Page Pass-through

# OFF (기본): CF 기본 에러 페이지
curl -s "https://$ZONE/s11/down" | grep -i "cloudflare\|error"

# Cache Rule: URI=/s11/down
# Origin error page pass-through: ON
curl -s "https://$ZONE/s11/down" | grep -i "서비스 점검\|X-Error-From"
# origin 실제 에러 페이지 반환
서버: /s11/down → 항상 503
커스텀 브랜드 에러 페이지 포함

/s11/partial-down → 50% 확률 503
💡 ON: origin 브랜드 에러 페이지 표시
OFF: Cloudflare 기본 에러 페이지

Part III — Cache Key 고급

Query String · Cookie · User Features · Cache Deception Armor
Part III

S12Query String — Cache Key 처리

모드동작설정
기본 (Include All)?a=1&b=2 와 ?b=2&a=1 = 별도 캐시기본값
Ignore Query String쿼리 무관 동일 캐시exclude: *
Query String Sort파라미터 정렬 후 비교ON
Include specific지정 파라미터만 포함Enterprise
# Sort ON → 파라미터 순서 무관 HIT
curl -sI "https://$ZONE/s12/items?b=2&a=1"  # MISS
curl -sI "https://$ZONE/s12/items?a=1&b=2"  # HIT ✅

# Ignore QS → 쿼리 무관 HIT
# Rule: Cache Key > Query String: Ignore
curl -sI "https://$ZONE/s12/items?color=red"   # MISS
curl -sI "https://$ZONE/s12/items?color=blue"  # HIT ✅
💡 마케팅 파라미터(utm_*, fbclid) 제외 시 캐시 히트율 대폭 향상
Part III

S13Cookie 기반 Cache Key (Enterprise)

# Rule: URI=/s13/landing
# Cache Key > Cookie: ab_group (include value)

# 쿠키 없이
curl -sI "https://$ZONE/s13/landing"  # MISS

# A 그룹
curl -sI "https://$ZONE/s13/landing" -H "Cookie: ab_group=A"
# MISS (별도 Cache Key)

# B 그룹
curl -sI "https://$ZONE/s13/landing" -H "Cookie: ab_group=B"
# MISS (또 다른 Cache Key)

# A 그룹 재요청
curl -sI "https://$ZONE/s13/landing" -H "Cookie: ab_group=A"
# HIT ✅
서버: /s13/landing
• ab_group=A → 오렌지 배경
• ab_group=B → 파란 배경
각각 별도 캐시 버전
💡 쿠키 전체를 포함하면
사용자별 개별 캐시 → 히트율 0%
필요한 쿠키명만 포함할 것
Part III

S14User Features — Device / Country / Language

User FeatureCache Key 추가 요소
Device Typemobile / desktop / tablet
CountryCF-IPCountry (IP 기반)
LanguageAccept-Language 헤더 첫 번째 값
# Rule: URI=/s14/content
# Cache Key > User > Device Type: ON

# 모바일
curl -sI "https://$ZONE/s14/content" \
  -H "User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 14_0)"

# 데스크톱
curl -sI "https://$ZONE/s14/content" \
  -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64)"
# 각각 별도 Cache Key → 별도 HIT
💡 Device Type은 CF가 User-Agent 분석
Country는 IP 기반이라 정확
Language는 브라우저 설정 반영
Part III

S15Cache Deception Armor

# ⚠️ 취약 상태 (Cache Deception Armor OFF)
# /user/profile.css → origin이 text/html 반환
curl -sI "https://$ZONE/user/profile.css" | grep -i "content-type\|cf-cache-status"
# Content-Type: text/html
# cf-cache-status: HIT ← 위험! 개인정보 캐시됨

# ✅ Cache Deception Armor ON
# Cache Rule: Cache Deception Armor: ON
curl -sI "https://$ZONE/user/profile.css" | grep cf-cache-status
# MISS or BYPASS (Content-Type 불일치 → 캐시 거부)
공격: /account/secret.css
→ CF가 .css = 캐시 대상 오인
→ HTML 개인정보 캐시됨

Armor ON: Content-Type ≠ URL 확장자
→ 캐시 거부
💡 보안 필수 설정
개인정보 포함 응답이
캐시되는 것을 방지
Part III

S16Bypass Cache on Cookie

# Rule: Cookie contains "session"
# Then: Bypass cache

# 쿠키 없음 → 정상 캐시
curl -sI "https://$ZONE/s16/page" | grep cf-cache-status
# HIT

# session 쿠키 있음 → Bypass
curl -sI "https://$ZONE/s16/page" \
  -H "Cookie: session=user123abc" | grep cf-cache-status
# DYNAMIC (Bypass 적용)
Expression 예시:
http.cookie contains "session"
http.cookie contains "wordpress_logged_in_"
💡 로그인 사용자 = 개인화 콘텐츠 → 반드시 Bypass
비로그인 사용자만 캐시 서빙

Part IV — Purge (캐시 제거)

Single File · Prefix · Cache Tags · Custom Key · Everything
Part IV

S17Purge — Single File

Dashboard

Caching > Configuration > Purge Cache > Purge by URL
URL: https://$ZONE/static/style.css

API

curl -X POST \
  "https://api.cloudflare.com/client/v4/zones/<ZONE_ID>/purge_cache" \
  -H "Authorization: Bearer <TOKEN>" \
  -H "Content-Type: application/json" \
  --data '{"files": ["https://<zone>/static/style.css"]}'
# Purge 전
curl -sI "https://$ZONE/static/style.css" | grep cf-cache-status
# HIT

# Purge 실행 후
curl -sI "https://$ZONE/static/style.css" | grep cf-cache-status
# MISS ← 제거됨
Part IV

S18Purge — Prefix (URL 경로 접두사)

Business 이상 Plan 필요
curl -X POST "https://api.cloudflare.com/client/v4/zones/<ZONE_ID>/purge_cache" \
  -H "Authorization: Bearer <TOKEN>" \
  -H "Content-Type: application/json" \
  --data '{"prefixes": ["<zone>/s03/"]}'
# /s03/ 하위 모든 캐시 MISS로 전환
curl -sI "https://$ZONE/s03/page" | grep cf-cache-status  # MISS
💡 /static/ prefix Purge → JS/CSS/이미지 전체 갱신에 유용
CDN 배포 시 /assets/v2.0.1/ → /assets/v2.1.0/ 전환 패턴
Part IV

S19Purge — Cache Tags (Enterprise)

서버가 Cache-Tag 헤더 반환:

경로Cache-Tag
/s19/product/123product-123, category-merchandise, all-products
/s19/product/456product-456, category-merchandise, all-products
/s19/category/merchandisecategory-merchandise, all-products
# product-123 태그 Purge
--data '{"tags": ["product-123"]}'

# 결과
/s19/product/123 → MISS (product-123 포함)
/s19/product/456 → HIT  (product-456만 포함)
/s19/category/merchandise → MISS (공유 태그 포함)
💡 상품/카테고리 업데이트 시
관련 캐시만 선택적 Purge

단순 URL Purge보다 훨씬 강력
수천 개 URL을 태그 하나로 제어
Part IV

S20 Custom Cache Key Purge & S21 Purge Everything

S20 — Custom Cache Key로 Purge

# Cache Key에 X-Language 헤더 포함된 경우
curl -X POST .../purge_cache \
  --data '{"files": [{
    "url": "https://<zone>/s14/content",
    "headers": {"X-Language": "ko"}
  }]}'
# "ko" 버전만 Purge, "en" 버전은 HIT 유지

S21 — Purge Everything

⚠️ 강력한 작업: Zone 전체 캐시 제거 → origin에 급격한 트래픽
Dashboard: Caching > Configuration > Purge Everything

Part V — 고급 캐시 기능

Tiered Cache · Cache Reserve · QS Sort · CDN-CC · Always Online · Dev Mode · Early Hints · Crawler Hints · Vary
Part V

S22Tiered Cache

[사용자] → [CF 로컬 PoP]
             ↓ Miss
         [CF 상위 PoP (Tier)]
             ↓ Miss
         [Origin]
# Caching > Tiered Cache > Smart → Enable
# 여러 PoP에서 요청 시 Tier PoP 캐시 활용
curl -sI "https://$ZONE/s22/page" | grep -i "cf-ray\|cf-cache-status"
# CF-Ray: a1b2c3-ICN (서울 PoP)
# cf-cache-status: HIT (Tier PoP에서 서빙)
💡 전 세계 330+ PoP 각각이
origin에 직접 요청 대신
상위 Tier PoP에서 캐시 조회

Origin 요청 수 대폭 감소
Analytics에서
Cache Hit Rate 개선 확인
Part V

S23Cache Reserve

# Caching > Cache Reserve → Enable
# Rule: File extension in [zip, mp4, dmg]
# Cache Reserve Eligibility: ON
# Minimum file size: 10,000,000 (10MB)

# 테스트 파일
curl -sI "https://$ZONE/s23/installer.zip" \
  | grep -i "cf-cache-status\|content-length"
# Content-Length: 10485760 (10MB)
# cf-cache-status: HIT (R2에 영구 저장)
일반 CF 캐시Cache Reserve
LRU eviction (자주 미사용 시 제거)R2 영구 저장 (eviction 없음)
Free tier: 512MB과금 기반 (R2 요금)
대용량 파일 불리대용량 파일 최적
💡 동영상, 설치 파일, ISO 등
대용량 + 드물게 요청되는 파일에 적합
Part V

S24 Query String Sort & S25 CDN-Cache-Control

S24 — Query String Sort

# Caching > Configuration > Query String Sort: ON
# 또는 Cache Rule > Cache Key > Sort QS

curl -sI "https://$ZONE/s12/items?b=2&a=1"  # MISS
curl -sI "https://$ZONE/s12/items?a=1&b=2"  # HIT ✅
# 내부 정렬 → 동일 Cache Key

S25 — CDN-Cache-Control

curl -sI "https://$ZONE/s25/api/catalog" \
  | grep -iE "cache-control|cdn-cache"
# Cache-Control: public, max-age=60     (브라우저)
# CDN-Cache-Control: max-age=86400      (CF Edge)
# 브라우저: 60초, CF: 86400초 독립 캐시
Part V

S26Always Online

# 1) Always Online: ON
#    Caching > Configuration > Always Online

# 2) 사전 캐시
# Rule: URI=/s26/recovery, Eligible, TTL=300s
curl -sI "https://$ZONE/s26/recovery"  # MISS→HIT

# 3) Origin Down 시뮬레이션
# /s26/down?always=1 → 항상 503

# 4) Stale 서빙 확인
curl -sI "https://$ZONE/s26/recovery" \
  | grep cf-cache-status
# STALE ← Always Online이 캐시 서빙
Internet Archive 연동:
CF에 없는 페이지도 일부 서빙 가능

표시: cf-cache-status: STALE
💡 Origin 장애 시 비상 서빙
완전한 대체는 아님
(최신 데이터 아닐 수 있음)
Part V

S27 Development Mode & S28 Early Hints

S27 — Development Mode

# Caching > Configuration > Development Mode: ON
# 3시간 동안 모든 캐시 무력화

curl -sI "https://$ZONE/static/style.css" \
  | grep cf-cache-status
# BYPASS (Dev Mode 중)
배포 직후 즉시 확인용
3시간 후 자동 비활성화

S28 — Early Hints (103)

# Speed > Optimization > Early Hints: ON
curl -sI "https://$ZONE/s28/page" \
  | grep -i "link"
# Link: </static/style.css>; rel=preload; as=style,
#       </static/app.js>; rel=preload; as=script
# CF가 origin 응답 전에 103 전송
# 브라우저가 CSS/JS 선제 로드
Part V

S29 Crawler Hints & S30 Vary for Images

S29 — Crawler Hints

# Caching > Configuration > Crawler Hints: ON

# 1) 캐시
curl -sI "https://$ZONE/s29/blog/post"  # HIT

# 2) Purge → IndexNow 자동 전송
# Bing/Yandex에 변경 알림
--data '{"files": ["https://<zone>/s29/blog/post"]}'

S30 — Vary for Images

# Speed > Polish: ON, Vary for Images: ON

# WebP 지원 브라우저
curl -sI "https://$ZONE/s30/hero.jpg" \
  -H "Accept: image/webp" | grep -i "content-type\|x-image-format"
# Content-Type: image/webp

# 레거시 브라우저
curl -sI "https://$ZONE/s30/hero.jpg" \
  -H "Accept: image/jpeg" | grep -i "content-type"
# Content-Type: image/jpeg

Part VI — Revalidation & ETag

조건부 요청 · 304 Not Modified · REVALIDATED
Part VI

S31Cache Revalidation 흐름

# Rule: URI=/s31/resource.js
# Respect Strong ETags: ON
# Edge TTL: respect_origin (max-age=10 반환)

# 1) MISS + ETag 확인
curl -sI "https://$ZONE/s31/resource.js" \
  | grep -i "etag\|cf-cache-status"
# ETag: "f1418e1e8c06cc233cd2ce40fd9340ca"
# cf-cache-status: MISS

# 2) HIT
curl -sI "https://$ZONE/s31/resource.js" | grep cf-cache-status
# HIT (age 증가)

# 3) TTL 만료 후 (10초)
sleep 12
curl -sI "https://$ZONE/s31/resource.js" | grep cf-cache-status
# REVALIDATED (CF→origin If-None-Match → 304)
cf-cache-status의미
EXPIREDTTL 만료, revalidate 시작
REVALIDATEDorigin 304 → 캐시 갱신됨
MISSorigin 변경됨, 새 콘텐츠 저장
💡 REVALIDATED = origin 변경 없음
origin 데이터 전송 없이 캐시 갱신
대역폭 절감

Part VII — 캐시 보안

Cache Poisoning · CORS
Part VII

S32 Cache Poisoning & S33 CORS

S32 — Cache Poisoning 테스트

# 서버: /s32/reflect → X-Forwarded-Host 반영
curl -sI "https://$ZONE/s32/reflect" \
  -H "X-Forwarded-Host: evil.com" | grep -i x-reflected
# X-Reflected-Host: evil.com

# 방어: Transform Rule로 X-Forwarded-Host 제거
# 또는 URL 정규화 활성화

S33 — CORS 캐시

# /s33/api/data → Access-Control-Allow-Origin: *
#               + Vary: Origin
curl -sI "https://$ZONE/s33/api/data" \
  -H "Origin: https://app-a.example.com" \
  | grep -i "access-control\|vary\|cf-cache-status"

# CF는 기본적으로 Origin 헤더를
# Cache Key에 포함 → CORS 응답 안전

Part VIII — Analytics & Rule Priority

Cache Analytics · Rule 우선순위 충돌
Part VIII

S34Cache Analytics 대시보드

확인 항목목표/기준
Cache Hit Rate90%+ 이상 목표
Bandwidth Saved히트율 × 평균 응답 크기
Top MISS URLsCache Rule 추가 검토 대상
DYNAMIC 많은 경로의도적 미캐시인지 확인
시간대별 패턴TTL 만료 패턴 분석
Caching > Cache Analytics

히트율 낮은 원인:
• HTML/JSON 미캐시 (가장 흔함)
• TTL이 너무 짧음
• Query String 분산
• 마케팅 파라미터 미제거
💡 Analytics → MISS 경로 분석
→ Cache Rule 추가 후
→ Hit Rate 재측정
Part VIII

S35Cache Rule 우선순위 충돌 테스트

# 시나리오: 두 규칙이 겹칠 때 어느 쪽이 이기는가?

# Rule A (하위): URI contains /s35/products/  → Eligible, TTL=60s
# Rule B (상위): URI = /s35/products/sale/    → Bypass

curl -sI "https://$ZONE/s35/products/general" | grep cf-cache-status
# HIT (Rule A 적용)

curl -sI "https://$ZONE/s35/products/sale/" | grep cf-cache-status
# ? Rule B가 위에 있으면 DYNAMIC, 아래면 HIT

# → Rule B를 Rule A 위로 이동
curl -sI "https://$ZONE/s35/products/sale/" | grep cf-cache-status
# DYNAMIC ✅ (Bypass 정상 적용)
💡 더 구체적인 경로 Rule을 위에 배치.
CF Rules: first-match wins (위→아래 순서)
Summary

실습 완료 체크리스트

Cache Rules 설정

☐ Cache Eligibility (Bypass/Eligible)
☐ Edge TTL 3가지 모드
☐ Status Code TTL
☐ Browser TTL
☐ Serve Stale
☐ Respect Strong ETags
☐ Origin Cache Control
☐ Origin Error Page Pass-through
☐ Cache Deception Armor
☐ Cache Key (QS / Cookie / User)

Purge

☐ Single File
☐ Prefix
☐ Cache Tags
☐ Custom Cache Key
☐ Everything

고급 기능

☐ Tiered Cache
☐ Cache Reserve
☐ CDN-Cache-Control
☐ Always Online
☐ Early Hints / Crawler Hints
☐ Vary for Images