Google은 사용자 경험을 측정하는 Core Web Vitals를 검색 순위 신호로 활용합니다. LCP(최대 콘텐츠 페인트), INP(다음 페인트까지의 상호작용), CLS(누적 레이아웃 이동) 세 가지 지표를 이해하고 개선하면 SEO와 사용자 경험을 동시에 향상시킬 수 있습니다.
LCP — Largest Contentful Paint (목표: 2.5초 이내)
화면에서 가장 큰 이미지나 텍스트 블록이 렌더링되는 시간입니다. 대부분 히어로 이미지나 H1 제목이 해당됩니다.
<!-- LCP 개선 1: 히어로 이미지 preload -->
<link rel="preload" as="image"
href="/hero.webp"
imagesrcset="/hero-400.webp 400w, /hero-800.webp 800w"
imagesizes="100vw">
<!-- LCP 개선 2: fetchpriority 힌트 -->
<img src="/hero.webp" fetchpriority="high" alt="히어로 이미지">
<!-- LCP 개선 3: LCP 이미지에는 lazy loading 금지 -->
<!-- 나쁜 예 -->
<img src="/hero.webp" loading="lazy">
<!-- 좋은 예 -->
<img src="/hero.webp" loading="eager">
<!-- LCP 개선 4: 이미지 형식 최적화 -->
<picture>
<source type="image/avif" srcset="/hero.avif">
<source type="image/webp" srcset="/hero.webp">
<img src="/hero.jpg" alt="히어로"
width="1400" height="500"> <!-- width/height 반드시 명시 -->
</picture>
INP — Interaction to Next Paint (목표: 200ms 이내)
사용자 상호작용(클릭, 키입력)에서 다음 화면 업데이트까지 걸리는 시간입니다. 2024년 FID를 대체했습니다.
// INP 개선 1: 긴 작업(Long Task) 분리
// 나쁜 예 — 메인 스레드 블로킹
function processLargeList(items) {
items.forEach(item => heavyComputation(item));
}
// 좋은 예 — yield로 메인 스레드 해방
async function processLargeList(items) {
for (const item of items) {
heavyComputation(item);
// 50ms마다 메인 스레드에 제어권 반환
if (performance.now() % 50 < 1) {
await new Promise(r => setTimeout(r, 0));
}
}
}
// INP 개선 2: 이벤트 핸들러 최적화
button.addEventListener('click', () => {
// 즉시 시각 피드백 제공
button.disabled = true;
button.textContent = '처리 중...';
// 무거운 작업은 비동기로
requestAnimationFrame(() => {
performHeavyTask();
});
});
CLS — Cumulative Layout Shift (목표: 0.1 이하)
페이지 로드 중 요소들이 갑자기 움직이는 정도입니다. 이미지 크기 미지정, 늦게 로드되는 광고, 동적 콘텐츠가 주요 원인입니다.
<!-- CLS 개선 1: 이미지/영상 크기 항상 명시 -->
<img src="thumbnail.jpg" width="640" height="360" alt="썸네일">
<!-- 또는 CSS aspect-ratio 사용 -->
/* CLS 개선 2: aspect-ratio로 공간 미리 확보 */
.thumbnail {
aspect-ratio: 16 / 9;
width: 100%;
object-fit: cover;
}
/* CLS 개선 3: 폰트 로딩 중 레이아웃 변화 방지 */
@font-face {
font-family: 'Pretendard';
src: url('/fonts/pretendard.woff2') format('woff2');
font-display: optional; /* 폰트 없으면 시스템 폰트 유지 */
}
/* CLS 개선 4: 광고 영역 크기 고정 */
.ad-slot {
min-height: 250px;
background: #f5f5f5;
}
성능 측정 도구
// Web Vitals 라이브러리로 실제 사용자 데이터 수집
import { onLCP, onINP, onCLS } from 'web-vitals';
function sendToAnalytics({ name, value, rating }) {
console.log(`${name}: ${value}ms (${rating})`);
// GA4, DataDog 등으로 전송
}
onLCP(sendToAnalytics);
onINP(sendToAnalytics);
onCLS(sendToAnalytics);
리소스 우선순위 힌트
<!-- DNS 미리 연결 -->
<link rel="dns-prefetch" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<!-- 핵심 리소스 미리 로드 -->
<link rel="preload" href="/fonts/pretendard.woff2" as="font" crossorigin>
<link rel="preload" href="/critical.css" as="style">
<!-- 다음 페이지 미리 가져오기 -->
<link rel="prefetch" href="/posts/next-article.html">
<!-- 중요하지 않은 스크립트 지연 로드 -->
<script src="/analytics.js" defer></script>
<script src="/chat-widget.js" async></script>
Critical CSS 인라인
<!-- 첫 화면에 필요한 CSS만 인라인으로 -->
<style>
/* Above-the-fold 스타일만 포함 */
body { margin: 0; font-family: system-ui; }
.header { position: sticky; top: 0; background: #fff; }
.hero { height: 500px; background: #6891f8; }
</style>
<!-- 나머지 CSS는 비동기 로드 -->
<link rel="stylesheet" href="/style.css" media="print" onload="this.media='all'">
LCP는 히어로 이미지 preload와 WebP/AVIF 형식으로 개선하세요. INP는 긴 작업을 분리하고 즉시 시각 피드백을 제공하세요. CLS는 이미지와 광고 영역의 크기를 미리 확보하세요. PageSpeed Insights와 Chrome DevTools의 Performance 탭으로 정기적으로 측정하고 개선하는 것이 중요합니다.
LCP 개선 실전 전략
LCP 요소가 무엇인지 먼저 파악해야 합니다. Chrome DevTools Performance 탭의 LCP 마커 클릭 또는 Lighthouse 리포트의 "Largest Contentful Paint element"에서 확인하세요.
- 히어로 이미지가 LCP라면 —
<img loading="eager" fetchpriority="high">추가,<link rel="preload" as="image">적용 - 배경 이미지가 LCP라면 — CSS background-image는 preload가 어렵습니다.
<img>태그로 교체하거나<link rel="preload">로 처리 - 텍스트가 LCP라면 — 웹폰트 로딩 최적화.
font-display: swap+ preconnect 적용 - 서버 응답이 느리면 — TTFB(Time to First Byte) 개선이 우선입니다. CDN 도입, 서버 사이드 캐싱 검토
CLS 원인 진단과 해결
CLS는 페이지 로드 중 예상치 못하게 레이아웃이 이동하는 정도를 측정합니다. 흔한 원인과 해결 방법입니다.
| 원인 | 해결법 |
|---|---|
| 이미지에 width/height 없음 | <img width="800" height="600"> 또는 CSS aspect-ratio 설정 |
| 광고 슬롯 크기 미지정 | 광고 컨테이너에 min-height 예약 |
| 웹폰트 교체(FOUT) | font-display: optional 또는 size-adjust 폴백 설정 |
| 동적 콘텐츠 삽입 | 위에서 삽입하지 말고 공간을 미리 예약 |
| transform 미사용 애니메이션 | transform과 opacity만 사용, layout 속성 변경 금지 |
INP 개선 — 인터랙션 응답성 높이기
INP는 클릭, 키보드 입력 등 모든 인터랙션의 응답 시간을 측정합니다. 200ms를 넘으면 사용자가 느리다고 체감합니다.
// 무거운 작업을 requestIdleCallback으로 분산
function processLargeList(items) {
const CHUNK_SIZE = 50;
let index = 0;
function processChunk() {
const chunk = items.slice(index, index + CHUNK_SIZE);
chunk.forEach(item => renderItem(item));
index += CHUNK_SIZE;
if (index < items.length) {
requestIdleCallback(processChunk); // 메인 스레드 양보
}
}
processChunk();
}
// 입력 이벤트 — 즉시 시각적 피드백, 무거운 작업은 비동기
button.addEventListener('click', () => {
button.disabled = true;
button.textContent = '처리 중...'; // 즉시 피드백
setTimeout(() => { // 무거운 작업은 분리
doHeavyWork();
button.disabled = false;
button.textContent = '완료';
}, 0);
});
Core Web Vitals 모니터링 도구
Lighthouse 점수(실험실 데이터)와 실제 사용자 데이터(Field Data)는 다를 수 있습니다. 두 가지를 모두 활용하세요.
- Google Search Console — "Core Web Vitals" 리포트에서 실제 사용자 CWV 현황 확인 (무료)
- PageSpeed Insights — URL 입력만으로 실제 필드 데이터 + Lighthouse 점수 동시 확인
- web-vitals.js — 라이브러리 설치 한 줄로 CWV를 GA4나 BigQuery로 직접 수집 가능
- CrUX Dashboard — Google Looker Studio 기반 무료 대시보드, 월별 추이 시각화
// web-vitals.js로 GA4에 CWV 지표 전송
import { onLCP, onINP, onCLS } from 'web-vitals';
function sendToAnalytics(metric) {
gtag('event', metric.name, {
value: Math.round(metric.name === 'CLS' ? metric.value * 1000 : metric.value),
metric_rating: metric.rating, // 'good', 'needs-improvement', 'poor'
});
}
onLCP(sendToAnalytics);
onINP(sendToAnalytics);
onCLS(sendToAnalytics);
Core Web Vitals 개선이 비즈니스에 미치는 실제 영향
Core Web Vitals 개선은 기술적인 성취에 그치지 않고 실제 비즈니스 성과로 직결됩니다. Google은 2021년 페이지 경험 업데이트를 통해 CWV 점수를 검색 순위 알고리즘에 공식 반영했습니다. 이후 다수의 사례 연구에서 LCP를 1초 개선했을 때 전환율이 평균 7~15% 상승하는 결과가 보고됐습니다. 쿠팡, 무신사 같은 국내 이커머스 플랫폼들도 모바일 성능 최적화를 지속적으로 투자하는 이유가 바로 여기에 있습니다. 느린 페이지는 사용자 이탈률을 높이고, 이탈률 증가는 광고비 대비 수익률(ROAS)을 떨어뜨립니다.
CLS 개선 효과도 측정 가능한 수준으로 나타납니다. 레이아웃이 갑자기 이동하면 사용자가 의도치 않은 버튼을 클릭하거나 결제 정보를 잘못 입력하는 사고가 발생합니다. CLS를 0.1 이하로 낮춘 사이트에서 폼 오류율이 감소하고 체류 시간이 늘었다는 데이터가 여러 최적화 사례에서 확인됩니다. INP 개선은 특히 모바일 사용자 경험과 밀접합니다. 반응이 느린 버튼이나 드롭다운 메뉴는 사용자에게 앱이 고장난 것 같은 인상을 줍니다. INP를 200ms 이하로 관리하면 모바일 사용자의 세션당 페이지뷰가 증가하는 패턴이 자주 관찰됩니다.