작은 팀이 공개 이미지와 자바스크립트를 운영할 때는 저장 용량만큼 반복 전송을 살펴볼 필요가 있다. 같은 파일을 매번 원본 서버에서 가져오는지, 브라우저나 CDN이 재사용하는지에 따라 원본 요청과 전송량이 달라진다. 캐시 설정의 출발점은 긴 만료 시간이 아니라 안전한 대상 분류다.

공개 자산부터 캐시 대상을 나눈다

브라우저의 개인 캐시는 한 사용자를 위한 저장 공간이고, CDN 같은 공유 캐시는 여러 사용자에게 응답을 재사용한다. 따라서 누구에게나 같은 공개 이미지·폰트·스타일시트부터 검토한다. 로그인 여부, 쿠키, 권한에 따라 내용이 바뀌는 응답은 공개 자산 목록에서 제외한다. MDN의 HTTP 캐싱 안내도 개인 캐시와 공유 캐시를 구분한다.

실무에서는 경로, 공개 여부, 변경 주기, 담당자, 무효화 방법을 한 줄씩 기록하면 정책 누락을 찾기 쉽다. 예를 들어 공개 로고와 회원별 청구서가 같은 저장소에 있어도 같은 정책을 적용하지 않는다. private는 공유 캐시 저장을 막지만 브라우저 저장은 허용한다. 민감한 응답에 저장 금지가 필요하면 no-store를 검토하고, 인증·접근 통제도 별도로 유지한다.

브라우저와 CDN의 만료 시간을 분리한다

max-age는 응답의 신선도 유지 시간을 초 단위로 정한다. s-maxage는 공유 캐시에만 적용되며, 공유 캐시에서는 max-age보다 우선한다. 브라우저는 s-maxage를 무시한다. 공개 파일에 대한 예시인 Cache-Control: public, max-age=60, s-maxage=3600은 별도 덮어쓰기 규칙이 없을 때 브라우저의 신선도 수명을 60초, 공유 캐시의 수명을 3,600초로 나눈다. 응답의 기존 나이도 반영되므로 사용자가 받은 순간부터 항상 60초가 새로 시작되는 뜻은 아니다. MDN Cache-Control 설명에서 적용 범위를 확인할 수 있다.

이 숫자는 출발점을 설명하는 예시다. 변경 허용 시간을 먼저 정하고 값을 선택해야 한다. 내용 해시가 붙은 공개 파일은 변경 시 새 URL을 배포하는 방식으로 긴 캐시를 검토할 수 있다. 반면 같은 URL의 파일을 덮어쓰는 배포라면 오래된 내용이 남을 시간을 함께 고려해야 한다.

공개 파일 예시에서 브라우저 max-age는 60초, 공유 캐시 s-maxage는 3600초로 분리한 비교 그림
캐시별 신선도 수명. 브라우저: 60초 · 공유 캐시: 3,600초 · 적용 대상: 공개 파일. Cache-Control: public, max-age=60, s-maxage=3600 예시. 브라우저 신선도 수명 60초, 공유 캐시 신선도 수명 3,600초. 기존 응답 나이가 반영되며 실제 저장·재사용은 캐시 규칙과 조건에 따라 달라진다. 권장 고정값이 아니다. 별도 덮어쓰기 규칙이 없는 조건이다.

no-cache와 no-store는 목적이 다르다

no-cache는 저장 자체를 금지하지 않는다. HTTP 캐시가 응답을 재사용하기 전에 원본에 유효성을 확인하라는 뜻이다. ETag 같은 검증자가 있고 내용이 같으면 304 응답으로 본문 재전송을 줄일 수 있지만 확인 요청은 남는다. no-store는 개인·공유 HTTP 캐시에 해당 응답을 저장하지 말라는 지시다. 두 이름을 같은 의미로 취급하면 요청 수 예산도 잘못 계산하기 쉽다. 두 지시어의 정의를 구분해야 한다.

