Skip to content
Published on

성능·Core Web Vitals 2025 완전 정복: LCP·CLS·INP, Real User Monitoring vs Synthetic, Critical Rendering Path, JS 번들·Image·Font 최적화, Caching·Edge·CDN·HTTP/3, Vercel Speed Insights·CrUX·PageSpeed, 한국 네트워크 특성 — Season 6 Ep 6

Authors

프롤로그 · 성능은 기능이 아니다

개발자들이 자주 착각하는 것: "성능 최적화는 기능 출시 후의 튜닝". 2025년 현실은 다르다.

  • Google 검색 순위에 Core Web Vitals 반영 (2021~)
  • 이커머스에서 LCP 0.1초 개선당 전환율 1%+ 연구 (Amazon, Booking)
  • 2024년 INP 정식 적용 후 반응성 최적화 경쟁
  • 한국 사용자의 지하철 5G·저전력 모드 현실

"성능은 기능이 아니다. 모든 기능의 조건이다."

좋은 AI·좋은 UX·좋은 모션도 느리면 아무 가치 없다. 이번 글은 2025년 실전 성능 가이드.

1장 · Core Web Vitals 2025 — 3대 지표

LCP (Largest Contentful Paint)

  • 가장 큰 콘텐츠가 뷰포트에 렌더된 시점
  • Good: ≤ 2.5초, Needs Improvement: ≤ 4초, Poor: > 4초
  • 보통 Hero 이미지·텍스트 블록

CLS (Cumulative Layout Shift)

  • 뷰포트 이동(레이아웃 시프트) 누적
  • Good: ≤ 0.1, Needs: ≤ 0.25, Poor: > 0.25
  • 이미지 size 미지정·광고 삽입·폰트 로드 등이 주범

INP (Interaction to Next Paint) — 2024 FID 대체

  • 사용자 상호작용 → 다음 페인트까지 걸린 시간
  • Good: ≤ 200ms, Needs: ≤ 500ms, Poor: > 500ms
  • 느린 JS·메인스레드 블록 탐지
  • FID(First Input Delay)보다 페이지 생애 전체 평가

측정 기준

  • p75 (75 백분위수) — 대부분 사용자 경험
  • Real users, 28일 rolling (CrUX)
  • Mobile·Desktop 분리 평가

보조 지표

  • FCP (First Contentful Paint): 1.8초 목표
  • TTFB (Time to First Byte): 0.8초 목표
  • TTI (Time to Interactive): 오래된 지표, INP가 대체

2장 · RUM vs Synthetic — 무엇을 측정할까

Synthetic (합성 테스트)

  • 도구가 제어된 환경에서 시뮬레이션
  • Lighthouse, WebPageTest, SpeedCurve
  • 장점: 재현성, 회귀 감지
  • 단점: 실사용자와 괴리

RUM (Real User Monitoring)

  • 실제 사용자 브라우저에서 측정
  • Vercel Speed Insights, Datadog RUM, New Relic Browser, Sentry, CrUX
  • 장점: 진짜 경험 반영
  • 단점: 노이즈, 소수 사용자 영향 큼

병행 원칙

  • CI에서 Lighthouse (회귀 감지)
  • Production에서 RUM (진짜 성능)
  • CrUX 월간 리뷰로 경쟁사 벤치마크

CrUX (Chrome User Experience Report)

  • Google이 Chrome 사용자 데이터 수집 (opt-in)
  • 익명 집계, 월 단위 업데이트
  • PageSpeed Insights가 이를 활용
  • BigQuery 공개 데이터셋

3장 · Critical Rendering Path

브라우저의 렌더 파이프라인

  1. Network: HTML 다운로드
  2. Parse HTML → DOM
  3. Parse CSS → CSSOM
  4. DOM + CSSOM → Render Tree
  5. Layout (크기·위치)
  6. Paint (픽셀)
  7. Composite (레이어 합성)

주요 병목

  • Render-Blocking CSS: 외부 CSS 로드 중 렌더 불가
  • Render-Blocking JS: <script> 파싱 중 DOM 파싱 중단
  • Font Swap Period: 폰트 로드 전 FOIT/FOUT

2025년 표준 개선 기법

(1) Critical CSS Inline

  • Above-the-fold CSS를 <style> 로 인라인
  • Next.js·Astro·Vite 플러그인 자동화

