S3 정적 파일, 캐시 미설정으로 CloudFront 비용 낭비한 경험
CloudFront 비용을 줄여보려고 트래픽 높은 엔드포인트를 분석했다. 이미지와 동영상 파일이 많았는데, 동영상 일부가 캐시되지 않고 있었다.
CloudFront 캐시 적중률(Cache Hit Ratio)을 확인했더니, S3에서 직접 서빙하는 동영상 파일들이 캐시되지 않았다.
구조:
Amplify (SSR) → CloudFront → 사용자
S3 (정적 파일) → CloudFront → 사용자
Amplify로 배포한 프론트엔드는 정상적으로 캐시됐는데, S3에 올린 동영상/이미지만 문제였다.
CloudFront는 오리진(S3)이 보내주는 Cache-Control 헤더를 보고 캐시 여부를 결정한다.
| 출처 | Cache-Control 헤더 | 캐시 |
|---|---|---|
| Amplify (SSR) | 코드에서 응답 헤더 설정 | ✓ |
| S3 | 설정 안 함 | ✗ |
S3 객체는 메타데이터로 Cache-Control을 설정해야 하는데, 업로드할 때 아무것도 안 넣었던 거다.
flowchart LR
User[사용자] --> CF[CloudFront]
CF --> |캐시 있음| Cache[(Edge Cache)]
CF --> |캐시 없음| S3[(S3 Origin)]
S3 --> |Cache-Control 헤더| CF
style Cache fill:#16a34a,color:#fff
style S3 fill:#3b82f6,color:#fff
HTTP 응답 헤더로, 브라우저와 CDN에게 “이 파일을 얼마나 오래 캐시해도 되는지” 알려준다.
Cache-Control: max-age=86400
→ "이 파일은 86400초(24시간) 동안 캐시해도 됨"
동작:
- S3에서
Cache-Control: max-age=86400헤더가 오면 → CloudFront가 24시간 캐시 - 헤더 없으면 → CloudFront 캐시 정책의 Default TTL에 따름 (CachingOptimized 정책은 24시간이지만, 커스텀 정책에서 Default TTL이 0이면 캐시되지 않음)
- S3 버킷 → 객체 선택
- Actions → Edit metadata
- Add metadata
- Type: System defined
- Key:
Cache-Control - Value:
max-age=31536000(1년)
단일 파일:
|
|
폴더 전체 (재귀):
|
|
특정 확장자만:
|
|
주의: --metadata-directive REPLACE 필수. 없으면 메타데이터가 적용 안 됨.
| 파일 유형 | 권장 max-age | 이유 |
|---|---|---|
| 동영상 (.mp4, .webm) | 31536000 (1년) | 거의 안 바뀜 |
| 이미지 (.jpg, .png) | 31536000 (1년) | 거의 안 바뀜 |
| JS/CSS (버저닝 있음) | 31536000 (1년) | 파일명에 해시 포함 |
| HTML | 0 또는 3600 | 자주 바뀜, 캐시 주의 |
s-maxage vs max-age:
max-age: 브라우저 + CDN 모두 적용s-maxage: CDN만 적용 (브라우저 무시)
CDN에만 오래 캐시하고 브라우저는 짧게 하려면:
Cache-Control: max-age=60, s-maxage=31536000
캐시 설정 후 CloudFront 비용 변화:
| 월 | 비용 | 변화 |
|---|---|---|
| 10월 | $4,317 | - |
| 11월 | $4,008 | -7% |
약 7% 절감. 기대만큼 드라마틱하진 않았다. 예상 원인:
- 배포할 때마다 CloudFront invalidation을 실행해서 캐시 보존 기간이 짧았을 수 있음
- 사용자 재방문 주기가 길어서 캐시 효과가 제한적이었을 수 있음
그래도 월 $300 정도 절감 효과는 있었다.
업로드 시점에 메타데이터를 넣어야 한다. 나중에 수정하려면 파일을 자기 자신에게 복사하는 방식이라 번거롭다.
S3 sync 예시:
|
|
| 항목 | Amplify | S3 |
|---|---|---|
| 캐시 헤더 설정 | 코드에서 응답 헤더 | 객체 메타데이터 |
| 설정 시점 | 런타임 | 업로드 시 |
| 변경 용이성 | 배포하면 적용 | 객체별로 수정 필요 |
| 항목 | 확인 |
|---|---|
| S3 정적 파일에 Cache-Control 메타데이터 설정 | ☐ |
| 동영상/이미지는 max-age 길게 (1년) | ☐ |
| HTML은 max-age 짧게 또는 0 | ☐ |
| 업로드 스크립트에 –cache-control 옵션 추가 | ☐ |
| CloudFront 캐시 적중률 모니터링 | ☐ |