❗ 잘못된 TTL 설정 = CloudFront가 자주 S3에 요청 = S3 요금↑, 응답 속도↓
→ 해당 프로젝트에서는 이미지 변경이 없으므로, CloudFront에서 TTL을 1년으로 명시적으로 고정함
항목 | 설정 |
---|---|
CloudFront 캐시 | TTL 1년 (CachePolicy-Thumbnail-1y ) |
업로드 시 Cache-Control | 설정하지 않음 |
파일명 | UUID 기반 랜덤 → 경로 중복 없음 |
iOS 앱 로컬 캐시 | TTL 짧게 가져가서 디스크 부담 최소화 |
이미지 변경 | 없음 (기존 파일 덮어쓰기 없음) |
정확히는 "immutable 헤더는 없음", 하지만 동작은 비슷하게 흘러감
비교 항목 | 현재 구조 | immutable 전략 |
---|---|---|
TTL 설정 | CloudFront 정책 기반 | Cache-Control: max-age, immutable |
클라이언트 헤더 | 없음 | 명시적 설정 필요 |
invalidate 필요 | 없음 | 없음 |
효과 | 사실상 동일 | 동일 |
📌 정리하자면: 기술적으로는 immutable은 아니지만, 실질적인 캐시 효율은 같다
URLCache
는 TTL이 길수록 디스크에 오래 저장함→ 그래서 로컬 캐시는 짧게 유지
→ 필요 시 CloudFront에서 다시 받아옴 (속도 문제 없음)
CDN 캐시 요금 관련
캐시가 많다고 요금이 올라가는 게 아님 캐시를 못 쓰면 요금이 올라감
구분 요금 발생 여부 캐시 저장 공간 ❌ 없음 데이터 전송 ✅ 있음 (캐시든 S3든) 요청 수 ✅ 있음 (10,000건당 과금) CloudFront Functions 등 ✅ 있음 (별도 과금) 실수 주의: Cache-Control 헤더
업로드할 때 잘못된 Cache-Control 붙이면, CloudFront는 그걸 응답 헤더로 인식함
PUT /image.png HTTP/1.1 Cache-Control: no-store
→ 이게 객체 메타데이터로 저장됨
→ CloudFront는 응답 시 이 헤더 따라감
→ 캐시 안 됨, 매번 S3로 요청 감
→ 업로드 시 Cache-Control 아예 안 붙이는 게 전략적으로 안전함
CloudFront > Behaviors(동작) > 편집
캐시 키 및 원본 요청 > Create Cache Policy
CloudFront의 새로운 캐시 설정은 총 3가지 정책 기반 구성으로 나뉜다.
설명 | |
---|---|
Cache Policy | 어떤 요청을 캐시 키로 사용할지, 그리고 TTL을 얼마나 설정할지 |
Origin Request Policy | 캐시에 없어서 원본(S3)에 요청할 때, 어떤 헤더, 쿼리, 쿠키를 전달할지 |
Response Headers Policy | CDN이 응답을 보낼 때 어떤 HTTP 헤더를 강제로 추가할지 (옵션) |
Cache policy > “Create cache policy” 클릭
CachePolicy-Thumbnail-1y
31536000
(default/max), 0
(min)항목 | 의미 |
---|---|
Min TTL | 캐시가 최소한 무조건 유지돼야 하는 시간 |
Default TTL | Cache-Control 없을 때, CloudFront가 기본으로 유지할 시간 |
Max TTL | Cache-Control 에서 아무리 길게 줘도 이 시간을 넘기지는 못함 |
Min TTL = 0 으로 설정하는 이유는?
TTL이 남아 있어도 강제 invalidate 또는 변경 요청 시 바로 반영되게 하려는 안전장치
- 99.9%는 1년 동안 캐시되게 놔두되,
- 0.1%라도 강제로 바꾸고 싶을 때 (ex. 실수로 파일 잘못 올림),
- Min TTL이
0
이면 → 바로 CloudFront가 새로 요청 가능함Min TTL = 캐시 강제 최소 유지 시간인데, 만약 이걸
1초
이상으로 설정해버리면?❗ CloudFront는 그 시간 동안 "무조건 캐시된 것만 사용"하고,
ETag/If-Modified-Since 등 변경 여부 확인도 안 함.
문제 되는 시나리오:
- 원래는 TTL 1년 줬지만,
- 나중에 뭐가 잘못돼서 invalidate 시도하거나, 파일 바꾸고 다시 업로드했는데도,
- Min TTL이 1 이상이면 캐시가 무조건 남아있음.
즉, CloudFront가 원본에 다시 확인도 안 해버림
위와 같이 캐시 키 및 원본 요청 설정 > 변경 사항 저장
항목 | 설정 값 |
---|---|
Cache policy | CachePolicy-Thumbnail-1y (직접 생성한 TTL 1년짜리 정책) |
Origin request policy | None (정적 파일이라 전달할 헤더 없음) |
Response headers policy | None (보안/헤더 커스터마이징 안 한다면 불필요) |
Cache-Control
헤더 주의CloudFront는 S3 객체의 Cache-Control 응답 헤더를 그대로 따른다.
즉, 이미지 업로드할 때 붙이는 헤더 하나가 CloudFront 캐시 정책 전체에 영향을 줄 수 있다.
Cache-Control
헤더는 따로 지정하지 않는다이렇게 하면 업로드 실수로 캐시 꼬일 일이 없음.
Cache-Control
헤더는 뭐길래 이렇게 중요할까?브라우저뿐 아니라, CloudFront 같은 CDN도 이 헤더를 보고 캐시 전략을 정한다.
공식 스펙(RFC 9111)에서도 다음과 같이 정의돼 있음: “Cache-Control은 요청/응답 체인에 있는 모든 캐시들에 적용된다.”
즉, 다음 대상이 모두 이 헤더를 따라 움직인다는 얘기:
- 브라우저
- 중간 프록시
- CDN (CloudFront 포함)
- 모바일 앱의 URLCache 등
결론
구분 영향 받음? 설명 CloudFront 캐시 ✅ S3 응답 헤더의 Cache-Control을 기반으로 TTL 계산 iOS 앱 캐시 ✅ URLSession이 응답 헤더를 기준으로 로컬 저장 판단 클라이언트 요청 헤더 ❌ 서버 응답에는 영향 없음 (단, S3 업로드 시 예외)
Cache-Control
은 CDN, 브라우저, 앱까지 모두 영향을 주는 헤더https://cdn.example.com/images/user/thumbs/9d0a3f90e8.png
이 방식을 유지하면:
즉, 파일명이 바뀌면 이미지도 완전히 새로운 리소스로 인식되기 때문에, 캐시 전략을 강하게 가져가도 전혀 문제 없다.
현재 구조는 다음 조건을 모두 만족하고 있다
이 말인즉슨, 캐시 무효화 정책을 아예 운영하지 않아도 된다.
만약 같은 URL에 다른 이미지를 덮어쓰는 구조였다면 CloudFront invalidation API를 사용해야 했을 거야.
하지만 지금은 그럴 일이 없으니, 운영 부담 자체가 사라진다.