(2) defer / async JS

  • <script defer> : 문서 끝까지 실행 지연
  • <script async> : 독립 실행

(3) fetchpriority

  • <img fetchpriority="high"> 로 우선순위
  • LCP 이미지에 필수

(4) preconnect / dns-prefetch

  • 외부 도메인 핸드셰이크 미리
  • <link rel="preconnect" href="https://cdn.example.com">

(5) preload

  • 중요 리소스 미리 로드
  • 폰트·Hero 이미지 등

4장 · JS 번들 다이어트

2025년 번들의 "좋은 크기":

  • Initial: < 170kb gzipped
  • Per route: < 50kb
  • 모바일 환경에서 Parse·Execute 비용 고려

번들러 지형 2025

  • esbuild: 가장 빠른 Go 기반
  • swc: Rust 기반, Next.js 내부
  • Rollup: 라이브러리·트리셰이킹
  • Turbopack: Next.js 15 기본, Rust 기반 Webpack 후계
  • Vite: 개발 서버 최고, 번들은 Rollup
  • Rspack: Rust 기반 Webpack 호환
  • Bun: 런타임+번들러 통합

번들 분석 도구

  • Bundle Analyzer (Next.js, Vite)
  • source-map-explorer
  • Rollup visualizer
  • Bundlephobia: 패키지 크기 사전 조회

흔한 문제

(1) 무거운 라이브러리

  • momentdate-fns or dayjs
  • lodash 전체 → 개별 import
  • react-icons → svg 직접

(2) 사용 안 하는 코드

  • 트리셰이킹 안 되는 CJS 패키지
  • "sideEffects": false 명시

(3) Dynamic Import

  • 차트·모달 등 지연 로드
  • const Chart = dynamic(() => import('./Chart'))

(4) Polyfill 과잉

  • 타겟 브라우저 명확히 (Baseline 2024)
  • core-js 선택적 import

(5) CSS-in-JS 오버헤드

  • 런타임 CSS-in-JS → zero-runtime (linaria, Vanilla Extract, Pigment)
  • Tailwind·CSS Modules 대세

5장 · Image 최적화 — LCP의 핵심

포맷 선택 (2025)

포맷용도압축률지원
AVIF최신최강 (~50% vs JPEG)모던 브라우저
WebP표준JPEG 대비 30%모든 모던
JPEG사진기본100%
PNG투명·단순무손실100%
SVG벡터작음100%

2025년 권장: AVIF + WebP + JPEG 폴백

반응형 이미지

  • <img srcset="..." sizes="..."> 로 기기별 최적 이미지
  • 또는 <picture> 로 포맷별 분기

Next.js Image 컴포넌트

import Image from 'next/image';

<Image
  src="/hero.jpg"
  width={1200}
  height={600}
  priority         // LCP 후보
  alt="Hero"
  placeholder="blur"
  blurDataURL={blur}
/>
  • 자동 AVIF/WebP 변환
  • 반응형 srcset 생성
  • Lazy load 기본 (priority만 eager)
  • CLS 방지 (width·height 필수)

Astro Image / Astro Assets

  • 빌드 타임 최적화
  • getImage() API로 고급 제어

CDN 이미지 서비스

  • Cloudinary, Imgix, Bunny, Cloudflare Images
  • 실시간 변환·캐싱

주요 팁

  • 항상 width·height 지정 (CLS 0)
  • Lazy Load + priority 혼합
  • LCP 이미지는 preload + fetchpriority=high
  • Hero 이미지는 인라인 SVG·data-URL 검토

6장 · Font 최적화

핵심 이슈

  • 폰트 로드 지연 → 텍스트 보이지 않음(FOIT) 또는 전환 깜빡(FOUT)
  • CLS 발생

font-display 설정

@font-face {
  font-family: 'Pretendard';
  src: url('/fonts/pretendard.woff2') format('woff2');
  font-display: swap;  /* 기본 폰트 먼저, 로드 후 교체 */
}
  • swap: 기본 폰트 먼저 (CLS↑), 가장 빠름
  • optional: 100ms 안에 로드 안 되면 기본 폰트 유지 (CLS↓)
  • fallback: swap과 optional 중간

size-adjust·ascent-override

  • 기본 폰트와 웹폰트 메트릭 맞춤
  • CLS 대폭 감소
