Next.js <img> vs <Image> — PageSpeed 관점에서의 선택 기준
Next.js를 처음 배우면 "이미지는 무조건 <Image>를 쓰세요"라고 배웁니다. 공식 문서도 그렇게 권장합니다. 하지만 PageSpeed 최적화를 진행하면서 발견한 건, 직접 최적화한 <img> 태그가 더 높은 점수를 내는 경우가 있다는 것입니다.
두 방식의 차이를 이해하면, 상황에 맞는 선택을 할 수 있습니다.
1Next.js Image가 하는 일
next/image의 Image 컴포넌트는 개발자 대신 여러 가지를 자동으로 처리합니다:
자동 리사이즈
원본 이미지에서 여러 크기의 srcset을 자동 생성합니다. 디바이스 너비에 맞는 이미지만 다운로드합니다.
포맷 변환
브라우저가 지원하면 자동으로 WebP로 변환합니다 (AVIF는 별도 설정 필요).
Lazy Loading 기본
viewport 밖 이미지는 자동으로 lazy loading됩니다. priority 속성으로 Hero 이미지만 즉시 로드할 수 있습니다.
CLS 방지
width/height를 필수로 요구해서 이미지 로드 전후 레이아웃 시프트를 방지합니다.
이렇게 보면 만능처럼 보입니다. 하지만 자동화에는 대가가 있습니다.
<!-- Next.js Image가 생성하는 HTML -->
<img
alt="Hero Image"
loading="lazy"
width="900"
height="1118"
decoding="async"
data-nimg="1"
style="color:transparent"
sizes="100vw"
srcset="
/_next/image?url=%2Fhero.webp&w=640&q=75 640w,
/_next/image?url=%2Fhero.webp&w=750&q=75 750w,
/_next/image?url=%2Fhero.webp&w=828&q=75 828w,
/_next/image?url=%2Fhero.webp&w=1080&q=75 1080w,
/_next/image?url=%2Fhero.webp&w=1200&q=75 1200w,
/_next/image?url=%2Fhero.webp&w=1920&q=75 1920w,
/_next/image?url=%2Fhero.webp&w=2048&q=75 2048w,
/_next/image?url=%2Fhero.webp&w=3840&q=75 3840w
"
src="/_next/image?url=%2Fhero.webp&w=3840&q=75"
/>srcset에 8개 크기가 들어갑니다. 이미지마다 이런 HTML이 생성되면, document 크기가 커지고, 브라우저는 어떤 크기를 다운로드할지 계산하는 시간이 필요합니다. 또한 /_next/image 엔드포인트를 거치면서 서버에서 실시간 리사이즈가 일어나므로 첫 요청은 느릴 수 있습니다.
2수동 최적화 img 태그
반대로 직접 이미지를 최적화하면 이렇게 됩니다:
// 빌드 시 sharp로 미리 변환
// sharp input.png -resize 900 --avif quality=40 -o hero.avif
<!-- HTML — 깔끔하고 가벼움 -->
<img
src="/images/hero.avif"
alt="Hero Image"
width={900}
height={1118}
fetchPriority="high"
className="object-cover w-full h-full"
/>HTML이 간결합니다. srcset도 없고, /_next/image 엔드포인트도 거치지 않습니다. 이미지는 이미 최적화된 상태로 /public에 있기 때문에 정적 파일로 바로 서빙됩니다.
수동 최적화의 장점
- AVIF 사용 가능: Next.js Image는 기본이 WebP입니다. AVIF를 쓰려면 별도 설정이 필요하고, 실시간 인코딩은 느립니다.
- CDN 캐시 적중률: 정적 파일은 CDN에서 바로 응답합니다.
/_next/image는 서버를 거쳐야 합니다. - 정확한 품질 제어: 이미지마다 적절한 quality와 크기를 직접 정할 수 있습니다.
- 빌드 타임 최적화: 한 번 변환하면 끝입니다. 런타임 비용이 없습니다.
3실전 비교
같은 Hero 이미지를 두 방식으로 로드했을 때의 차이입니다.
| 항목 | <Image> | <img> + AVIF |
|---|---|---|
| 포맷 | WebP (자동) | AVIF (수동) |
| 파일 크기 | ~124KB | ~60KB |
| 서빙 방식 | 서버 리사이즈 후 응답 | 정적 파일 직접 서빙 |
| 첫 요청 응답 | 리사이즈 + 인코딩 대기 | 즉시 응답 |
| HTML 크기 | srcset 8개 포함 (~500B) | 단일 src (~80B) |
| 설정 필요 | 거의 없음 | sharp 스크립트 필요 |
핵심 차이는 이미지 변환이 언제 일어나는가입니다. Image 컴포넌트는 런타임(사용자 요청 시)에 변환하고, 수동 방식은 빌드 타임에 변환합니다. Hero 이미지처럼 항상 같은 이미지가 보이는 경우, 빌드 타임에 최적화하는 게 더 효율적입니다.
4Image가 적합한 경우
그렇다고 Image 컴포넌트가 나쁜 건 아닙니다. 이미지를 제어할 수 없을 때 진짜 가치를 발휘합니다.
사용자 업로드 이미지
프로필 사진, 게시물 이미지 등 어떤 크기/포맷이 올라올지 모릅니다. Image가 자동으로 리사이즈해줍니다.
CMS 연동 이미지
외부 CMS에서 가져오는 이미지는 크기를 직접 제어할 수 없습니다. remotePatterns와 함께 쓰면 편리합니다.
반응형 아트 디렉션
디바이스마다 다른 크기의 이미지를 보여줘야 할 때, srcset이 자동 생성되는 건 편합니다.
이미지가 수백 장인 경우
블로그 글마다 썸네일이 다르고, 일일이 sharp로 변환하기 번거로운 경우 자동화가 필요합니다.
// ✅ 사용자 업로드 이미지 — Image가 적합
import Image from "next/image";
<Image
src={user.profileImage} // 어떤 크기인지 모름
alt={user.name}
width={128}
height={128}
className="rounded-full object-cover"
/>
// ✅ CMS 이미지 — Image가 적합
<Image
src={post.thumbnailUrl} // 외부 URL
alt={post.title}
width={800}
height={450}
sizes="(max-width: 768px) 100vw, 50vw"
/>5img가 적합한 경우
반대로, 이미지를 완전히 제어할 수 있을 때는 수동 최적화가 더 좋은 결과를 냅니다.
Hero 이미지 (LCP 요소)
항상 같은 이미지가 표시됩니다. 빌드 타임에 AVIF로 변환하고 fetchPriority='high'와 preload를 쓰면 LCP가 최소화됩니다.
배경 이미지, 아이콘
디자이너가 전달한 에셋을 그대로 사용합니다. 크기와 포맷이 고정되어 있어 자동 리사이즈가 불필요합니다.
정적 사이트 이미지
회사 소개 페이지, 서비스 페이지 등 이미지가 바뀌지 않는 경우. 빌드 시 한 번 최적화하면 런타임 비용이 없습니다.
PageSpeed 점수가 중요한 랜딩 페이지
0.1초라도 더 빠른 LCP가 필요합니다. 서버 리사이즈 과정을 건너뛸 수 있습니다.
// ✅ Hero 이미지 — img + AVIF가 적합
<img
src="/images/hero.avif"
alt="서비스 소개"
width={900}
height={1118}
fetchPriority="high"
className="object-cover w-full h-full"
/>
// ✅ 서비스 카드 이미지 — img + WebP + lazy
<img
src="/images/service-ai.webp"
alt="AI 서비스"
width={1920}
height={1434}
loading="lazy"
className="object-cover w-full h-full"
/>img 태그 사용 시 주의사항
- width/height 필수: CLS를 방지하려면 반드시 지정해야 합니다. Image 컴포넌트는 강제하지만, img는 누락하기 쉽습니다.
- lazy loading 직접 관리: Image는 자동이지만, img는
loading="lazy"를 직접 넣어야 합니다. - 최적화를 직접 해야 함: sharp 같은 도구로 빌드 스크립트를 만들어야 합니다. 구체적인 방법은 sharp 자동화를 참고하세요. 귀찮지만 결과는 더 좋습니다.
6선택 기준 정리
결론은 간단합니다. "이미지를 제어할 수 있으면 img, 제어할 수 없으면 Image."
| 상황 | 추천 | 이유 |
|---|---|---|
| Hero / LCP 이미지 | <img> + AVIF | 최소 용량, 즉시 서빙, preload 가능 |
| 정적 에셋 (배경, 아이콘) | <img> + WebP | 고정 크기, 런타임 비용 불필요 |
| 사용자 업로드 이미지 | <Image> | 크기 불확실, 자동 리사이즈 필요 |
| 외부 CMS 이미지 | <Image> | remotePatterns로 외부 URL 처리 |
| 이미지 수백 장 (갤러리) | <Image> | 일일이 수동 최적화 비현실적 |
핵심 정리
이 글의 비교는 Next.js 15 기준이며, 버전에 따라 Image 컴포넌트의 동작이 다를 수 있습니다. 실제 성능 차이는 서버 환경, CDN 설정, 이미지 크기에 따라 달라집니다.
댓글
(4개)로그인하면 댓글을 작성할 수 있습니다.
결론이 깔끔합니다. '제어 가능하면 img, 불확실하면 Image.' 저도 같은 결론에 도달했는데 이렇게 정리해주니 팀원 설득이 쉬워지겠네요.
사용자 업로드 이미지에는 Image가 편하다는 게 핵심이네요. 어떤 이미지가 들어올지 모르니까 자동 리사이즈가 필요한 거고.
Image 컴포넌트가 생성하는 srcset이 오히려 HTML을 무겁게 만드는 케이스, 저도 경험했습니다. 정적 사이트에서는 빌드 타임에 최적화하는 게 맞습니다.
관련 글
© 2026 TreeRU. All rights reserved.
본 콘텐츠의 저작권은 TreeRU에 있으며, 출처를 밝히지 않은 무단 전재 및 재배포를 금합니다. 인용 시 출처(treeru.com)를 반드시 명시해 주세요.