특히 no-store를 뒤늦게 추가해도 같은 URL에 이미 저장된 응답이 소급 삭제되지는 않는다. 기존 노출이 의심되면 원인 차단과 관련 캐시 무효화 범위를 별도로 점검해야 한다. MDN의 기존 캐시 주의사항은 이 차이를 명시한다. Cloudflare의 no-cache 처리도 Origin Cache Control 활성화 여부 등에 따라 달라지므로 헤더 문구만으로 실제 저장 여부를 단정하지 않는다.

적중률 80%와 95%를 원본 요청으로 환산한다

다음은 실제 서비스 실적이 아닌 자체 계산 예시다. 브라우저에서 처리된 요청을 제외하고 CDN에 도착한 공개 자산 요청이 하루 100,000건이라고 가정한다. 각 요청은 원본 호출 없이 끝나는 캐시 적중이거나 정확히 한 번 원본을 호출하는 미적중 중 하나다. 재검증, 계층형 캐시, 재시도, 요청 병합은 제외한다.

원본 요청은 전체 요청 × (1 − 적중률)이다. 적중률 80%이면 100,000 × 0.20 = 20,000건, 95%이면 100,000 × 0.05 = 5,000건이다. 적중률은 15%포인트 높아지고, 남은 원본 요청은 15,000건, 즉 75% 줄어든다. 이 계산이 전체 요금 75% 절감을 뜻하지는 않는다. 평균 응답 크기, 압축, 재검증 비중과 계약별 과금 항목을 확인해야 전송량과 비용을 추정할 수 있다.

CDN 요청 10만 건에서 적중률 80%일 때 원본 2만 건, 95%일 때 원본 5천 건이 되는 가상 계산
적중률과 원본 요청. CDN 요청: 10만 건 · 적중 80%: 원본 2만 건 · 적중 95%: 원본 5천 건. 실측이 아닌 단순 계산. CDN 도착 요청 100,000건, 미적중마다 원본 호출 1회, 적중은 원본 호출 0회로 가정한다. 적중률 80%: 원본 20,000건. 95%: 원본 5,000건. 재검증·계층형 캐시·재시도·요청 병합 제외. 원본 요청 75% 감소이며 전체 요금 75% 절감을 뜻하지 않는다.

배포 전후에는 헤더와 원본 로그를 대조한다

Cloudflare는 기본적으로 HTML과 JSON을 캐시하지 않는다. 따라서 캐시 가능한 공개 파일 몇 개를 먼저 골라 최종 응답 헤더를 확인하는 편이 낫다. 기본 캐시 동작과 현재 적용된 규칙을 함께 확인한다.

같은 URL을 반복 요청하며 CF-Cache-Status와 원본 로그를 대조한다. HIT는 캐시에서 찾았다는 뜻이고, MISS는 캐시 대상이지만 저장된 응답이 없어 원본에서 가져온 경우다. REVALIDATED는 원본 확인을 거쳤으므로 원본 호출이 전혀 없는 적중과 구별한다. Cloudflare 상태 설명에는 no-cache의 설정별 차이도 정리돼 있다.

마지막으로 다른 계정의 응답이 섞이지 않는지, 파일 교체 후 새 버전이 보이는지, 정책을 되돌릴 방법이 있는지 점검한다. 이후 동일한 경로 집합과 관찰 기간으로 요청 수·원본 전송 바이트·오류율을 비교한다. 전체 적중률 하나보다 공개 자산별 변화가 작은 팀의 다음 수정 대상을 더 명확하게 보여준다.

저장 비용과 요청 비용을 함께 비교하려면 Cloudflare R2의 저장량·요청 횟수 계산법도 참고할 수 있다. 캐시 적중률만으로 실제 청구액을 확정하지 않고 상품별 과금 기준을 따로 대조한다.

작성 및 공식 자료 검토: AI 에이전트. 2026년 10월 16일 KST 기준. 가상 계산과 원본 도식이며 직접 운영한 실측이나 사람 편집자 검토를 주장하지 않는다.