@font-face {
  font-family: 'Pretendard-fallback';
  src: local('Arial');
  size-adjust: 105%;
  ascent-override: 90%;
}

서브셋팅

  • 한국어 폰트는 크기가 큼 (2-3MB) → 자주 쓰는 글자만
  • 주요 자주 사용 문자 (KS X 1001 기본)
  • Subfont 도구로 자동 서브셋

Variable Font

  • 하나의 파일로 여러 굵기·너비·스타일
  • font-variation-settings
  • Pretendard Variable 공개 (국산 대표)

2025년 권장 스택

  • Pretendard Variable (한글)
  • Inter / Geist (영문)
  • Noto Sans KR (폴백)
  • font-display: swap + size-adjust

7장 · Caching 전략

HTTP 캐시

  • Cache-Control: 가장 중요한 헤더
    • public, max-age=31536000, immutable — 정적 리소스
    • no-cache — 항상 검증
    • no-store — 절대 저장 X
  • ETag / Last-Modified — 조건부 요청
  • Stale-While-Revalidate — 만료 후에도 써도 되나 백그라운드 갱신

Next.js 15 Caching (재설계)

  • Request Memoization: 동일 요청 중복 제거
  • Data Cache: 서버 fetch 응답 캐시
  • Full Route Cache: 정적 페이지 HTML
  • Router Cache: 클라이언트 라우터 캐시
  • 2025년부터 use cache 지시어로 명시적 opt-in

Service Worker

  • Offline, App-shell, Cache-first for assets
  • Workbox로 구현 편의
  • 2025년 PWA 부활 조짐 (iOS 제한 완화 움직임)

Edge Caching

  • CDN 레벨 캐시 (Vercel, Cloudflare, Fastly)
  • stale-while-revalidate 로 체감 속도↑
  • ISR (Incremental Static Regeneration) — Next.js 대표 기법

8장 · Edge·CDN·HTTP/3

CDN의 역할

  • 지리적 가까운 서버에서 응답
  • 원본 서버 부하 감소
  • TLS·HTTP/3·압축 오프로딩

2025년 주요 CDN

  • Cloudflare: 가격·기능 밸런스 최강
  • Vercel Edge Network: Next.js 친화
  • Fastly: 개발자 친화, VCL
  • AWS CloudFront: AWS 생태계 통합
  • Netlify Edge: JAMstack 친화
  • 한국: Toast KRP, 네이버 클라우드 CDN, KT 올레CDN

Edge Function

  • CDN 레벨에서 로직 실행
  • Cloudflare Workers, Vercel Edge, Deno Deploy, Fastly Compute@Edge
  • Cold Start 거의 없음 (V8 Isolate)
  • 사용 사례: A/B, 인증, Rate Limit, i18n

HTTP/3 (QUIC)

  • UDP 기반, Head-of-line Blocking 해결
  • TLS 1.3 내장, 0-RTT 연결
  • 2025년 CDN·주요 사이트 기본
  • 모바일·불안정 네트워크에서 특히 이점

한국 네트워크 특성

  • 지하철 5G: 혼잡·지연·패킷 로스
  • 공공 WiFi: 제한·광고 프록시
  • KT·SKT·LGU+ 통신사별 라우팅 차이
  • → Edge·CDN이 특히 중요

9장 · INP 최적화 — 반응성 실전

INP의 원인

  • 긴 작업(long task) >50ms 이 메인 스레드 점유
  • 상호작용 처리 지연

실전 기법

(1) Debounce / Throttle

  • 검색 input·스크롤 리스너

(2) Scheduler API (Chrome)

scheduler.postTask(() => heavyWork(), { priority: 'background' });

(3) useDeferredValue / useTransition (React 18+)

const [isPending, startTransition] = useTransition();
startTransition(() => setQuery(input));

(4) Web Workers

  • 무거운 계산·정렬을 워커로

(5) Virtualization

  • 긴 리스트에 react-window, TanStack Virtual

(6) Code Splitting

  • 필요할 때만 로드

측정

  • Chrome DevTools Performance "INP" 기록
  • Long Task API로 production 감지

10장 · Vercel Speed Insights·CrUX·PageSpeed

Vercel Speed Insights

  • Vercel 배포 프로젝트에 간단 통합
  • RUM 데이터, Web Vitals 자동
  • 페이지별·시간별 분해
  • 가격: Pro 플랜 포함

