Ray Book
프론트엔드 성능 최적화

성능을 측정하라, Core Web Vitals

LCP, INP, CLS, 사용자 경험을 숫자로 측정하는 세 가지 핵심 지표를 시각화합니다

performancecore-web-vitalslcpinpclslighthouse

핵심 질문

"이 페이지가 빠른가, 느린가"를 어떻게 숫자로 증명할 수 있는가?

"체감상 빠르다"는 근거가 될 수 없습니다. 성능 개선의 첫 단계는 측정입니다. Google은 사용자 경험을 대표하는 세 가지 핵심 지표, LCP , INP , CLS , 를 Core Web Vitals로 정의하고, 이를 검색 순위에 반영합니다.

왜 측정해야 하는가

성능은 비즈니스에 직접적인 영향을 미칩니다.

  • 로딩이 1초 느려지면 전환율이 7% 떨어진다는 연구 결과가 있습니다
  • Google은 Core Web Vitals를 페이지 경험 신호 에 포함하여 검색 순위에 반영합니다
  • 느린 페이지는 사용자 이탈률을 높이고, SEO 점수를 낮춥니다

측정 없이는 개선이 불가능합니다. "어디가 느린지" 모르면 "무엇을 고쳐야 하는지"도 알 수 없습니다.

LCP, Largest Contentful Paint

LCP는 뷰포트에서 가장 큰 콘텐츠 요소가 렌더링 완료된 시점을 측정합니다. "사용자가 주요 콘텐츠를 볼 수 있게 된 순간"을 나타내는 로딩 지표 입니다.

LCP 후보가 되는 요소:

  • <img> 요소
  • <video> 요소의 포스터 이미지
  • CSS background-image로 로드한 이미지
  • 텍스트 노드를 포함하는 블록 레벨 요소
등급임곗값
Good2.5초 이하
Needs Improvement2.5초 ~ 4.0초
Poor4.0초 초과

LCP를 개선하는 핵심 전략:

  1. 서버 응답 시간 줄이기 , TTFB (Time to First Byte) 가 느리면 모든 지표가 밀립니다
  2. 렌더 차단 리소스 제거 , 불필요한 동기 CSS/JS를 제거하거나 defer/async 처리
  3. LCP 리소스를 preload , <link rel="preload">로 브라우저가 일찍 발견하게 합니다
  4. 이미지 최적화 , WebP/AVIF 포맷, 적절한 크기, CDN 배포

INP, Interaction to Next Paint

INP 는 사용자의 인터랙션 (클릭, 탭, 키 입력) 에 대해 브라우저가 다음 프레임을 그리기까지의 지연 시간을 측정합니다. 2024년 3월, 기존의 FID (First Input Delay) 를 대체했습니다.

FID는 첫 번째인터랙션의 입력 지연만 측정했습니다. INP는 페이지 전체 수명 동안 발생하는 모든 인터랙션을 추적하고, 그중 가장 느린 값 (또는 상위 백분위) 을 대표값으로 사용합니다.

등급임곗값
Good200ms 이하
Needs Improvement200ms ~ 500ms
Poor500ms 초과

INP를 구성하는 세 구간:

  1. Input delay , 이벤트 핸들러가 실행되기까지의 대기 시간 (메인 스레드가 바쁜 경우)
  2. Processing time , 이벤트 핸들러의 실행 시간
  3. Presentation delay , 렌더링이 완료되어 다음 프레임이 그려지기까지의 시간

INP를 개선하는 핵심 전략:

  1. 긴 작업 쪼개기 , 50ms 이상의 Long Task를 scheduler.yield() 또는 setTimeout으로 분할
  2. 불필요한 리렌더링 방지 , React의 useMemo, useCallback, memo
  3. 메인 스레드 부하 줄이기 , 무거운 연산은 Web Worker로 이동

CLS, Cumulative Layout Shift

