개인의 기록
  • 소개
  • 프로젝트
  • 글
  • 링크

© 2026 newgirok

← 글 목록

Next.js Image Optimization — 이미지를 자동 최적화하는 방법

2025년 5월 29일
Next.jsImagenext/imageWebPLazy Loading

웹 성능에서 이미지는 가장 큰 병목 중 하나다. Next.js는 next/image 컴포넌트 하나로 WebP 변환, 크기 조정, Lazy Loading을 자동으로 처리해 별도의 설정 없이도 Core Web Vitals 점수를 끌어올린다. 원본 PNG를 그대로 서빙하던 방식과 비교하면 체감 성능 차이가 크다.

next/image 컴포넌트 기본 구조

브라우저 요청
    │
    ▼
Next.js Image Optimization API
    │  ├─ 포맷 변환 (PNG/JPG → WebP/AVIF)
    │  ├─ 크기 리사이징 (srcset 자동 생성)
    │  └─ 캐싱 (CDN or 로컬)
    │
    ▼
최적화된 이미지 응답

next/image는 브라우저가 요청하는 시점에 서버 사이드에서 이미지를 변환한다. 한 번 변환된 이미지는 캐시에 저장되어 재요청 시 즉시 반환된다.

width / height / fill

고정 크기 이미지는 width와 height를 명시한다.

import Image from 'next/image'

export default function Avatar() {
  return (
    <Image
      src="/profile.png"
      alt="프로필 사진"
      width={80}
      height={80}
    />
  )
}

부모 컨테이너를 채우는 이미지는 fill prop을 사용한다. 이때 부모 요소에 position: relative가 필요하다.

<div style={{ position: 'relative', width: '100%', height: '400px' }}>
  <Image
    src="/hero.jpg"
    alt="히어로 이미지"
    fill
    style={{ objectFit: 'cover' }}
  />
</div>

fill: 부모 요소의 크기를 기준으로 이미지를 꽉 채우는 모드. width/height 대신 사용한다.

priority와 Lazy Loading

기본적으로 모든 next/image는 Lazy Loading이 적용된다. 뷰포트 밖에 있는 이미지는 스크롤이 가까워질 때 로드된다.

Above-the-fold 이미지(LCP 후보)는 priority prop으로 즉시 로드해야 한다.

<Image
  src="/hero.jpg"
  alt="히어로"
  width={1200}
  height={600}
  priority
/>
prop동작사용 시점
기본값Lazy Loading스크롤 아래 이미지
priorityPreload + 즉시 로드LCP 대상, 첫 화면 이미지

LCP(Largest Contentful Paint): 뷰포트에서 가장 큰 콘텐츠가 렌더링되는 시점. Core Web Vitals의 핵심 지표.

WebP 자동 변환

별도 설정 없이 next/image는 브라우저가 WebP를 지원하면 자동으로 WebP로 변환해 응답한다. next.config.js에서 포맷 우선순위를 조정할 수 있다.

// next.config.js
module.exports = {
  images: {
    formats: ['image/avif', 'image/webp'],
  },
}

AVIF를 먼저 시도하고 미지원 브라우저는 WebP로 폴백된다.

Blur Placeholder

이미지가 로드되기 전 블러 처리된 미리보기를 보여주면 레이아웃 시프트를 방지하고 UX가 개선된다.

로컬 이미지는 빌드 타임에 자동 생성된다.

import profilePic from '/public/profile.png'

<Image
  src={profilePic}
  alt="프로필"
  placeholder="blur"
/>

외부 이미지는 blurDataURL을 직접 제공해야 한다.

<Image
  src="https://example.com/photo.jpg"
  alt="외부 이미지"
  width={800}
  height={600}
  placeholder="blur"
  blurDataURL="data:image/png;base64,iVBORw0KGgo..."
/>

sizes 속성으로 srcset 최적화

반응형 레이아웃에서 sizes를 지정하면 브라우저가 현재 뷰포트에 맞는 최소 크기의 이미지를 선택한다.

<Image
  src="/article-thumbnail.jpg"
  alt="썸네일"
  fill
  sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
/>

sizes를 생략하면 Next.js는 항상 최대 크기 이미지를 내려보내 불필요한 데이터를 낭비한다.

← 이전 글Next.js ISR — 정적 페이지를 주기적으로 재생성하는 방법
다음 글 →Next.js Metadata — SEO를 위한 메타 태그 관리