TTFB (Time to First Byte): 서버가 첫 번째 응답 바이트를 보내기까지 걸리는 시간.
FCP (First Contentful Paint): 화면에 처음으로 텍스트나 이미지 같은 콘텐츠가 표시되는 시점.
LCP (Largest Contentful Paint): 화면에서 가장 큰 요소(텍스트 블록, 이미지 등)가 표시되는 시점.
FID (First Input Delay): 사용자가 처음으로 페이지와 상호작용(클릭, 탭 등)했을 때 응답하기까지 걸린 시간.
CLS (Cumulative Layout Shift): 페이지 로딩 중 레이아웃이 예기치 않게 움직이는 정도를 측정하는 지표.
INP (Interaction to Next Paint): 사용자가 입력(클릭, 키 입력 등)한 후 다음 화면 업데이트가 완료되기까지 걸린 시간.
useReportWebVitals((m) => {
// m.name: 'FCP' | 'LCP' | 'CLS' | 'INP' | 'TTFB' | 'FID' 등
console.log(`[WebVitals] ${m.name}`, m.value, m);
});
<div>123</div>;
---- 콘솔 값 ---
{
"name": "FCP",
"value": 472,
"rating": "good",
"delta": 472,
"entries": [
{
"name": "first-contentful-paint",
"entryType": "paint",
"startTime": 472,
"duration": 0
}
],
"id": "v4-1756182372462-2445471802253",
"navigationType": "reload"
}
const [show, setShow] = useState(false);
useReportWebVitals((m) => {
// m.name: 'FCP' | 'LCP' | 'CLS' | 'INP' | 'TTFB' | 'FID' 등
console.log(`[WebVitals] ${m.name}`, m.value, m);
});
useEffect(() => {
// 2초 뒤에야 첫 콘텐츠 노출
const end = performance.now() + 2000;
while (performance.now() < end) {}
setShow(true);
}, []);
return <div>{show ? <h1>첫 콘텐츠</h1> : null}</div>;
{
"name": "FCP",
"value": 3460,
"rating": "poor",
"delta": 3460,
"entries": [
{
"name": "first-contentful-paint",
"entryType": "paint",
"startTime": 3460,
"duration": 0
}
],
"id": "v4-1756182424710-9327242888893",
"navigationType": "reload"
}
interface Metric {
//메트릭의 이름(약어 형태).
name: "CLS" | "FCP" | "INP" | "LCP" | "TTFB";
//메트릭의 현재 값.
value: number;
/**
* 메트릭 값이 "좋음(good)", "개선 필요(needs improvement)",
* 또는 "나쁨(poor)" 임계치 범위에 해당하는지를 나타내는 평가.
*/
rating: "good" | "needs-improvement" | "poor";
/**
* 현재 값과 마지막 보고 값의 차이(델타).
* 첫 번째 보고에서는 `delta`와 `value`가 항상 동일함.
*/
delta: number;
id: string;
/**
* 메트릭 값 계산과 관련된 성능 항목들.
* 항목이 없을 수도 있으며, 이는 메트릭 값이 특정 항목에 기반하지 않은 경우임.
* (예: 레이아웃 시프트가 없어서 CLS 값이 0인 경우)
*/
entries: PerformanceEntry[];
/**
* 네비게이션 타입.
*
* 이는 Navigation Timing API가 반환하는 값(브라우저가 지원하지 않으면 `undefined`)과 같음.
* 단, 다음 예외 사항이 있음:
* - 'back_forward'는 일관성을 위해 'back-forward'로 이름이 바뀜.
* - 'prerender': 미리 렌더링된 페이지.
*/
navigationType:
| "navigate"
| "reload"
| "back-forward"
| "prerender"
}




StaticTest와 Loading...을 빠르게 확인할 수 있으므로 FCP 개선 효과가 있습니다.
대규모 데이터 로딩/SSR에 유리: 서버/클라이언트에서 일부 데이터를 비동기로 가져오는 상황에서 유용합니다.
개발 환경에서는 Rating이 Good이 아닐 경우 콘솔에 표시되도록 해서, 원인을 바로 확인하면서 개선하는 게 좋습니다.
운영 환경에서는 Google Analytics(GA)를 활용해 웹 추적을 진행하면 효율적으로 관리할 수 있습니다.