Core Web Vitals: 웹 성능 향상을 위한 측정 및 개선
빠른 웹사이트를 구축했는데도 사용자들이 여전히 느리다고 불평하나요? 아니면 Google 업데이트 이후 SEO 순위가 떨어졌나요? 원인은 Core Web Vitals일 수 있습니다. 이는 Google이 실제 사용자 경험을 측정하는 데 사용하는 지표 집합입니다. 이를 무시하면 사용자 만족도와 검색 가시성 모두에 악영향을 줄 수 있습니다.
이 가이드에서는 Core Web Vitals이 무엇인지, 정확하게 측정하는 방법, 그리고 각 지표를 개선하기 위한 실용적인 단계를 배웁니다. 현재 세 가지 지표인 Largest Contentful Paint(LCP), Interaction to Next Paint(INP), Cumulative Layout Shift(CLS)에 초점을 맞춥니다.
Core Web Vitals이란 무엇인가요?
Core Web Vitals은 Google이 훌륭한 사용자 경험을 제공하는 데 필수적이라고 간주하는 Web Vitals의 하위 집합입니다. 콘텐츠가 얼마나 빨리 로드되는지, 페이지가 상호작용에 얼마나 반응하는지, 시각적으로 얼마나 안정적인지를 정량화합니다.
Google은 이러한 지표를 순위 신호로 사용하지만, 더 중요하게는 실제 사용자의 불편함을 반영합니다. 느린 LCP는 콘텐츠를 기다리는 사용자를 frustrate시키고, 높은 INP는 페이지가 느리게 느껴지게 하며, 높은 CLS는 잘못된 클릭과 짜증을 유발합니다.
세 가지 Core Web Vitals
- Largest Contentful Paint (LCP): 로딩 성능을 측정합니다. 가장 큰 콘텐츠 요소(이미지, 비디오 또는 텍스트 블록)가 보이게 되는 시간을 표시합니다. 좋은 LCP는 2.5초 이하입니다.
- Interaction to Next Paint (INP): 반응성을 측정합니다. 모든 상호작용(클릭, 탭, 키 누름)의 지연 시간을 기록하고 단일 값을 보고합니다. 좋은 INP는 200밀리초 이하입니다.
- Cumulative Layout Shift (CLS): 시각적 안정성을 측정합니다. 로딩 중 예기치 않은 레이아웃 이동을 정량화합니다. 좋은 CLS는 0.1 이하입니다.
이러한 임계값은 실험실 테스트가 아닌 실제 사용자의 필드 데이터를 기반으로 합니다. Google은 페이지 로드의 75번째 백분위수에서 이를 평가합니다. 즉, 사용자 경험의 75%가 "좋음" 임계값을 충족해야 합니다.
Core Web Vitals 측정 방법
실험실 데이터와 필드 데이터가 모두 필요합니다. 실험실 도구는 통제된 조건에서 단일 페이지 로드를 시뮬레이션하는 반면, 필드 데이터(Real User Monitoring, RUM)는 다양한 기기와 네트워크에서 실제 사용자 경험을 캡처합니다.
실험실 도구
- Lighthouse: Chrome DevTools에 내장되어 있으며 성능을 감사하고 LCP, CLS, 그리고 INP와 상관관계가 있는 총 차단 시간(TBT)에 대한 점수를 제공합니다. 확장 프로그램이 결과를 왜곡하지 않도록 시크릿 모드에서 실행하세요.
- PageSpeed Insights: 실험실(Lighthouse) 및 필드(CrUX) 데이터를 결합합니다. 실험실 점수와 실제 사용자 지표를 모두 확인하는 데 사용하세요.
- WebPageTest: 여러 위치와 기기에서 고급 테스트를 제공합니다. 필름스트립과 워터폴 차트를 제공하여 로딩 문제를 진단합니다.
필드 도구
- Chrome User Experience Report (CrUX): Chrome의 실제 사용자 지표에 대한 공개 데이터 세트입니다. PageSpeed Insights, CrUX Dashboard 또는 BigQuery를 통해 사용할 수 있습니다.
- Google Search Console: CrUX 데이터를 기반으로 사이트의 Core Web Vitals 상태를 보여줍니다. 성능별로 URL을 그룹화합니다.
- web-vitals JavaScript 라이브러리: 자체 RUM에서 지표를 측정하는 작은 라이브러리입니다. 데이터를 분석 플랫폼으로 보낼 수 있습니다.
다음은 web-vitals 라이브러리를 사용하여 콘솔에 지표를 기록하는 방법입니다:
import {onLCP, onINP, onCLS} from 'web-vitals';
function sendToAnalytics(metric) {
const body = JSON.stringify(metric);
// navigator.sendBeacon() 또는 fetch()를 사용하여 데이터 전송
(navigator.sendBeacon && navigator.sendBeacon('/analytics', body)) ||
fetch('/analytics', {body, method: 'POST', keepalive: true});
}
onLCP(sendToAnalytics);
onINP(sendToAnalytics);
onCLS(sendToAnalytics);
코딩 없이 빠르게 확인하려면 성능 데이터를 파싱하는 온라인 도구를 사용할 수 있습니다. 예를 들어 서버 로그가 있는 경우 Nginx Log Analyzer가 LCP에 영향을 줄 수 있는 느린 응답을 식별하는 데 도움이 됩니다.
Largest Contentful Paint (LCP) 개선
LCP는 종종 최적화하는 데 가장 영향력 있는 지표입니다. 서버 응답 시간, 리소스 로드 시간, 클라이언트 측 렌더링의 영향을 받습니다.
서버 응답 최적화
- CDN을 사용하여 사용자에게 더 가까운 위치에서 콘텐츠를 제공하세요.
- 정적 자산에 대해 캐싱(브라우저 및 서버 측)을 활성화하세요.
- 데이터베이스 쿼리와 서버 측 코드를 최적화하여 TTFB(Time to First Byte)를 줄이세요.
- 멀티플렉싱과 더 빠른 연결을 위해 HTTP/2 또는 HTTP/3로 업그레이드하세요.
리소스 최적화
- 중요 리소스 미리 로드: LCP 이미지나 폰트에
<link rel="preload">를 사용하세요. - 이미지 압축 및 적절한 크기 조정: WebP나 AVIF 같은 최신 형식을 사용하고
srcset으로 반응형 이미지를 제공하세요. - CSS 및 JavaScript 최소화: 불필요한 문자와 주석을 제거하세요.
- 비중요 JavaScript 지연:
async또는defer속성을 사용하세요. - 중요 CSS 인라인: 렌더 차단 요청을 피하기 위해 스크롤 없이 보이는 스타일을 HTML에 직접 넣으세요.
렌더 차단 리소스 제거
<head>의 CSS와 JavaScript는 렌더링을 차단합니다. 중요 CSS를 인라인하고 나머지는 비동기로 로드하세요. JavaScript의 경우 defer 또는 async를 사용하세요.
Interaction to Next Paint (INP) 개선
INP는 사용자 상호작용부터 다음 페인트까지의 시간을 측정합니다. JavaScript 실행, 이벤트 처리, 렌더링 작업의 영향을 받습니다.
JavaScript 실행 시간 줄이기
setTimeout또는requestIdleCallback을 사용하여 긴 작업(50ms 초과)을 분할하세요.- 무거운 계산에는 웹 워커를 사용하세요.
- 스크롤, 크기 조정, 입력 이벤트에 대해 이벤트 핸들러를 디바운스하거나 스로틀하세요.
- 큰 동기 스크립트를 피하고 코드 분할 및 모듈 지연 로드를 사용하세요.
이벤트 처리 최적화
- 스크롤 성능을 향상시키기 위해 터치 및 휠 이벤트에 수동 이벤트 리스너를 사용하세요.
- DOM 조작을 최소화하고 업데이트를 일괄 처리하며
requestAnimationFrame을 사용하세요. - 복잡한 선택자를 피하여 스타일 재계산 범위를 줄이세요.
렌더링 성능 향상
- GPU 가속을 유발하려면 애니메이션에 CSS
will-change또는transform을 사용하세요. - 스타일 읽기와 쓰기를 별도 단계로 분리하여 레이아웃 스래싱을 피하세요.
Cumulative Layout Shift (CLS) 개선
CLS는 예기치 않은 레이아웃 이동을 측정합니다. 이는 종종 크기 없는 이미지, 광고 또는 동적으로 삽입된 콘텐츠로 인해 로딩 중 요소 위치가 변경되어 발생합니다.
항상 크기 속성 포함
이미지와 비디오의 경우 width 및 height 속성을 설정하거나 CSS aspect-ratio를 사용하세요. 이렇게 하면 공간이 확보되어 이동을 방지합니다.
<img src="#" width="800" height="600" alt="Hero">
동적 콘텐츠를 위한 공간 확보
- 비동기로 콘텐츠를 로드하는 컨테이너(예: 광고, 임베드)에 CSS
min-height를 사용하세요. - 사용자 상호작용으로 트리거되지 않는 한 기존 콘텐츠 위에 콘텐츠를 삽입하지 마세요.
Font-Display Swap 사용
사용자 정의 폰트는 로드될 때 보이지 않는 텍스트(FOIT)나 레이아웃 이동을 유발할 수 있습니다. font-display: swap을 사용하여 대체 텍스트를 즉시 표시하고, 폰트를 미리 로드하여 교체 시간을 줄이세요.
모두 함께 적용하기: 실용적인 워크플로우
- 측정: PageSpeed Insights로 시작하여 실험실 및 필드 데이터를 모두 얻으세요. 개선이 필요한 지표를 식별하세요.
- 진단: Lighthouse와 Chrome DevTools Performance 패널을 사용하여 병목 현상을 찾으세요. 워터폴, 메인 스레드 활동, 레이아웃 이동을 살펴보세요.
- 최적화: 위의 기술을 적용하고 가장 나쁜 지표에 영향을 미치는 변경을 우선시하세요.
- 테스트: 실험실 테스트를 다시 실행하여 개선을 확인하세요. 스테이징 환경에 배포하고 RUM을 사용하여 필드 데이터를 모니터링하세요.
- 모니터링: web-vitals 라이브러리로 지속적인 RUM을 설정하고 회귀에 대해 경고하세요. Search Console을 사용하여 Core Web Vitals 상태를 추적하세요.
최적화에는 트레이드오프가 있을 수 있음을 기억하세요. 예를 들어 이미지 지연 로드는 초기 로드를 개선할 수 있지만 LCP 이미지가 지연 로드되면 LCP를 해칠 수 있습니다. 항상 실제 사용자와 함께 테스트하세요.
FAQ
Core Web Vitals의 현재 임계값은 무엇인가요?
LCP의 경우 좋음은 ≤2.5초, 개선 필요는 ≤4.0초, 나쁨은 >4.0초입니다. INP의 경우 좋음은 ≤200ms, 개선 필요는 ≤500ms, 나쁨은 >500ms입니다. CLS의 경우 좋음은 ≤0.1, 개선 필요는 ≤0.25, 나쁨은 >0.25입니다. 이러한 임계값은 페이지 로드의 75번째 백분위수에서 평가됩니다.
Core Web Vitals을 얼마나 자주 확인해야 하나요?
RUM으로 필드 데이터를 지속적으로 모니터링하세요. Search Console을 매월 확인하여 전체 추세를 파악하세요. 주요 코드 변경이나 배포 후에 실험실 테스트를 실행하세요. Core Web Vitals은 사이트나 타사 스크립트 업데이트로 변경될 수 있습니다.
개발자 없이 Core Web Vitals을 개선할 수 있나요?
일부 개선은 플러그인이나 설정(예: 캐싱 활성화, 이미지 최적화)을 통해 가능합니다. 그러나 상당한 이득을 얻으려면 중요 CSS 인라인, JavaScript 지연, 리소스 로드 방식 재구성과 같은 코드 변경이 필요한 경우가 많습니다. INP 및 고급 LCP 최적화에는 일반적으로 개발자의 도움이 필요합니다.
서버 성능을 분석할 준비가 되셨나요? Nginx Log Analyzer를 사용하여 Core Web Vitals에 영향을 줄 수 있는 느린 요청을 식별하세요.