프론트엔드 개발
Next.js로 배우는 실전 웹 바이탈 최적화 완벽 가이드
쫌수
2025. 1. 11. 02:29
안녕하세요! 오늘은 Next.js에서 제공하는 기능들을 활용해 웹 바이탈을 최적화하는 방법을 상세히 알아보겠습니다. 특히 Next.js 13 이상에서 사용할 수 있는 최신 기능들을 중심으로 설명드리겠습니다.
1. LCP(Largest Contentful Paint) 최적화
LCP는 사용자가 보는 화면에서 가장 큰 이미지나 텍스트가 표시되는 시간을 측정합니다. Next.js의 Image 컴포넌트를 활용하면 쉽게 최적화할 수 있습니다.
Next.js Image 컴포넌트 최적화
// app/page.tsx
import Image from 'next/image'
function HeroSection() {
return (
<Image
src="/hero.jpg"
alt="Hero image"
width={1200}
height={600}
priority={true} // LCP 이미지는 priority 필수!
quality={75} // 품질과 파일 크기 최적화
placeholder="blur" // 로딩 중 blur 효과
blurDataURL="data:image/jpeg;base64,..." // 미리보기 이미지
/>
)
}
Next.js 설정 최적화
// next.config.js
module.exports = {
images: {
deviceSizes: [640, 750, 828, 1080, 1200, 1920],
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
formats: ['image/avif', 'image/webp'],
},
experimental: {
optimizeCss: true, // CSS 최적화
}
}
2. FID(First Input Delay) 최적화
FID는 사용자의 첫 상호작용(클릭, 탭 등)에 대한 응답 시간을 측정합니다.
App Router의 Dynamic Imports
// app/dashboard/page.tsx
import { Suspense } from 'react'
import dynamic from 'next/dynamic'
// 무거운 컴포넌트 동적 로딩
const HeavyChart = dynamic(() => import('@/components/HeavyChart'), {
loading: () => <LoadingSkeleton />,
ssr: false // 클라이언트 사이드에서만 로드
})
export default function DashboardPage() {
return (
<Suspense fallback={<LoadingSkeleton />}>
<HeavyChart />
</Suspense>
)
}
서버 컴포넌트 활용
// app/products/page.tsx
import { ProductList } from '@/components/ProductList'
// 서버 컴포넌트로 데이터 로딩
async function getProducts() {
const res = await fetch('https://api.example.com/products')
return res.json()
}
export default async function ProductsPage() {
const products = await getProducts()
return <ProductList products={products} />
}
3. CLS(Cumulative Layout Shift) 최적화
CLS는 페이지 로드 중 발생하는 레이아웃 변화를 측정합니다.
Next/Image를 활용한 이미지 CLS 방지
// app/components/ProductCard.tsx
import Image from 'next/image'
export function ProductCard({ product }) {
return (
<div className="relative aspect-square w-full">
<Image
src={product.image}
alt={product.name}
fill
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
className="object-cover rounded-lg"
/>
</div>
)
}
Next/Font로 폰트 최적화
// app/layout.tsx
import { Inter } from 'next/font/google'
const inter = Inter({
subsets: ['latin'],
display: 'swap',
preload: true,
})
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en" className={inter.className}>
<body>{children}</body>
</html>
)
}
Loading UI와 Streaming
// app/products/loading.tsx
export default function Loading() {
return (
<div className="grid grid-cols-3 gap-4">
{[...Array(6)].map((_, i) => (
<div key={i} className="animate-pulse">
<div className="bg-gray-200 aspect-square rounded-lg" />
<div className="h-4 bg-gray-200 rounded mt-2 w-3/4" />
<div className="h-4 bg-gray-200 rounded mt-2 w-1/2" />
</div>
))}
</div>
)
}
4. Next.js 성능 분석 및 모니터링
내장 Analytics 활용
// app/layout.tsx
import { Analytics } from '@vercel/analytics/react'
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>
{children}
<Analytics />
</body>
</html>
)
}
웹 바이탈 측정
// app/components/WebVitals.tsx
'use client'
import { useReportWebVitals } from 'next/web-vitals'
export function WebVitals() {
useReportWebVitals(metric => {
console.log(metric)
// 애널리틱스로 전송
switch (metric.name) {
case 'LCP':
console.log('LCP:', metric.value)
break
case 'FID':
console.log('FID:', metric.value)
break
case 'CLS':
console.log('CLS:', metric.value)
break
}
})
return null
}
결과 및 모범 사례
실제 프로젝트에 위 최적화를 적용한 결과:
- LCP: Next/Image + priority로 2초 이하 달성
- FID: 서버 컴포넌트 + 동적 임포트로 100ms 이하 유지
- CLS: Next/Image fill + 스켈레톤 UI로 0.1 이하 달성
추가 팁
- 페이지별 최적화
// app/[slug]/page.tsx export async function generateMetadata({ params }) { return { title: `${params.slug} - My Site`, description: '...', } }
export const dynamicParams = true
2. **이미지 자동 최적화**
```jsx
/** @type {import('next').NextConfig} */
const nextConfig = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'your-domain.com',
},
],
},
}
- 라우트 그룹화로 성능 최적화
app/ (marketing)/ # 마케팅 페이지 그룹 page.tsx about/page.tsx (dashboard)/ # 대시보드 그룹 layout.tsx page.tsx
결론
Next.js는 웹 바이탈 최적화를 위한 다양한 기능을 기본적으로 제공합니다. Image, Font, Analytics 등의 컴포넌트와 서버 컴포넌트, Suspense 등의 기능을 적절히 활용하면 손쉽게 최적화된 웹사이트를 구축할 수 있습니다.
특히 App Router와 서버 컴포넌트를 활용하면, 클라이언트 번들 크기를 줄이고 초기 로딩 성능을 크게 개선할 수 있습니다.
다음 포스트에서는 Next.js 13의 새로운 기능인 Server Actions과 Parallel Routes를 활용한 고급 최적화 기법에 대해 다루도록 하겠습니다.