아래는 실제 운영에서 가장 빨리 효과를 보는 순서로 정리한 점검 루트입니다.
1) 문제 징후: LCP만 튀고 TTFB도 함께 증가한다
가장 먼저 “서버가 느려진 건지, CDN 캐시가 안 붙는 건지”를 분리해야 합니다. Chrome에서 대략적인 체감이 아니라, 요청 단위로 확인하면 원인이 빠르게 보입니다.
- 증상 패턴: LCP가 악화되면서 TTFB도 같이 증가(초반 응답이 늦음)
- 주로 의심: Cloudflare 캐시 미스/우회, 캐시 키 문제, HTML/이미지 캐시 정책 불일치
Chrome(DevTools)에서 빠르게 확인
- Network 탭에서 문서(HTML) 요청을 선택하고 Response Headers의 cf-cache-status를 확인합니다.
- HIT이면 CDN 캐시에서 나간 것, MISS/DYNAMIC/BYPASS면 원서버까지 갔을 가능성이 큽니다.
- Timing에서 Waiting (TTFB)가 길면, 초기 응답이 병목일 확률이 높습니다.
2) 원인: 캐시가 “안 먹는 게 정상”인 조건을 스스로 만들어 둔 경우
Cloudflare를 켰는데도 HTML이 계속 DYNAMIC으로 찍히거나, 특정 쿼리스트링/쿠키 때문에 캐시가 계속 분리되는 일이 흔합니다. Core Web Vitals 관점에서는 “매 방문마다 원서버 생성”이 되면 LCP에 바로 타격이 옵니다.
- Cache-Control이 no-store/no-cache/private로 내려가서 캐시가 포기되는 경우
- 페이지 URL에 불필요한 쿼리스트링(utm 등)이 붙어 캐시가 쪼개지는 경우
- HTML 응답이 사용자별 Set-Cookie를 과도하게 내려 캐시 전략을 망치는 경우
- Cloudflare Rules(캐시 규칙/리다이렉트/Transform Rules) 변경 직후, 일부 경로만 캐시가 깨진 경우
3) 해결: “HTML은 가볍게, 정적 리소스는 길게” 캐시를 다시 잡는다
성능 목적이라면 캐시는 한 번에 “전부 캐시”가 아니라, HTML/정적 파일을 분리해서 정책을 만드는 게 안전합니다. HTML은 너무 공격적으로 캐시하면 운영 리스크가 생기니, 우선은 정적 리소스부터 확실히 안정화하는 게 좋습니다.
- 정적 리소스(이미지/CSS/JS/폰트): 파일명 해시(버전) 전략이 있다면 Cache-Control: max-age를 길게 설정합니다.
- HTML: 로그인/개인화가 없다면 짧은 max-age + stale-while-revalidate를 고려합니다(가능한 서버/프레임워크 범위 내에서).
- 쿼리스트링 정리: 캐시 분리를 유발하는 파라미터는 Cloudflare에서 무시하거나, 아예 URL을 정리(리다이렉트)합니다.
- 불필요한 Set-Cookie 줄이기: 전 페이지 공통으로 쿠키를 뿌리는 코드를 먼저 의심합니다(특히 마케팅/AB 테스트 스크립트).
체크리스트(운영 안전 버전)
- 정적 리소스 응답에 cf-cache-status가 HIT로 안정적으로 찍히는가
- 동일 리소스가 방문 때마다 ETag/Last-Modified 협상만 하고 실제 다운로드는 줄었는가
- HTML이 캐시되지 않더라도, LCP 이미지/폰트는 캐시로 커버되는가
4) 문제 징후: LCP 요소가 “이미지”인데 다운로드가 늦게 시작한다
LCP가 이미지인 경우, “이미지 자체 용량”보다 “언제 요청을 시작하느냐”가 더 크게 작용합니다. Cloudflare 캐시가 HIT인데도 LCP가 느리면, 브라우저가 이미지를 늦게 발견하는 레이아웃/마크업 구조일 수 있습니다.
- HTML 파싱 중 이미지가 늦게 등장(슬라이더/템플릿 하단 삽입)
- lazy-loading이 LCP 이미지에도 적용되어 시작이 늦어짐
- CSS background-image로 큰 히어로를 넣어, 발견이 늦어짐
5) 해결: LCP 이미지 전달을 “작게 + 빨리 + 우선”으로 바꾼다
Cloudflare 환경에서는 이미지 최적화 옵션(예: Polish/Mirage, 플랜/구성에 따라 상이)도 도움이 되지만, 그보다 먼저 “프론트에서 LCP 이미지를 우선순위로 만든다”가 가장 재현성이 좋습니다.
- 크기: 실제 표시 크기에 맞춘 리사이즈(srcset/sizes) 적용
- 포맷: WebP/AVIF 가능하면 사용(호환성 고려)
- 우선순위: LCP 이미지에는 lazy-load를 피하고, 필요 시 preload 또는 fetchpriority를 검토
- 배치: 가능한 한 HTML 상단에서 빨리 발견되게 구조 조정
또한 캐시 관점에서는 LCP 이미지가 Cloudflare에서 HIT로 나가고, 브라우저 캐시도 충분히 활용되는지(적절한 Cache-Control) 같이 봐야 합니다.
6) 원인/해결: 폰트 때문에 렌더가 늦어져 LCP가 밀리는 경우
LCP가 텍스트(헤딩/히어로 카피)인 페이지에서 자주 보입니다. 폰트가 늦게 로드되면 FOIT/FOUT가 길어지고, 그 결과 LCP 타이밍이 뒤로 밀릴 수 있습니다.
- 원인: 폰트 파일 캐시가 짧거나, CORS/Content-Type 문제로 폰트가 재시도/차단되는 경우
- 원인: @import 체인, CSS가 늦게 도착해 폰트 요청이 늦게 시작되는 경우
- 해결: font-display: swap 적용, 필요한 굵기만 사용, 폰트 파일 캐시 기간을 길게
- 해결: 폰트는 동일 도메인 또는 일관된 CDN 경로로 제공하고, 응답 헤더를 표준으로 유지
7) 재검증: Chrome에서 “LCP가 빨라졌는지”를 같은 조건으로 다시 측정한다
개선 작업 후에는 “좋아진 것 같음”이 아니라, 동일 조건에서 수치를 다시 잡아야 합니다. 특히 Cloudflare는 엣지 캐시가 퍼지는 데 시간이 걸릴 수 있어, 테스트 환경을 통제하는 게 중요합니다.
- 캐시 상태 고정: 반복 새로고침으로 cf-cache-status가 HIT인지 확인한 뒤 측정(정적 리소스 기준)
- 측정 도구: Chrome DevTools Performance/Lighthouse로 LCP 요소와 타이밍을 확인
- 변수 제거: 확장프로그램 비활성화, 시크릿 모드 활용, 네트워크 조건(Throttling) 고정
- 핵심 확인: LCP 요소가 무엇인지(이미지/텍스트), 요청 시작 시점이 앞당겨졌는지
추가로, Cloudflare에서 설정을 건드린 직후라면 Purge(필요한 범위만) 후에 다시 HIT가 형성되는지까지 확인하면 재발을 줄일 수 있습니다.
마무리
Cloudflare CDN을 쓰면서 LCP가 나빠질 때는 “CDN이 느리다”라기보다, 캐시가 비정상적으로 비켜가거나(LCP를 서버 생성에 의존), LCP 리소스(이미지/폰트)의 우선순위가 뒤로 밀리는 경우가 대부분입니다.
위 순서대로 cf-cache-status/TTFB → LCP 리소스 우선순위 → 이미지/폰트 캐시를 정리하면, Core Web Vitals 관점에서 체감 개선이 빠르게 나오는 편입니다.