
Core Web Vitals는 구글이 웹 사용자 경험을 정량화하기 위해 정의한 핵심 성능 지표다. 이 지표는 실제 사용자 경험을 직접적으로 반영하며 검색 순위(SEO)에도 영향을 미친다. 프론트엔드 개발자는 필수적으로 이해하고 지속적으로 관리해야 한다.
Core Web Vitals는 세 가지 지표로 구성된다.
| 지표 | 의미 | 권장 기준 | 주의 구간 |
|---|---|---|---|
| LCP (Largest Contentful Paint) | 가장 큰 콘텐츠가 화면에 보이기까지의 시간 | ≤ 2.5s | 2.5s ~ 4.0s |
| INP (Interaction to Next Paint) | 사용자 상호작용 후 다음 페인트까지의 지연 | ≤ 200ms | 200ms ~ 500ms |
| CLS (Cumulative Layout Shift) | 예기치 않은 레이아웃 이동의 누적량 | ≤ 0.1 | 0.1 ~ 0.25 |
preload를 적용한다.srcset/sizes를 사용한다. 히어로 이미지는 지연 로드를 피한다.font-display: swap을 적용하고 필요한 글자만 서브셋 처리하며 폰트를 preload한다.<link rel="preload" as="image" href="/hero.jpg" imagesrcset="/hero.jpg 1x, /hero@2x.jpg 2x" imagesizes="100vw">
<link rel="preload" as="font" href="/fonts/inter.woff2" type="font/woff2" crossorigin>
/* FOIT 방지용 폰트 표시 전략 */
@font-face {
font-family: 'Inter';
src: url('/fonts/inter.woff2') format('woff2');
font-display: swap;
}
setTimeout(0) 또는 requestIdleCallback로 위임한다.transform/opacity를 우선 사용한다.// 긴 배열 처리 시 이벤트 반응성을 확보하기 위한 단순 작업 분할 예시
function processInChunks<T>(items: T[], chunkSize: number, handle: (chunk: T[]) => void) {
for (let i = 0; i < items.length; i += chunkSize) {
const chunk = items.slice(i, i + chunkSize);
setTimeout(() => handle(chunk), 0);
}
}
width/height 또는 aspect-ratio를 명시한다.font-display: swap을 적용하고 FOUT를 허용하며 폴백 폰트는 메트릭 유사 폰트를 사용한다.top/left/width/height 대신 transform을 사용한다./* 레이아웃 이동 방지 */
img {
aspect-ratio: 16 / 9;
width: 100%;
height: auto;
display: block;
}
npm i web-vitals
// vitals.ts
import { onCLS, onINP, onLCP, Metric } from 'web-vitals';
export function initWebVitals(report: (metric: Metric) => void) {
onCLS(report);
onINP(report);
onLCP(report);
}
// App.tsx
import { useEffect } from 'react';
import { initWebVitals } from './vitals';
export default function App() {
useEffect(() => {
initWebVitals((metric) => {
// 서버로 전송하여 대시보드로 집계한다.
navigator.sendBeacon('/analytics', JSON.stringify({
name: metric.name,
value: metric.value,
rating: metric.rating,
}));
});
}, []);
return (
<div>...</div>
);
}
preload와 적절한 포맷(AVIF/WebP)을 적용하고, 비핵심 이미지는 지연 로드한다.preload하고 font-display: swap을 적용한다. 폰트 종류와 가중치는 최소화한다.preconnect와 dns-prefetch로 외부 리소스 초기 지연을 줄인다.<link rel="preconnect" href="https://example-cdn.com" crossorigin>
<link rel="dns-prefetch" href="https://example-cdn.com">
preload하여 네트워크 병목을 유발한다.preload를 적용했다.preload와 font-display: swap을 적용하고 서브셋을 구성했다.width/height 또는 aspect-ratio를 지정했다.