Part 01. CloudFront 캐싱 정책 완벽 가이드

안녕하세요!
이커머스 웹사이트 운영 중 겪은 AWS CloudFront 캐싱 정책
변경 장애 사례와 해결 방법을 정리해봤습니다.

01. HTTP 통신과 헤더의 이해
✅ 기본 HTTP 통신 흐름
간단하게, 고객이 웹사이트에 방문하게 된다면 아래와 같은 흐름으로 Traffic이 흘러갑니다.
[사용자 브라우저] → [CloudFront] → [Origin Server] → [CloudFront] → [사용자 브라우저]
첫번째 : 브라우저가 요청을 보냄
GET /index.php HTTP/1.1
Host: 이커머스 사이트 주소입니다.
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X)
Accept: text/html
Accept-Language: ko-KR,ko;q=0.9
Cookie: PHPSESSID=abc123; user_id=456
Referer: https://google.com
- Host : 어느 사이트에 접속하는지
- User-Agent : 어떤 디바이스/브라우저인지 (모바일? 데스크톱?)
- Accept : 어떤 형식의 응답을 원하는지
- Accept-Language : 선호하는 언어
- Cookie : 로그인 세션, 장바구니 등 사용자 정보
- Referer : 어디서 왔는지 (사이트에 접근하기 이전 페이지)
두번째 : CloudFront가 요청 받음
CloudFront는 받은 요청을 보고 두 가지 결정을 한다.
아래와 같이 캐시 키를 사용하여 캐시 확인, 캐시가 있는지 없는지 요청을 받고 결정합니다.
1. 캐시 확인 (Cache key 사용)
Cache Key 생성:
URL: /index.php
+ User-Agent: iPhone (설정된 경우)
+ Cookie: PHPSESSID=abc123 (설정된 경우)
예시 Cache Key: "index.php|iPhone|abc123"
2-1. 캐시 Hit
CloudFront: "아! 이거 캐시에 있네!" → 오리진 서버에 안 가고 → 바로 캐시된 응답 반환 → 빠름!
2-2. 캐시 Miss
CloudFront: "캐시에 없네, 오리진 서버에 물어봐야겠다" → 오리진 서버로 요청 전달
세번째 : CloudFront → 오리진 서버 (Cache Miss 시)
Origin Request Policy에 따라 헤더 전달
GET /index.php HTTP/1.1
Host: origin-server.internal
User-Agent: Mozilla/5.0 (iPhone...)
Cookie: PHPSESSID=abc123 ←
Referer: https://google.com
이때 User-Agent, Cookie, Referer 헤더는 Origin Request Policy에 설정을 해야 전달되며,
설정을 안했을 시에는 헤더 전달이 안됩니다. 즉, 서버는 전달받은 헤더만 알 수 있습니다.
네번째 : 오리진 서버 응답
HTTP/1.1 200 OK
Content-Type: text/html
Cache-Control: max-age=300
Set-Cookie: session_token=xyz789
<!DOCTYPE html>
<html>
...모바일 버전 HTML...
</html>
- 서버의 판단 과정 (PHP로 예시)
<?php
// User-Agent 헤더가 전달되었는지 확인
if (isset($_SERVER['HTTP_USER_AGENT'])) {
$userAgent = $_SERVER['HTTP_USER_AGENT'];
// 모바일 감지
if (strpos($userAgent, 'iPhone') !== false ||
strpos($userAgent, 'Android') !== false) {
// 모바일 버전 HTML 반환
include 'mobile_template.php';
} else {
// 데스크톱 버전 HTML 반환
include 'desktop_template.php';
}
} else {
// User-Agent가 없으면 기본값 (데스크톱)
include 'desktop_template.php'; // ← 문제 발생!
}
?>
다섯번째 : CloudFront가 응답 캐싱
1. Origin 응답 받음
2. Cache Key로 캐시에 저장
- Key: "index.php|iPhone|abc123"
- Value: Origin 응답 전체
3. TTL 설정 (Cache-Control 헤더 기반)
4. 사용자에게 응답 전달
여섯번째 : 다음 사용자 요청 시
다음 모바일 사용자:
Cache Key: "index.php|iPhone|def456"
→ 쿠키 다름 → Cache Miss → 오리진 요청
똑같은 모바일 사용자:
Cache Key: "index.php|iPhone|abc123"
→ 완전히 동일 → Cache Hit! → 바로 응답
1-1. User-Agent 헤더의 중요성
📌 User-Agent란? 브라우저가 자신의 신원을 알려주는 헤더
실제 User-Agent 예시
iPhone:
Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X)
AppleWebKit/605.1.15 (KHTML, like Gecko)
Version/16.0 Mobile/15E148 Safari/604.1
Android:
Mozilla/5.0 (Linux; Android 13)
AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/112.0.0.0 Mobile Safari/537.36
Desktop Chrome:
Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/112.0.0.0 Safari/537.36
왜 User-Agent가 중요하냐면, 적응형 웹사이트에서는 같은 URL에서 디바이스별로 다른 URL을 제공합니다.
URL: https://example.com/
모바일 접속:
→ 모바일 최적화 레이아웃
→ 작은 이미지
→ 터치 친화적 버튼
데스크톱 접속:
→ 넓은 레이아웃
→ 큰 이미지
→ 마우스 호버 효과
그렇다면 만약, 서버가 User-Agent를 못받는다면?
<?php
// User-Agent 없음
if (!isset($_SERVER['HTTP_USER_AGENT'])) {
// 기본값으로 데스크톱 버전 반환
include 'desktop_template.php';
}
?>
기본 값으로 데스크톱 버전을 반환하여 하기와 같은 결과를 초래한다.
- 모바일 사용자는 데스크톱 버전을 받는다.
- 그로 인해 레이아웃 깨짐.
- 이미지 사이즈 안맞음.
- 사용자 경험 최악 → 고객 재방문 X
1-2. Cookie 헤더의 역할
📌 Cookie란? 브라우저가 저장하는 작은 데이터 조각입니다.
Cookie 종류
- 세션 쿠키 (ex: PHPSESSID=abc123def456)
- 로그인 상태 유지
- 로그아웃 시 세션 쿠키 삭제됨.
- 영구 쿠키 (ex: user_pref=dark_mode)
- 사용자 설정 저장
- 브라우저 닫아도 유지
- 장바구니 쿠키 (ex: cart_id=789xyz)
- 장바구니 내용 추적 가능.
만약, 쿠키가 전달되지 않으면 ?
<?php
session_start();
// 세션 쿠키가 없으면
if (!isset($_SESSION['user_id'])) {
// 로그인 안 된 것으로 판단
header('Location: /login.php');
exit;
}
// 로그인된 사용자만 볼 수 있는 페이지
echo "환영합니다, " . $_SESSION['username'];
?>
- 로그인했는데 로그인 안 된 것으로 인식 (고객 입장에서는 최악)
- 관리자 역시 첫번째 이유와 같이 관리자 페이지에 접근 불가.
- 장바구니 내용 사라짐 (추적 불가 → 고객 입장에서 쇼핑 불가)
02. CloudFront 동작 원리
상세 내용은 하기 링크를 참고합시다!
https://ssunghwan.tistory.com/17
[AWS CloudFront] AWS에서 CDN서비스 사용하기.
01. What is a CDN?CloudFront를 알아보기에 앞서, CDN이 무엇인지 알고 CF에 대해서 알아보도록 하자. 💁♂️ CDN 이란?Content Delivery Network라고 불리며, 전 세계에 분산된 서버 네트워크를 통해 콘텐츠를
ssunghwan.tistory.com
💁♂️ CloudFront가 없는 경우
단, 거리에 따라 지연 시간에 차이가 있으며, 아래를 참고해보자.
[사용자] ---> [웹 서버]
1ms 100ms
총 소요 시간: 101ms
문제: 멀리 있는 사용자는 느림
- 서울 → 서울 서버 : 10ms
- 부산 → 서울 서버 : 30ms
- LA → 서울 서버 : 150ms
- 런던 → 서울 서버 : 300ms
💁♂️ CloudFront가 있는 경우
[사용자] ---> [CloudFront 엣지] ---> [오리진 서버]
1ms 20ms 100ms
첫 요청: 121ms (약간 느림)
캐시 Hit 시: 21ms (5배 빠름!)
📌 Cache Key 역할 : 캐시를 구분하는 고유 식별자입니다.
- Cache Key 구성 요소:
- URL (필수)
- Query String (선택)
- Headers (선택)
- Cookies (선택)
예시1) URL만 있을 경우 문제점 : 모바일 / 테스크톱 환경이 구분이 안된다.
Cache Key: "/index.php"
예시 2) URL + User-Agent 가 있을 경우 : 디바이스별 다른 캐시를 제공하므로, 환경 구분이 된다.
예시 2 (URL + User-Agent):
Cache Key: "/index.php|Mobile"
Cache Key: "/index.php|Desktop"
📌 실제 시나리오)
사용자 A (Mobile)
요청: GET /index.php
Cache Key: "/index.php|Mobile"
- Cache Miss
- 오리진에서 모바일 HTML 받음
- 캐시 저장
사용자 B (Mobile)
요청: GET /index.php
Cache Key: "/index.php|Mobile" (동일!)
- Cache Hit
- 빠르게 응답. (Origin Server에 안가고, CoudFront 엣지에서 해결)
사용자 C (Desktop)
요청: GET /index.php
Cache Key: "/index.php|Desktop"
- Cache Miss
- 오리진에서 데스크톱 HTML 받음
- 별도 캐시 저장
03. Cache Policy vs Origin Request Policy
두 가지 정책의 차이점에 대해 알아보도록 하자.
📌 Cache Policy (캐시 정책)
목적 : 캐시를 어떻게 구분할까?
Cache Policy:
Headers:
- CloudFront-Is-Mobile-Viewer
Cookies:
- PHPSESSID
Query Strings:
- All
이렇게 캐시 정책을 사용한다면, 같은 URL 이라도 모바일/데스크톱 다른 캐시, 로그인 사용자별 다른 캐시를 받는다.
즉, Cache Policy 영향은?
- 캐시 Hit/Miss 결정
- 캐시 효율성 결정
- Origin에 Header 전달 안함.
📌 Origin Request Policy (오리진 요청 정책)
목적 : 오리진에 무엇을 전달할까?
Origin Request Policy:
Headers:
- User-Agent
- Referer
Cookies:
- All
Query Strings:
- All
이렇게 오리진 요청 정책을 사용한다면 Cache Miss 시 오리진에 요청할 때 User-Agent 헤더, 쿠키를 전달하며
서버가 이 정보를 신뢰하고 판단이 가능하다.
즉, Origin Request Policy의 영향은?
- 캐시 구분에 영향 없음.
- 서버가 받는 정보 결정
- 서버 응답 내용을 결정
3-1. 왜 둘다 필요할까?
✅ 시나리오 1) Cache Policy만 설정하였을 때
Cache Policy:
Headers:
- CloudFront-Is-Mobile-Viewer
Origin Request Policy:
사용자 (Mobile) 요청 동작 ex:
→ Cache Key: "/index.php|Mobile"
→ Cache Miss
→ 오리진 요청
→ User-Agent 헤더 없음
→ 서버가 데스크톱 버전 반환
→ 캐시 저장: "/index.php|Mobile" = 데스크톱 HTML
결과 : 모바일 캐시에 데스크톱 HTML이 저장되며, 모든 모바일 사용자가 데스크톱 버전을 받는다.
✅ 시나리오 2) Origin Request Policy만 설정하였을 때
Cache Policy:
URL: /index.php
Origin Request Policy:
Headers:
- User-Agent
사용자 별 요청 동작 ex:
사용자 A (모바일):
→ Cache Key: "/index.php" (디바이스 구분 없음)
→ Cache Miss
→ 오리진 요청 (User-Agent 전달)
→ 서버가 모바일 HTML 반환
→ 캐시 저장: "/index.php" = 모바일 HTML
사용자 B (데스크톱):
→ Cache Key: "/index.php" (동일!)
→ Cache Hit!
→ 모바일 HTML 반환
✅ 시나리오 3) 둘 다 설정하였을 때
Cache Policy:
Headers:
- CloudFront-Is-Mobile-Viewer
Origin Request Policy:
Headers:
- User-Agent
사용자 별 요청 동작 ex:
사용자 A (모바일):
→ Cache Key: "/index.php|Mobile"
→ Cache Miss
→ 오리진 요청 (User-Agent 전달 ✓)
→ 서버가 모바일 HTML 반환
→ 캐시 저장: "/index.php|Mobile" = 모바일 HTML ✓
사용자 B (데스크톱):
→ Cache Key: "/index.php|Desktop" (다름!)
→ Cache Miss
→ 오리진 요청 (User-Agent 전달 ✓)
→ 서버가 데스크톱 HTML 반환
→ 캐시 저장: "/index.php|Desktop" = 데스크톱 HTML ✓
사용자 C (모바일):
→ Cache Key: "/index.php|Mobile"
→ Cache Hit! ✓
→ 모바일 HTML 반환 ✓