웹 성능 최적화의 기본은 캐싱입니다. Cache-Control 헤더 하나로 브라우저 캐싱을 제어할 수 있고, ETag로 변경 여부를 효율적으로 확인할 수 있습니다.


캐시 동작 흐름

PLAINTEXT
1. 첫 번째 요청:
   클라이언트 → GET /image.png → 서버
   서버 → 200 OK + Cache-Control: max-age=3600 + ETag: "abc123"
   → 브라우저가 캐시에 저장

![HTTP 캐싱 흐름](/images/diagrams/net-http-caching.svg)

2. 1시간 이내 재요청 (캐시 유효):
   브라우저 캐시에서 직접 반환 (서버 요청 없음!)

3. 1시간 이후 재요청 (캐시 만료):
   클라이언트 → GET /image.png + If-None-Match: "abc123"
   서버 → 304 Not Modified (변경 없음, 본문 없이 응답)
   → 캐시된 자원 재사용

Cache-Control 디렉티브

디렉티브의미
max-age=NN초 동안 캐시 유효
no-cache캐시 저장은 하되, 매번 서버에 검증
no-store캐시에 저장하지 않음 (민감 데이터)
publicCDN 등 공유 캐시에 저장 가능
private브라우저 캐시에만 저장 (개인 정보)
immutable만료 전에는 절대 재검증하지 않음
stale-while-revalidate=N만료 후 N초간 캐시를 먼저 반환하고 백그라운드에서 갱신
PLAINTEXT
# 정적 자원 (JS, CSS, 이미지) — 파일명에 해시 포함
Cache-Control: public, max-age=31536000, immutable

# API 응답 — 개인화된 데이터
Cache-Control: private, no-cache

# 로그인 페이지 — 캐시 금지
Cache-Control: no-store

ETag와 조건부 요청

ETag (Entity Tag)

자원의 버전 식별자입니다. 자원이 변경되면 ETag도 변경됩니다.

PLAINTEXT
응답: ETag: "abc123"
재요청: If-None-Match: "abc123"
→ 변경 없으면: 304 Not Modified
→ 변경 있으면: 200 OK + 새 ETag + 새 본문

Last-Modified / If-Modified-Since

PLAINTEXT
응답: Last-Modified: Wed, 15 Jan 2025 08:00:00 GMT
재요청: If-Modified-Since: Wed, 15 Jan 2025 08:00:00 GMT
→ 이후 변경 없으면: 304
→ 변경 있으면: 200

ETag가 Last-Modified보다 정확합니다 (1초 미만 변경, 내용 동일한데 날짜만 변경 등).


캐시 무효화 전략

파일명 해싱 (Cache Busting)

HTML
<!-- 파일 내용이 바뀌면 해시가 바뀜 → 새 URL → 새 캐시 -->
<script src="/app.abc123.js"></script>
<!-- 빌드 시 해시 변경 -->
<script src="/app.def456.js"></script>

CDN 캐시 퍼지

BASH
# Cloudflare 캐시 퍼지
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE/purge_cache" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"purge_everything": true}'

핵심 포인트

  • no-cache vs no-store: no-cache는 캐시하되 매번 검증, no-store는 아예 캐시 안 함
  • 304 응답의 이점: 본문 없이 헤더만 전송 → 대역폭 절약
  • CDN 캐시와 브라우저 캐시: public으로 CDN 허용, private로 브라우저만 허용

정리

HTTP 캐싱은 웹 성능의 기본입니다. max-age로 캐시 수명을 결정하고, ETag/Last-Modified로 조건부 요청을 처리합니다. 정적 자원에는 긴 max-age + 파일명 해시, API에는 no-cache 또는 짧은 max-age를 적용하는 것이 일반적입니다.

댓글 로딩 중...