아래는 Cloudflare 포함한 실전 운영 관점에서, 캐시/CDN을 성능에 도움이 되게 정리하는 점검 루트입니다.
1) 증상 먼저 분류하기: “느림”이 아니라 “캐시 정책 충돌”일 때
캐시 이슈는 단순히 서버가 느린 게 아니라, 어디에서 무엇을 얼마나 저장하는지가 꼬여서 생기는 경우가 많습니다. 먼저 증상을 아래처럼 나눠 보면 원인 추적이 빨라집니다.
- HTML만 가끔 옛날로 보인다: Cloudflare HTML 캐시 규칙, origin의 Cache-Control, 쿠키/로그인 구분 문제 가능
- CSS/JS만 반영이 늦다: 파일명 버전 관리(해시), 브라우저 캐시, Cloudflare Edge 캐시 TTL 문제 가능
- 특정 지역/특정 네트워크에서만 다르다: Edge PoP별 캐시 편차, DNS/프록시 상태, 캐시 워밍 영향 가능
- 관리자만 다르게 보인다: 쿠키 존재 시 캐시 우회/비우회 정책 충돌 가능
2) Chrome에서 3단 확인: 브라우저 캐시 vs Cloudflare 캐시 vs Nginx(origin)
운영 중 가장 안전한 접근은 “어디 캐시가 문제인지”를 먼저 분리하는 것입니다. Chrome DevTools에서 아래 순서로 확인하세요.
- DevTools → Network에서 해당 요청을 선택하고 Response Headers 확인
- cache-control, etag, last-modified, age(있으면) 체크
- cf-cache-status 확인: HIT / MISS / EXPIRED / BYPASS / DYNAMIC
- Disable cache(DevTools 상단) 체크 후 새로고침: 브라우저 캐시 영향 제거
해석은 보통 이렇게 합니다.
- cf-cache-status: HIT인데 내용이 오래됨 → Cloudflare Edge 캐시가 오래된 것
- cf-cache-status: BYPASS/DYNAMIC인데 느림 → Cloudflare가 캐시를 안 하고 origin(Nginx)로 매번 가는 구조
- Disable cache를 꺼야만 최신이 보임 → 브라우저 캐시 정책(파일명/TTL)이 핵심
3) Cloudflare에서 캐시를 “잘” 먹이는 기준: HTML과 정적 리소스를 분리
Cloudflare 운영에서 자주 하는 실수는, HTML과 정적 리소스를 같은 감각으로 캐시하려는 겁니다. 실무에서는 보통 다음 원칙이 안전합니다.
- 정적 파일(CSS/JS/이미지): 길게 캐시(예: 7일~1년) + 파일명에 버전(해시) 적용
- HTML(페이지): 원칙적으로 짧게 캐시하거나, 조건부 캐시(로그인/쿠키 제외)로 제한
- /admin, /login, 결제/장바구니: 캐시 금지(또는 BYPASS) 고정
Cloudflare 쪽에서는 “모든 걸 캐시”보다 Cache Rules(또는 Page Rules)로 경로별 정책을 나누는 편이 운영 안정성이 높습니다. 특히 쿠키가 있는 요청을 캐시 대상으로 잡아버리면, 사용자별 페이지가 섞이는 사고로 이어질 수 있으니 조심하세요.
4) Nginx에서 헤더를 정리해 Cloudflare가 오해하지 않게 만들기
Cloudflare는 origin(Nginx)의 응답 헤더를 강하게 참고합니다. 즉, Nginx가 애매한 헤더를 주면 Cloudflare도 애매하게 동작할 수 있습니다. 아래 체크리스트로 “의도”를 명확히 하는 게 핵심입니다.
- 정적 파일에는 명확한 Cache-Control 설정(예: public, max-age)
- HTML에는 상황에 맞는 Cache-Control(예: no-cache 또는 짧은 max-age)
- ETag를 쓸지 말지 결정(중간 캐시가 있을 때는 일관성이 중요)
- gzip/brotli 적용 시 Vary 헤더와 조합 확인(특히 Accept-Encoding)
실전 팁으로는, 정적 파일은 “파일명 버전화 + 장기 캐시”를 기본으로 두고, HTML은 운영 성격에 맞게 보수적으로 가는 게 트러블이 적습니다. (예: 정적 사이트/문서 성격이면 HTML도 캐시 가능, 게시판/개인화가 많으면 HTML 캐시는 신중)
5) “업데이트가 늦게 보임”을 줄이는 운영 루틴: Purge에 의존하지 않기
운영자가 자주 겪는 패턴이 “배포 후 Purge Cache를 눌러야 정상”입니다. 이 상태가 계속되면, 결국 Purge가 누락되는 순간 장애처럼 보이게 됩니다. Purge 의존도를 낮추려면 아래 순서로 구조를 바꾸는 게 좋습니다.
- 정적 파일 파일명에 버전(해시) 적용: 새 파일은 새 URL로 배포되어 캐시 충돌이 줄어듦
- HTML은 짧은 TTL 또는 조건부 캐시: “조금 늦어도 괜찮은 범위”만 캐시
- Cloudflare 캐시 규칙을 경로 기준으로 단순화: 예외가 많을수록 누락/충돌 가능성이 커짐
- 배포 후 확인 루틴을 Chrome 헤더 점검으로 표준화: cf-cache-status, cache-control만 봐도 대부분 판단 가능
6) 성능 개선 루트(캐시/CDN 포함) 최종 점검 체크리스트
- Chrome에서 cf-cache-status가 기대대로 나오나? (정적=HIT 유도, 개인화=우회)
- 정적 파일에 긴 Cache-Control을 주고, 파일명은 버전 관리하는가?
- HTML은 캐시해도 되는 범위만 캐시하고, admin/login은 확실히 제외했나?
- Nginx 응답에 cache-control/etag/last-modified가 일관되게 설정되어 있나?
- 문제 재현 시 DevTools Disable cache로 브라우저 캐시를 분리해 확인했나?
- 배포 절차가 Purge를 누르는 사람에 의존하지 않게 설계되어 있나?
마무리
Cloudflare+Nginx 조합에서 캐시는 성능을 크게 올려주지만, HTML/정적/개인화가 섞이는 순간부터는 “정책 설계”가 필요해집니다. 크롬에서 헤더를 기준으로 캐시 위치를 분리해 보고, 정적 파일은 버전화+장기 캐시로, HTML은 보수적으로 가져가면 운영 스트레스가 확 줄어듭니다.
지금 겪는 증상(특정 URL/확장자/쿠키 유무/지역)을 기준으로 캐시 규칙과 Nginx 헤더를 함께 조정해 보세요.