강력한 내장 컴포넌트 최적화 (Image, Font 등)
Next.js는 웹 사이트의 성능을 저하시키는 주된 원인인 무거운 이미지 리소스와 느린 페이지 이동 문제를 해결하기 위해, 매우 강력하게 최적화된 내장 컴포넌트를 제공합니다. 초보자도 기존 HTML 태그 대신 Next.js의 컴포넌트로 바꿔 쓰기만 하면 즉각적인 성능 향상을 경험할 수 있습니다.
1. 이미지 최적화: <Image> 컴포넌트
기존 HTML의 <img> 태그는 원본 용량 그대로 다운로드되어 화면 로딩을 지연시키고, 이미지가 뒤늦게 뜨면서 화면이 덜컹거리는 현상(CLS: Layout Shift)을 유발합니다. Next.js의 <Image> 컴포넌트는 이를 자동으로 완벽하게 해결합니다.
- 포맷 자동 변환: 무거운 PNG/JPEG 이미지를 브라우저가 지원하는 경우 최신 압축 포맷인 WebP나 AVIF로 자동 변환하여 제공합니다.
- 지연 로딩 (Lazy Loading): 사용자가 스크롤을 내려 이미지가 브라우저 화면(Viewport)에 보이기 직전까지 다운로드를 미뤄, 초기 페이지 렌더링 속도를 폭발적으로 향상시킵니다.
- 레이아웃 시프트(CLS) 방지: 태그에 반드시
width와height속성을 명시하게 강제하여, 이미지가 다운로드되기 전부터 브라우저에 빈 공간을 확보해 둡니다. 덕분에 이미지가 뜬다고 텍스트가 팍 밀리는 현상이 사라집니다.
2. 라우팅 최적화: <Link> 컴포넌트
일반적인 HTML의 <a> 태그는 클릭 시 브라우저가 전체 페이지를 하얗게 지우고 다시 로딩하는 '새로고침'을 발생시킵니다. 반면 Next.js의 <Link> 컴포넌트는 단일 페이지 애플리케이션(SPA)처럼 부드럽고 찰나의 순간에 페이지를 이동시킵니다.
- 사전 로딩 (Prefetching): 화면에
<Link>컴포넌트가 노출되는 순간, Next.js는 똑똑하게 백그라운드에서 해당 연결 페이지의 데이터를 미리 슬쩍 가져옵니다. 그래서 사용자가 클릭했을 때 기다림 없이 즉시 페이지가 열리게 됩니다. - 클라이언트 사이드 라우팅 (Client-side Routing): 브라우저가 새 페이지를 통째로 불러오는 대신, 변경되어야 하는 컴포넌트와 데이터 조각들만 갈아끼워 모바일 앱처럼 매끄러운 사용자 경험을 제공합니다.
💡 요약 핵심: Next.js 생태계 내에서는 구글, 네이버 등 외부 사이트로 나가는 링크가 아닌 이상 무조건
<a> 대신 <Link>를, 일반 이미지 태그 대신 <Image>를 사용하는 것이 성능 최적화를 위한 가장 기본적이고 훌륭한 첫걸음입니다!
// ==========================================
// 📂 app/OptimizationDemo.tsx
// Next.js 내장 컴포넌트 실전 예제
// ==========================================
import Image from 'next/image';
import Link from 'next/link';
export default function OptimizationDemo() {
return (
<div className="p-8 max-w-3xl mx-auto space-y-12">
{/* 1. <Link> 컴포넌트 사용 (SPA 부드러운 이동) */}
<section>
<h2 className="text-2xl font-bold mb-4">🚀 놀라운 속도의 페이지 이동</h2>
<nav className="flex gap-4">
{/* 외부 링크가 아닌 내부 라우팅은 무조건 Link 사용 */}
<Link
href="/about"
className="px-6 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition"
>
소개 페이지로 즉시 이동
</Link>
<Link
href="/blog"
className="px-6 py-3 bg-gray-200 text-gray-800 rounded-lg hover:bg-gray-300 transition"
>
블로그 둘러보기
</Link>
</nav>
<p className="mt-2 text-sm text-gray-500">
* 링크가 화면에 보이는 순간 백그라운드에서 다음 페이지 데이터를 미리 불러옵니다(Prefetching).
</p>
</section>
{/* 2. <Image> 컴포넌트 사용 (WebP 변환, Lazy loading) */}
<section>
<h2 className="text-2xl font-bold mb-4">🖼️ 극도로 최적화된 이미지 렌더링</h2>
<div className="border border-gray-200 rounded-xl overflow-hidden shadow-lg inline-block">
{/* 일반 img 태그 대신 Image 태그 사용 */}
<Image
src="/heavy-landscape.jpg" // public 폴더에 저장된 이미지
alt="멋진 풍경 이미지"
width={800} // Layout Shift(화면 덜컹거림)를 막기 위해 width 명시 필수
height={450} // Layout Shift(화면 덜컹거림)를 막기 위해 height 명시 필수
priority={true} // 첫 화면에 바로 보여야 하는 가장 중요한 이미지일 경우 우선순위 배정
placeholder="blur" // 로딩 중일 때 흐릿한 잔상(블러) 효과를 표시하여 UX 극대화
blurDataURL="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+ip1sAAAAASUVORK5CYII="
className="object-cover"
/>
</div>
<ul className="mt-4 text-sm text-gray-600 list-disc pl-5 space-y-1">
<li>원본이 5MB짜리 무거운 사진이라도 브라우저에 맞게 <b>WebP/AVIF로 자동 압축</b>됩니다.</li>
<li>화면 스크롤을 내려서 <b>이미지가 시야에 들어올 때만 다운로드</b>합니다. (Lazy loading 기본 적용)</li>
</ul>
</section>
</div>
);
}