CLS 는 페이지 로드 중 예기치 않은 레이아웃 이동의 누적 점수를 측정합니다. 버튼을 누르려는데 갑자기 광고가 삽입되어 잘못된 곳을 클릭한 경험, 그것이 CLS가 잡아내는 문제입니다.

등급임곗값
Good0.1 이하
Needs Improvement0.1 ~ 0.25
Poor0.25 초과

CLS 점수 계산: 영향 비율 (impact fraction) x 거리 비율 (distance fraction) . 뷰포트의 50%를 차지하는 요소가 뷰포트 높이의 25%만큼 이동하면, CLS = 0.5 x 0.25 = 0.125 입니다.

CLS를 개선하는 핵심 전략:

  1. 이미지/비디오에 크기 지정 , width, height 속성 또는 aspect-ratio CSS
  2. 동적 콘텐츠 공간 확보 , 광고, 배너, 폰트 로드 영역에 미리 공간을 예약
  3. 웹 폰트 FOUT 방지 , font-display: swap<link rel="preload">를 함께 사용
  4. transform 애니메이션 사용 , top/left 대신 transform은 레이아웃 시프트를 유발하지 않습니다

시각화, 페이지 로드 타임라인

아래 시각화는 페이지가 로드되는 과정에서 각 Core Web Vitals 지표가 어느 시점에 측정되는지 보여줍니다.

NavigationNavigation Start1 / 5
Navigation
FCP
LCP
INP
CLS
blank

사용자가 URL을 입력하거나 링크를 클릭한 순간 — 모든 측정의 기준점입니다. 아직 화면에는 아무것도 보이지 않습니다.

측정 도구

Lighthouse

Chrome DevTools에 내장된 성능 감사 도구입니다. Lab 데이터 (제어된 환경) 를 제공합니다.

# CLI로 실행
npx lighthouse https://example.com --output html --output-path report.html

Lab 데이터는 네트워크 속도, 디바이스 성능을 시뮬레이션하므로 실제 사용자 환경과 다를 수 있습니다. 개발 중 빠른 피드백에 유용합니다.

Chrome DevTools Performance 패널

실제 페이지 로드를 녹화하여 메인 스레드 활동, 레이아웃 시프트, Long Task 등을 타임라인으로 분석합니다. INP 디버깅에 특히 유용합니다.

web-vitals 라이브러리

실제 사용자 환경 (Field 데이터) 에서 Core Web Vitals를 측정합니다.

import { onLCP, onINP, onCLS } from "web-vitals";

onLCP(console.log);   // Largest Contentful Paint
onINP(console.log);   // Interaction to Next Paint
onCLS(console.log);   // Cumulative Layout Shift

측정된 데이터를 분석 서비스 (Google Analytics, 자체 엔드포인트) 로 전송하면 실제 사용자의 75번째 백분위 수 (p75) 를 기준으로 성능을 평가할 수 있습니다.

Chrome UX Report (CrUX)

Google이 수집하는 실제 사용자 데이터입니다. PageSpeed Insights와 Search Console에서 확인할 수 있습니다. 28일간의 p75 데이터 를 기준으로 하므로, 배포 후 효과를 확인하려면 시간이 필요합니다.

체크리스트

  • LCP 2.5초 이하, INP 200ms 이하, CLS 0.1 이하를 목표로 설정했는가
  • web-vitals 라이브러리로 Field 데이터를 수집하고 있는가
  • Lighthouse CI를 배포 파이프라인에 통합했는가
  • LCP 요소를 식별하고 preload를 적용했는가
  • 이미지에 width/height 또는 aspect-ratio를 지정했는가
  • Long Task를 50ms 이하로 분할했는가

다음 글에서는

성능을 측정하는 방법을 알았으니, 다음 글에서는 가장 직접적인 병목, 번들 크기 를 다룹니다. 코드 스플리팅, 트리 쉐이킹, 압축으로 네트워크 전송량을 줄이는 전략을 시각화합니다.