treeru.com
개발

Core Web Vitals 실전 디버깅 — Chrome DevTools로 CLS, LCP 원인 찾기

2026-02-08
Treeru

PageSpeed Insights에서 "Performance 74점"을 보면 "어디부터 고쳐야 하지?"라는 생각이 듭니다. 점수 아래에 나열된 항목들이 20개가 넘으니까요. 점수를 내리는 진짜 원인을 정확히 찾아야 효율적으로 고칠 수 있습니다.

Chrome DevTools와 몇 가지 도구를 사용해서, CLS는 어떤 요소가 움직이는지, LCP는 어떤 요소가 늦게 그려지는지 정확히 추적하는 방법을 정리했습니다.

DevTools
CLS 추적
Audit
LCP 식별
curl
SSR 분석
확장프로그램
실시간 모니터

1CLS 원인 요소 찾기

PageSpeed 결과에서 CLS가 높다고 나오면, 어떤 요소가 얼마나 움직였는지 알아야 합니다. 세 가지 방법이 있습니다.

방법 1: PageSpeed 감사 항목

PageSpeed 결과 페이지 하단에 "레이아웃 변경 방지" 항목이 있습니다. 여기서 어떤 요소가 CLS를 발생시키는지 확인할 수 있습니다.

// PageSpeed JSON 응답에서 CLS 요소 찾기
// .lighthouseResult.audits["layout-shift-elements"]

{
  "id": "layout-shift-elements",
  "details": {
    "items": [
      {
        "node": {
          "selector": "div.typewriter-container > span",
          "snippet": "<span class=\"text-4xl font-bold\">"
        },
        "score": 0.341  // 이 요소의 CLS 기여도
      },
      {
        "node": {
          "selector": "header > nav > div.auth-section",
          "snippet": "<div class=\"flex items-center\">"
        },
        "score": 0.089
      }
    ]
  }
}

selectorsnippet을 보면 어떤 요소인지 바로 특정할 수 있습니다. score가 높을수록 해당 요소의 CLS 기여도가 큽니다.

방법 2: Performance 탭 Layout Shift

Chrome DevTools Performance 탭에서 더 자세한 분석이 가능합니다:

1Chrome DevTools → Performance 탭 열기
2좌측 상단 녹화 버튼 클릭 → 페이지 새로고침
3로딩 완료 후 녹화 중지
4타임라인에서 분홍색 'Layout Shift' 마커 찾기
5클릭하면 하단 Summary에서 이동한 요소(Moved from/to) 표시

Layout Shift 하이라이트

Performance 녹화 중 Experience 행을 보면 Layout Shift 이벤트가 표시됩니다. 각 이벤트를 클릭하면 어떤 노드가 어디서 어디로 이동했는지 좌표까지 나옵니다. CLS 0.5가 여러 번의 작은 shift인지, 한 번의 큰 shift인지도 구분됩니다.

방법 3: Console에서 직접 관찰

// Console에 붙여넣기 — CLS 실시간 모니터
new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    if (entry.hadRecentInput) continue; // 사용자 입력은 무시
    console.log("Layout Shift:", entry.value.toFixed(4));
    for (const source of entry.sources || []) {
      console.log("  Element:", source.node?.nodeName,
        source.node?.className);
      console.log("  Moved:", source.previousRect, "→",
        source.currentRect);
    }
  }
}).observe({ type: "layout-shift", buffered: true });

2LCP 요소 식별하기

LCP를 개선하려면 먼저 LCP 요소가 뭔지 알아야 합니다. 생각보다 의외의 요소가 LCP일 수 있습니다.

// PageSpeed JSON에서 LCP 요소 확인
// .lighthouseResult.audits["largest-contentful-paint-element"]

{
  "id": "largest-contentful-paint-element",
  "details": {
    "items": [{
      "node": {
        "selector": "div.hero > img",
        "snippet": "<img src=\"/images/hero.avif\" />"
      }
    }]
  }
}

// Console에서도 확인 가능
new PerformanceObserver((list) => {
  const entries = list.getEntries();
  const last = entries[entries.length - 1];
  console.log("LCP Element:", last.element);
  console.log("LCP Time:", last.startTime, "ms");
  console.log("LCP Size:", last.size, "px²");
}).observe({ type: "largest-contentful-paint", buffered: true });

LCP가 이미지가 아닐 수 있다

LCP는 "가장 큰 콘텐츠 요소"입니다. Hero 이미지가 작거나 뒤늦게 나타나면, 큰 텍스트 블록이 LCP가 될 수 있습니다. 특히 motion/react로 이미지에 opacity:0을 넣으면, Lighthouse가 이미지를 건너뛰고 텍스트를 LCP로 잡습니다.

3Performance 탭 활용

Performance 탭의 타임라인에서 Core Web Vitals 이벤트를 한눈에 볼 수 있습니다.

마커색상의미확인 방법
FCP초록첫 콘텐츠 렌더링Timings 행의 초록 마커
LCP초록최대 콘텐츠 렌더링Timings 행의 LCP 마커
Layout Shift분홍레이아웃 변동Experience 행의 분홍 블록
Long Task빨강 줄무늬50ms 이상 메인 스레드 차단Main 행의 빨간 줄무늬 블록

Performance 탭 팁

  • Network throttling 설정: Performance 탭에서도 네트워크 쓰로틀링을 설정할 수 있습니다. "Fast 3G"로 설정하면 PageSpeed의 Mobile 환경과 비슷해집니다.
  • CPU throttling 설정: 톱니바퀴 → CPU: 4x slowdown으로 설정하면 모바일 환경을 시뮬레이션합니다.
  • Screenshots 활성화: 녹화 시 "Screenshots" 체크하면 시점별 화면을 볼 수 있습니다. CLS가 발생하는 순간을 시각적으로 확인 가능합니다.

