Ch 04. 성능 측정 — Lighthouse와 Core Web Vitals
배포했다고 끝이 아닙니다. 실제로 사용자에게 빠르게 느껴지는지 확인해야 합니다. 직접 체감하는 속도와 실제 측정값이 다를 수 있습니다. 개발자의 고사양 컴퓨터와 빠른 인터넷 환경은 일반 사용자와 다릅니다.
Lighthouse는 Google이 만든 성능 측정 도구입니다. Chrome에 내장되어 있어 별도 설치 없이 사용할 수 있습니다.
Lighthouse 사용법
- Chrome에서 측정할 페이지를 엽니다.
F12를 눌러 개발자 도구를 엽니다.Lighthouse탭을 클릭합니다.Analyze page load를 클릭합니다.
잠시 후 100점 만점의 네 가지 점수가 나타납니다.
- Performance: 페이지 로딩 속도와 반응성
- Accessibility: 장애인 접근성 (스크린 리더, 키보드 탐색 등)
- Best Practices: 보안, HTTPS, 최신 API 사용 여부
- SEO: 검색 엔진 최적화
Core Web Vitals — 세 가지 핵심 지표
Google이 2021년부터 검색 순위 요소로 반영하는 세 가지 지표입니다. Performance 점수의 핵심을 이룹니다.
LCP (Largest Contentful Paint) — 가장 큰 요소 로딩 시간
화면에서 가장 큰 요소(일반적으로 히어로 이미지, 큰 제목)가 보이는 데 걸리는 시간입니다.
| 점수 | 기준 |
|---|---|
| 좋음 | 2.5초 이하 |
| 개선 필요 | 2.5~4초 |
| 나쁨 | 4초 초과 |
LCP를 개선하는 방법입니다.
- 히어로 이미지에
priority속성을 추가합니다. - 서버에서 미리 렌더링합니다 (SSR, SSG).
- 이미지를 WebP/AVIF 형식으로 제공합니다.
INP (Interaction to Next Paint) — 상호작용 응답성
사용자가 클릭, 탭, 키 입력 등을 했을 때 화면이 반응하는 속도입니다. (2024년 3월 FID를 대체했습니다.)
| 점수 | 기준 |
|---|---|
| 좋음 | 200ms 이하 |
| 개선 필요 | 200~500ms |
| 나쁨 | 500ms 초과 |
INP를 개선하는 방법입니다.
- 무거운 JavaScript 연산을 Web Worker로 분리합니다.
- 불필요한 클라이언트 컴포넌트를 서버 컴포넌트로 전환합니다.
- 이벤트 핸들러를 최적화합니다.
CLS (Cumulative Layout Shift) — 레이아웃 이동
페이지가 로드되는 동안 요소들이 얼마나 이동하는지를 측정합니다. 글을 읽다가 갑자기 버튼이 내려가서 엉뚱한 것을 누른 경험이 있다면 CLS가 높은 것입니다.
| 점수 | 기준 |
|---|---|
| 좋음 | 0.1 이하 |
| 개선 필요 | 0.1~0.25 |
| 나쁨 | 0.25 초과 |
CLS를 개선하는 방법입니다.
<Image>컴포넌트에width,height를 명시합니다.- 동적으로 추가되는 콘텐츠에 공간을 미리 확보합니다.
- 웹 폰트 로딩 시
font-display: swap을 사용합니다.
Next.js가 자동으로 최적화하는 것들
Next.js를 사용하는 것만으로도 많은 최적화가 자동으로 이루어집니다.
이미지 최적화: next/image가 자동으로 WebP 변환, 지연 로딩, 크기 최적화를 처리합니다.
코드 분할: 각 페이지에 필요한 JavaScript만 로드합니다. 하나의 거대한 번들 대신, 페이지별로 작은 청크가 만들어집니다.
폰트 최적화: next/font를 사용하면 Google Fonts를 로컬로 호스팅해 외부 요청을 줄입니다.
// 파일: app/layout.tsximport { Inter } from "next/font/google";const inter = Inter({ subsets: ["latin"], display: "swap",});export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html lang="ko" className={inter.className}> <body>{children}</body> </html> );}```text**스크립트 최적화**: `next/script`의 `strategy` 옵션으로 서드파티 스크립트 로딩을 제어합니다.```typescriptimport Script from "next/script";// 페이지 로딩 후에 실행<Script src="https://analytics.example.com/script.js" strategy="lazyOnload" />```text### 점수를 높이는 실용적인 팁1. **LCP 이미지에 priority 추가**: 화면 상단 이미지에 `priority` 속성을 붙입니다.2. **불필요한 "use client" 제거**: 클라이언트 컴포넌트가 많을수록 JavaScript 번들이 커집니다.3. **Suspense로 스트리밍**: 느린 데이터를 기다리는 동안 나머지 페이지를 먼저 보여줍니다.4. **캐싱 활용**: `unstable_cache`, `revalidateTag`로 불필요한 데이터 재조회를 줄입니다.5. **번들 분석**: `@next/bundle-analyzer`로 어떤 모듈이 번들을 크게 만드는지 확인합니다.```bashnpm install @next/bundle-analyzerANALYZE=true npm run build
다음 챕터에서는 배포 후 장애가 발생했을 때 대응하는 체크리스트를 정리합니다.