Datadog RUM / New Relic Browser

  • 엔터프라이즈 APM과 통합
  • 사용자 세션 리플레이, 에러 추적
  • 가격 비쌈

CrUX Dashboard

  • Google이 제공 무료 도구
  • site-level, origin-level 리포트
  • CrUX API·BigQuery로 자동화

PageSpeed Insights

  • Google 무료 도구
  • Lighthouse + CrUX 결합
  • SEO·Accessibility·Best Practices까지

WebPageTest

  • 가장 정교한 Synthetic
  • 다양한 위치·네트워크·디바이스
  • 워터폴 차트, 필름 스트립

11장 · 실전 체크리스트 · 성능 린터

프로젝트 초기 설정

  • Next.js/Astro Image 활용
  • font-display: swap + size-adjust
  • Critical CSS (프레임워크 기본)
  • Bundle Analyzer 설치
  • Lighthouse CI 설정 (threshold: LCP<2.5s, CLS<0.1, INP<200ms)
  • Vercel Speed Insights 또는 자체 RUM

릴리즈 전 체크

  • LCP 원인 분석 (DevTools "Performance insights")
  • INP 이벤트 핸들러 점검
  • CLS 이미지 size 확인
  • 번들 < 170kb
  • 핵심 폰트 preload
  • 3G Fast 에뮬레이션 테스트

릴리즈 후 모니터링

  • RUM 75p 추이
  • 사고 시 롤백·수정
  • 주간 Performance Review 팀 미팅

12장 · 2025년 고급 패턴

Partial Pre-Rendering (PPR)

  • Next.js 15: 정적 셸 + 동적 홀
  • LCP 극단 단축 + 개인화 공존

Islands Architecture

  • Astro: 기본 정적 + JS 섬만 하이드레이트
  • 번들 최소화

Qwik Resumability

  • 초기 JS 0에 가까움
  • 상호작용 필요 시점에 로드

Bun/Deno 런타임

  • Node.js 대비 시작·런타임 속도
  • 일부 프로덕션 도입 시작

Turbopack

  • Next.js 15 기본
  • Dev 서버·빌드 속도 혁명

Server-sent Streaming

  • RSC·Suspense로 콘텐츠 조각 전송
  • TTFB·LCP 개선

13장 · 다음 글 예고 — Season 6 Ep 7: "접근성과 국제화"

성능을 잘 만들어 놓았다면 다음은 모두가 쓸 수 있는 제품. Ep 7은 접근성(a11y)과 국제화(i18n).

  • WCAG 2.2 실전 체크리스트
  • Screen Reader 테스트 (NVDA·VoiceOver)
  • 키보드 내비게이션 설계
  • ARIA 패턴과 오남용
  • 색 대비·모션·폰트 크기
  • EU Accessibility Act 2025·ADA·한국 장애인차별금지법
  • i18n: next-intl·react-intl·vue-i18n·Format.js
  • Locale-aware 숫자·날짜·통화
  • 한국어 타이포그래피의 특수성 (조사·줄바꿈·세로 쓰기)
  • 일본·중국어·RTL(아랍어·히브리어) 지원
  • AI·LLM의 다국어 품질

"접근성은 소수의 권리가 아니다. 모두의 품질이다."

다음 글에서 만나자.

에필로그 · 체크리스트 12

  1. Core Web Vitals p75 기준을 RUM으로 추적하는가?
  2. LCP < 2.5s, CLS < 0.1, INP < 200ms 를 달성하는가?
  3. LCP 이미지에 priority + fetchpriority=high 설정되는가?
  4. 모든 이미지에 width·height 가 지정되는가?
  5. 폰트가 font-display + size-adjust 로 FOIT/CLS 방지되는가?
  6. 번들이 초기 <170kb, 라우트 <50kb 인가?
  7. Dynamic Import·Code Splitting 을 적극 활용하는가?
  8. CDN·Edge Caching 이 설정되어 있는가?
  9. HTTP/3 가 활성화되어 있는가?
  10. Lighthouse CI로 회귀 감지되는가?
  11. Vercel Speed Insights 또는 RUM 운영되는가?
  12. 한국 네트워크·모바일 실사용자 경험이 고려되는가?

"빠른 제품은 좋은 제품이다. 느린 제품은 존재하지 않는 제품이다."

— Season 6 Ep 6, Fin.