Core Web Vitals 완벽 가이드 2026 - 페이지 경험 최적화
LCP, INP, CLS 지표의 의미와 최적화 방법. Google 순위 요소인 Core Web Vitals를 개선하는 실전 가이드.
Toolypet Team
Development Team
Core Web Vitals 완벽 가이드 2026
"사이트가 느려서 이탈했다"
사용자의 53%는 로딩이 3초 이상 걸리면 페이지를 떠납니다. Google은 이런 사용자 경험을 순위에 반영하기 위해 Core Web Vitals를 도입했습니다.
2026년 기준, Core Web Vitals는 모바일 SEO의 핵심 순위 요소입니다.
Core Web Vitals란?
Core Web Vitals는 사용자 경험을 측정하는 3가지 핵심 지표입니다.
2026년 지표
| 지표 | 측정 항목 | 좋음 | 개선 필요 | 나쁨 |
|---|---|---|---|---|
| LCP | 로딩 속도 | ≤2.5초 | ≤4초 | >4초 |
| INP | 상호작용 반응 | ≤200ms | ≤500ms | >500ms |
| CLS | 시각적 안정성 | ≤0.1 | ≤0.25 | >0.25 |
지표 변화 (2024년)
FID (First Input Delay) → INP (Interaction to Next Paint)
FID: 첫 번째 입력만 측정
INP: 모든 상호작용의 응답성 측정 (더 포괄적)
LCP (Largest Contentful Paint)
정의
페이지에서 가장 큰 콘텐츠 요소가 화면에 렌더링되는 시간
측정 대상
| 요소 | 예시 |
|---|---|
<img> | 히어로 이미지 |
<video> 포스터 | 비디오 썸네일 |
CSS background-image | 배경 이미지 |
| 텍스트 블록 | <h1>, <p> 등 |
최적화 방법
1. 이미지 최적화
<!-- ❌ 느림 -->
<img src="hero.png" alt="Hero">
<!-- ✅ 최적화 -->
<img
src="hero.webp"
srcset="hero-400.webp 400w, hero-800.webp 800w"
sizes="(max-width: 600px) 400px, 800px"
alt="Hero"
loading="eager"
fetchpriority="high"
>
2. 서버 응답 시간 (TTFB)
목표: TTFB < 200ms
개선 방법:
- CDN 사용
- 서버 사이드 캐싱
- 데이터베이스 쿼리 최적화
- HTTP/2 또는 HTTP/3
3. 렌더링 차단 리소스 제거
<!-- ❌ 렌더링 차단 -->
<link rel="stylesheet" href="styles.css">
<script src="app.js"></script>
<!-- ✅ 최적화 -->
<link rel="stylesheet" href="critical.css">
<link rel="preload" href="styles.css" as="style" onload="this.rel='stylesheet'">
<script src="app.js" defer></script>
4. 크리티컬 CSS 인라인
<head>
<style>
/* 첫 화면에 필요한 CSS만 인라인 */
.hero { ... }
.header { ... }
</style>
<link rel="preload" href="full.css" as="style">
</head>
5. 프리로드 힌트
<head>
<!-- LCP 이미지 프리로드 -->
<link rel="preload" href="hero.webp" as="image" fetchpriority="high">
<!-- 웹폰트 프리로드 -->
<link rel="preload" href="font.woff2" as="font" crossorigin>
</head>
INP (Interaction to Next Paint)
정의
사용자 상호작용(클릭, 탭, 키 입력)부터 다음 화면 업데이트까지의 시간
FID와의 차이
| FID | INP |
|---|---|
| 첫 번째 입력만 | 모든 상호작용 |
| 입력 지연만 | 전체 응답 시간 |
| 2024년 폐지 | 2024년 3월 대체 |
측정 대상
- 클릭 (마우스, 터치)
- 키 입력
- 탭 (모바일)
최적화 방법
1. 메인 스레드 차단 방지
// ❌ 메인 스레드 차단
function heavyTask() {
for (let i = 0; i < 1000000; i++) {
// 무거운 계산
}
}
// ✅ 청크로 분할
async function heavyTaskChunked() {
const chunks = splitIntoChunks(data, 1000);
for (const chunk of chunks) {
processChunk(chunk);
await new Promise(r => setTimeout(r, 0)); // 양보
}
}
2. 디바운스/스로틀
// ❌ 매번 실행
input.addEventListener('input', search);
// ✅ 디바운스
input.addEventListener('input', debounce(search, 300));
3. Web Worker 사용
// 메인 스레드
const worker = new Worker('worker.js');
worker.postMessage(data);
worker.onmessage = (e) => updateUI(e.data);
// worker.js
self.onmessage = (e) => {
const result = heavyComputation(e.data);
self.postMessage(result);
};
4. 이벤트 핸들러 최적화
// ❌ 무거운 핸들러
button.onclick = () => {
computeData(); // 무거움
updateDOM(); // DOM 조작
sendAnalytics(); // 네트워크
};
// ✅ 비동기 분리
button.onclick = async () => {
requestAnimationFrame(() => {
updateDOM(); // 빠른 UI 업데이트 먼저
});
await computeDataAsync();
sendAnalytics(); // 나중에
};
5. 스크립트 크기 줄이기
// 코드 스플리팅
const Modal = React.lazy(() => import('./Modal'));
// 트리 쉐이킹
import { specific } from 'library'; // 전체 import 피하기
CLS (Cumulative Layout Shift)
정의
페이지 로드 중 예상치 못한 레이아웃 이동의 누적 점수
문제 상황
사용자: 버튼을 클릭하려는 순간
광고가 로드됨: 레이아웃이 밀림
결과: 다른 버튼을 클릭해버림
최적화 방법
1. 이미지/비디오 크기 지정
<!-- ❌ 크기 없음 (CLS 유발) -->
<img src="photo.jpg" alt="Photo">
<!-- ✅ 크기 지정 -->
<img src="photo.jpg" alt="Photo" width="800" height="600">
<!-- ✅ aspect-ratio 사용 -->
<img src="photo.jpg" alt="Photo" style="aspect-ratio: 4/3; width: 100%;">
2. 광고/임베드 공간 예약
/* 광고 영역 미리 예약 */
.ad-slot {
min-height: 250px;
background: #f0f0f0;
}
/* 또는 aspect-ratio */
.video-embed {
aspect-ratio: 16/9;
width: 100%;
}
3. 웹폰트 최적화
/* ❌ FOUT/FOIT 발생 */
@font-face {
font-family: 'Custom';
src: url('font.woff2');
}
/* ✅ font-display 사용 */
@font-face {
font-family: 'Custom';
src: url('font.woff2');
font-display: swap; /* 또는 optional */
}
<!-- 폰트 프리로드 -->
<link rel="preload" href="font.woff2" as="font" crossorigin>
4. 동적 콘텐츠 처리
// ❌ 갑자기 삽입
container.innerHTML = newContent;
// ✅ 공간 예약 후 삽입
container.style.minHeight = '200px';
container.innerHTML = newContent;
/* 또는 CSS로 최소 높이 */
.dynamic-content {
min-height: 200px;
}
5. transform 애니메이션 사용
/* ❌ 레이아웃 트리거 */
.element {
animation: slide 0.3s;
}
@keyframes slide {
from { top: -100px; }
to { top: 0; }
}
/* ✅ transform 사용 (레이아웃 이동 없음) */
@keyframes slide {
from { transform: translateY(-100px); }
to { transform: translateY(0); }
}
측정 도구
필드 데이터 (실제 사용자)
| 도구 | 데이터 소스 | 특징 |
|---|---|---|
| Chrome UX Report | Chrome 사용자 | 28일 집계 |
| Search Console | CrUX 기반 | Google 공식 |
| PageSpeed Insights | CrUX + Lighthouse | 실시간 분석 |
랩 데이터 (시뮬레이션)
| 도구 | 용도 |
|---|---|
| Lighthouse | Chrome DevTools 내장 |
| WebPageTest | 상세 분석, 비교 테스트 |
| GTmetrix | 시각적 리포트 |
Chrome DevTools
1. F12 (개발자 도구)
2. Performance 탭
3. Record → 페이지 새로고침
4. Web Vitals 섹션 확인
프레임워크별 최적화
Next.js
// next.config.js
module.exports = {
images: {
formats: ['image/avif', 'image/webp'],
},
experimental: {
optimizeCss: true,
},
};
// 컴포넌트
import Image from 'next/image';
export default function Hero() {
return (
<Image
src="/hero.jpg"
alt="Hero"
width={1200}
height={600}
priority // LCP 이미지
placeholder="blur"
/>
);
}
React
// 코드 스플리팅
const HeavyComponent = React.lazy(() => import('./HeavyComponent'));
// Suspense
<Suspense fallback={<Skeleton />}>
<HeavyComponent />
</Suspense>
Vanilla JavaScript
<!-- 스크립트 로딩 -->
<script src="critical.js"></script>
<script src="app.js" defer></script>
<script src="analytics.js" async></script>
<!-- 이미지 지연 로딩 -->
<img src="below-fold.jpg" loading="lazy" alt="Below fold">
개선 우선순위
영향도 순
| 순위 | 최적화 항목 | 효과 |
|---|---|---|
| 1 | LCP 이미지 최적화 | LCP ↓ |
| 2 | 렌더링 차단 JS 제거 | LCP, INP ↓ |
| 3 | 이미지/임베드 크기 지정 | CLS ↓ |
| 4 | CDN 사용 | LCP ↓ |
| 5 | 웹폰트 최적화 | CLS ↓ |
| 6 | JS 번들 분할 | INP ↓ |
빠른 성과 (Quick Wins)
<!-- 1. LCP 이미지 프리로드 -->
<link rel="preload" href="hero.webp" as="image">
<!-- 2. 이미지 크기 지정 -->
<img width="800" height="600" ...>
<!-- 3. JS defer -->
<script src="app.js" defer></script>
FAQ
Q1: Core Web Vitals가 순위에 얼마나 영향을 주나요?
A: 직접적인 순위 요소이지만, 콘텐츠 품질보다 중요하지는 않습니다. 경쟁 페이지와 콘텐츠 품질이 비슷할 때 결정적 역할을 합니다.
Q2: 모바일과 데스크톱 점수가 다른 이유는?
A: Google은 모바일 데이터를 주로 사용합니다. 모바일 최적화를 우선하세요.
Q3: "데이터 없음"이 표시되는 이유는?
A: Chrome UX Report에 충분한 트래픽 데이터가 없습니다. 사이트 트래픽이 적거나 신규 사이트일 수 있습니다.
Q4: 어떤 지표를 먼저 개선해야 하나요?
A: 일반적으로:
- LCP - 가장 눈에 띄는 개선
- CLS - 사용자 불만 감소
- INP - 상호작용 많은 사이트에서 중요
Q5: 서드파티 스크립트가 문제일 때는?
A:
- 필요 없는 스크립트 제거
async또는defer속성 사용- Partytown 같은 Web Worker 라이브러리 사용
체크리스트
LCP 최적화
- LCP 이미지 프리로드
- 이미지 최적화 (WebP/AVIF)
- 렌더링 차단 리소스 제거
- TTFB < 200ms
- CDN 사용
INP 최적화
- 무거운 JS 청크 분할
- 디바운스/스로틀 적용
- 불필요한 JS 제거
- 서드파티 스크립트 정리
CLS 최적화
- 이미지/비디오 크기 지정
- 광고 공간 예약
- font-display 설정
- 동적 콘텐츠 공간 예약
마무리
Core Web Vitals 핵심:
- LCP ≤ 2.5초: 가장 큰 콘텐츠 빠르게
- INP ≤ 200ms: 상호작용 즉시 반응
- CLS ≤ 0.1: 레이아웃 이동 없이
모바일 최적화가 핵심입니다.
관련 도구
| 도구 | 용도 |
|---|---|
| PageSpeed 분석기 | Core Web Vitals 측정 |
| 이미지 최적화 | WebP 변환 |
| 메타 태그 생성기 | SEO 메타 태그 |
저자 소개
Toolypet Team
Development Team
The Toolypet Team creates free, privacy-focused web tools for developers and designers. All tools run entirely in your browser with no data sent to servers.