배포했는데 한 시간 동안 예전 페이지가 보였다
새 버전을 배포했는데 한 시간쯤 예전 게임 목록이 그대로 보이는 일이 있었다. 코드는 맞게 배포되어 있었다. 캐시가 문제였다.
이 사이트는 Firebase Hosting 에 올라가 있다. 브라우저는 받은 파일을 얼마 동안 다시 받지 않고 쓸지를 응답의 Cache-Control 헤더로 정한다. max-age=3600 이면 한 시간 동안 서버에 묻지 않고 저장해 둔 것을 쓴다. 그 사이에 배포로 파일이 바뀌어도 브라우저는 모른다. 그래서 페이지가 바뀌는 사이트는 이 값을 신경 써서 정해야 한다.
Firebase Hosting 에서는 firebase.json 의 headers 에 주소 패턴별로 응답 헤더를 정할 수 있다. HTML, JS, CSS 에 캐시 설정을 주려고 이렇게 적었다.
{ "source": "**/*.@(js|css|html|glb)",
"headers": [{ "key": "Cache-Control", "value": "public, max-age=0, s-maxage=604800" }] }
그런데 이 사이트는 cleanUrls 를 켜서 /ko/games/cloudhop 처럼 확장자 없는 주소를 쓴다. 실제로 열리는 파일은 cloudhop.html 이지만, 패턴은 파일 이름이 아니라 요청한 주소로 고른다. /ko/games/cloudhop 에는 .html 이 없어서 위 규칙에 걸리지 않았다.
규칙에 걸리지 않은 응답에는 Firebase 의 기본 캐시가 붙는다. 기본은 1시간(max-age=3600)이다. 사람들의 브라우저가 한 시간 동안 예전 페이지를 쓰는 것이다. 정작 문제가 된 것은 가장 많이 열리는 페이지(홈, 게임 페이지)가 이 확장자 없는 주소라는 점이었다.
예상하지 못한 일이라 이 문제를 발견하는데 한참이 걸렸다. 큰 문제가 아닐 수 있지만 새로 배포한 것이 나중에야 사용자들에게 적용된다면 여러 문제가 있을 수 있다.
확장자 없는 주소를 따로 잡는 규칙을 추가했다. 점(.)이 없는 모든 주소에 같은 헤더를 준다.
{ "regex": "^[^.]*$",
"headers": [{ "key": "Cache-Control", "value": "public, max-age=0, s-maxage=604800" }] }
이 규칙은 / 와 /ko/games/cloudhop 처럼 점이 없는 주소에 걸리고, 점이 있는 /portal.js 나 /img/logo.png 에는 걸리지 않는다. 앞서 홈에만 따로 두었던 규칙도 이것으로 합쳤다.
헤더 규칙은 보내는 파일의 이름이 아니라 요청 주소로 고른다. 깔끔한 주소를 쓰는 사이트라면 확장자로 규칙을 적어도 대부분의 페이지가 걸리지 않을 수 있다. 헤더를 바꾼 뒤에는 실제 페이지 주소에 대한 응답 헤더를 한 번 확인해 보는 것이 안전하다.
참고한 문서
- MDN, Cache-Control: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
- Firebase, Hosting 설정(headers, cleanUrls): https://firebase.google.com/docs/hosting/full-config
- Firebase, Hosting 캐시 관리: https://firebase.google.com/docs/hosting/manage-cache
다른 글
- 구름이 닿지 않는 판은 왜 나오지 않을까 2026년 10월 25일
- 밟으면 사라지는 구름은 길에 놓지 않았다 2026년 10월 25일
- 바탕을 지웠는데 분홍 띠가 남았다 2026년 10월 25일
- 하루에 세 번 바꾼 배포 제외 규칙 2026년 10월 25일
- 게임 화면에 fps 를 띄우는 열 줄짜리 코드 2026년 10월 25일
