no-cache 를 줬더니 CDN 이 놀고 있었다
배포하면 사람들이 바로 새 화면을 보게 하려고 JS, CSS, HTML 에 Cache-Control: no-cache 를 주었다. 이렇게 하면 브라우저가 쓰기 전에 항상 서버에 확인한다. 안전하지만 대가가 있었다.
CDN 은 전 세계 여러 곳에 파일 사본을 두고 가까운 곳에서 보내 주는 서비스다. Firebase Hosting 은 CDN 을 앞에 두고 있어서, 사본이 있으면 원본 서버까지 가지 않고 CDN 이 바로 답한다. 브라우저가 이미 받은 파일이 바뀌었는지 묻는 요청(조건부 요청)에는 바뀌지 않았다는 뜻의 304 로 짧게 답할 수 있다. 이때 본문은 다시 보내지 않는다.
no-cache 는 저장하지 말라는 뜻이 아니라 쓰기 전에 확인하라는 뜻이다. 브라우저는 조건부 요청을 보낸다. 파일이 바뀌지 않았으면 서버가 304 로 답해서 본문을 다시 보내지 않아도 되는 것이 원래 흐름이다.
그런데 Firebase Hosting 의 CDN 은 no-cache 응답을 저장하지 않는다. 그래서 조건부 요청이 와도 원본까지 가서 매번 200 으로 전체 파일을 돌려보냈다. 확인해 보니 304 가 거의 없고 CDN 에서는 캐시 미스가 계속 났다. 파일이 바뀌지 않아도 같은 JS 와 CSS 를 사람마다 매번 전체 받고 있었다.
원하는 동작은 이랬다. 브라우저는 쓸 때마다 서버에 확인한다(항상 최신). 그 확인에는 CDN 이 304 로 대신 답한다(원본까지 가지 않음). 그래서 헤더를 이렇게 바꿨다.
Cache-Control: public, max-age=0, s-maxage=604800
max-age=0 은 브라우저에게 저장은 하되 매번 확인하라는 뜻이고, s-maxage=604800 은 공유 캐시(CDN)가 최대 일주일 저장해도 된다는 뜻이다. public 은 CDN 이 저장해도 되는 응답이라는 표시다.
배포하면 예전 파일이 남지 않을까
CDN 이 일주일 저장하면 배포 후에도 예전 파일이 나갈 것 같지만, 배포할 때 Firebase 가 CDN 에 저장된 것을 비운다. 그래서 새 배포가 바로 반영된다.
참고한 문서
- MDN, Cache-Control: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
- MDN, 304 Not Modified: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/304
- MDN, ETag: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag
- Jake Archibald, Caching best practices & max-age gotchas: https://jakearchibald.com/2016/caching-best-practices/
- Firebase, Hosting 캐시 관리: https://firebase.google.com/docs/hosting/manage-cache
다른 글
- 배포했는데 한 시간 동안 예전 페이지가 보였다 2026년 10월 25일
- 구름이 닿지 않는 판은 왜 나오지 않을까 2026년 10월 25일
- 밟으면 사라지는 구름은 길에 놓지 않았다 2026년 10월 25일
- 바탕을 지웠는데 분홍 띠가 남았다 2026년 10월 25일
- 하루에 세 번 바꾼 배포 제외 규칙 2026년 10월 25일