4curl로 SSR HTML 분석

브라우저에서 보이는 HTML은 JavaScript가 실행된 후의 결과입니다. 서버가 보내는 원본 HTML을 확인하려면 curl을 사용합니다. motion/react의 opacity:0 문제는 브라우저에서 절대 찾을 수 없습니다 — JS가 즉시 바꿔버리니까요.

# SSR HTML에서 opacity:0 찾기
curl -s https://example.com | grep -i "opacity"

# 결과 예시:
# <div style="opacity:0;transform:translateY(60px)">
# → motion/react가 인라인으로 넣은 초기 상태!

# img 태그의 속성 점검
curl -s https://example.com | grep -oP '<img[^>]+>'

# 결과 예시:
# <img src="/hero.avif" width="900" height="1118"
#   fetchpriority="high">
# <img src="/service.webp">  ← loading="lazy" 누락!

# preload 확인
curl -s https://example.com | grep "rel=\"preload\""

# 결과 예시:
# <link rel="preload" href="/hero.avif" as="image">
# <link rel="preload" href="/service.webp" as="image">
#   ↑ 아래 fold 이미지까지 preload되고 있음!

curl로 반드시 확인해야 할 것들

  • opacity:0 인라인 스타일: motion/react가 SSR에서 넣은 초기 상태. LCP를 지연시킵니다.
  • img 태그의 loading 속성: 아래 fold 이미지에 lazy가 있는지 확인.
  • 불필요한 preload: Hero 외 이미지에 preload가 있으면 대역폭 낭비.
  • font-display 값: 웹폰트 CSS에서 swap인지 optional인지 확인.

5Web Vitals 확장 프로그램

Chrome Web Store에서 "Web Vitals"를 검색하면 Google이 만든 공식 확장 프로그램이 있습니다. 설치하면 브라우저 상단에 현재 페이지의 Core Web Vitals가 실시간으로 표시됩니다.

실시간 CLS 모니터링

스크롤하거나 클릭할 때마다 CLS가 누적됩니다. 어떤 인터랙션에서 CLS가 발생하는지 실시간으로 확인 가능합니다.

LCP 요소 하이라이트

확장 프로그램을 클릭하면 현재 LCP 요소가 하이라이트됩니다. 예상과 다른 요소가 LCP일 수 있습니다.

TTFB, FCP, FID 동시 확인

Core Web Vitals 3가지(LCP, CLS, INP)와 FCP, TTFB까지 한눈에 볼 수 있습니다.

Console 로그 옵션

옵션에서 'Console Logging'을 활성화하면 DevTools Console에 상세 정보가 출력됩니다.

6디버깅 체크리스트

PageSpeed 점수가 낮을 때, 순서대로 확인하면 됩니다.

Core Web Vitals 디버깅 순서

CLS가 높을 때

PageSpeed 결과에서 layout-shift-elements 감사 항목 확인 → 어떤 요소인지 특정
해당 요소가 동적으로 크기가 변하는지 확인 (이미지 width/height 누락, 폰트 swap, 동적 콘텐츠)
애니메이션이 transform 대신 top/left/width/height를 변경하는지 확인
Performance 탭 Experience 행에서 Layout Shift 시점 확인

LCP가 느릴 때

PageSpeed에서 LCP 요소 확인 → 이미지인지 텍스트인지 파악
curl로 SSR HTML 확인 → LCP 요소 wrapper에 opacity:0이 있는지 점검
이미지 용량 확인 → AVIF/WebP 변환 여부, 불필요한 크기
preload 확인 → Hero 외 이미지에 preload가 있으면 제거
아래 fold 이미지에 loading='lazy' 있는지 확인

TBT가 높을 때

Performance 탭에서 Long Task(50ms+) 찾기 → 어떤 스크립트가 원인인지 확인
서드파티 스크립트(GA, GTM, 광고) 여부 점검
hydration 시간 확인 → React 컴포넌트 수가 많으면 hydration이 오래 걸림

이 글의 DevTools 기능은 Chrome 120+ 기준이며, 버전에 따라 UI와 기능이 다를 수 있습니다. Web Vitals 확장 프로그램은 Chrome Web Store에서 무료로 설치할 수 있습니다.

T

Treeru

웹 개발, IT 인프라, AI 솔루션 분야의 실무 인사이트를 공유합니다. 기업의 디지털 전환을 돕는 IT 파트너, Treeru입니다.

공유

댓글

(4개)
4.50/ 5

로그인하면 댓글을 작성할 수 있습니다.

2026-02-19
4.554.5

Performance 탭에서 Layout Shift 이벤트를 클릭하면 어떤 노드가 움직였는지 나온다는 거, 팀원들한테 공유했습니다. 디버깅 시간이 확 줄겠네요.

2026-02-16
555.0

Web Vitals 확장 프로그램 깔았는데, 페이지 이동할 때마다 CLS가 실시간으로 보이는 게 신기합니다. 어떤 인터랙션에서 CLS가 발생하는지 바로 잡을 수 있어요.

2026-02-14
454.0

curl로 SSR HTML 확인하는 방법이 제일 유용합니다. opacity:0이 인라인으로 들어가는 걸 브라우저에서는 절대 못 찾거든요. JS가 즉시 바꿔버리니까.

관련 글

© 2026 TreeRU. All rights reserved.

본 콘텐츠의 저작권은 TreeRU에 있으며, 출처를 밝히지 않은 무단 전재 및 재배포를 금합니다. 인용 시 출처(treeru.com)를 반드시 명시해 주세요.