# Next.js 프로젝트에 이미 포함되어 있습니다
# 새 프로젝트 생성 시
npx create-next-app@latest
Next.js는 React 기반의 프레임워크로, 웹 개발 경험을 크게 향상시키는 다양한 기능을 제공합니다. 그중에서도 next/image 모듈은 웹 성능 최적화의 핵심 요소인 이미지 처리를 혁신적으로 개선한 기능입니다. 이 글에서는 next/image의 모든 것을 자세히 알아보겠습니다.
Next.js Image 컴포넌트란?
next/image 모듈은 HTML의 기본 <img> 태그를 대체하는 Next.js의 내장 컴포넌트입니다. 이 컴포넌트는 다음과 같은 주요 기능을 제공합니다:
- 자동 이미지 최적화: 다양한 디바이스에 맞는 크기로 이미지 제공
- 지연 로딩(Lazy Loading): 뷰포트에 들어올 때만 이미지 로드
- 이미지 리사이징: 다양한 화면 크기에 맞게 자동 리사이징
- WebP, AVIF 같은 현대적 포맷 지원: 더 작은 파일 크기로 고품질 이미지 제공
- CLS(Cumulative Layout Shift) 방지: 이미지 로딩으로 인한 레이아웃 이동 최소화
기본 사용법
next/image의 가장 기본적인 사용법은 다음과 같습니다:
import Image from 'next/image';
function MyComponent() {
return (
<div>
<Image
src="/images/profile.jpg"
alt="프로필 이미지"
width={500}
height={300}
/>
</div>
);
}
이 간단한 코드로 Next.js는 자동으로 이미지를 최적화하여 제공합니다.
주요 속성(props) 이해하기
Image 컴포넌트는 다양한 속성을 제공합니다. 자주 사용되는 중요한 속성들을 살펴보겠습니다.
1. 필수 속성
<Image
src="/images/hero.jpg" // 이미지 소스 경로
alt="히어로 이미지" // 접근성을 위한 대체 텍스트
width={1200} // 이미지 너비 (픽셀)
height={600} // 이미지 높이 (픽셀)
/>
src, alt, width, height는 기본적으로 필요한 속성입니다. 단, fill 속성을 사용할 경우 width와 height는 생략 가능합니다.
2. 레이아웃 관련 속성
fill 속성
컨테이너 크기에 맞게 이미지를 채우고 싶을 때 사용합니다:
<div style={{ position: 'relative', width: '100%', height: '300px' }}>
<Image
src="/images/landscape.jpg"
alt="풍경"
fill
style={{ objectFit: 'cover' }}
/>
</div>
fill을 사용할 때는 부모 컨테이너가 position: relative 또는 position: absolute로 설정되어 있어야 합니다.
sizes 속성
반응형 이미지 크기를 지정할 때 사용합니다:
<Image
src="/images/hero.jpg"
alt="히어로 이미지"
fill
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
style={{ objectFit: 'cover' }}
/>
이 코드는 뷰포트 너비에 따라 이미지가 화면의 몇 퍼센트를 차지할지 브라우저에 알려줍니다:
- 모바일(768px 이하): 화면 너비의 100%
- 태블릿(1200px 이하): 화면 너비의 50%
- 데스크톱: 화면 너비의 33%
3. 로딩 관련 속성
priority 속성
LCP(Largest Contentful Paint) 이미지에 사용하는 속성으로, 해당 이미지를 우선적으로 로드합니다:
<Image
src="/images/hero.jpg"
alt="히어로 이미지"
width={1200}
height={600}
priority
/>
hero 이미지나 상단에 노출되는 중요 이미지에 priority를 사용하면 페이지 성능 점수를 향상시킬 수 있습니다.
loading 속성
이미지 로딩 방식을 지정합니다:
<Image
src="/images/content.jpg"
alt="콘텐츠 이미지"
width={800}
height={500}
loading="eager" // 또는 "lazy"
/>
- lazy(기본값): 뷰포트에 접근할 때 로드
- eager: 페이지 로드 시 즉시 로드
placeholder 속성
이미지 로딩 중 표시할 플레이스홀더를 지정합니다:
<Image
src="/images/large-image.jpg"
alt="대형 이미지"
width={1000}
height={800}
placeholder="blur"
blurDataURL="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAD..."
/>
로컬 이미지를 사용하는 경우 placeholder="blur"만 지정하면 Next.js가 자동으로 blur 이미지를 생성합니다.
4. 품질 및 최적화 관련 속성
quality 속성
이미지 최적화 품질을 1-100 사이의 값으로 지정합니다:
<Image
src="/images/photo.jpg"
alt="사진"
width={600}
height={400}
quality={75} // 기본값은 75
/>
높은 품질은 더 선명한 이미지를 제공하지만 파일 크기가 커집니다.
로컬 이미지 vs 외부 이미지
Next.js Image 컴포넌트는 로컬 이미지와 외부 이미지를 다르게 처리합니다.
로컬 이미지
import profilePic from '../public/images/profile.jpg';
function Profile() {
return (
<Image
src={profilePic}
alt="프로필 사진"
// 로컬 이미지는 import하면 width와 height를 자동으로 결정
/>
);
}
로컬 이미지를 import하면 Next.js가 빌드 시점에 이미지 크기를 자동으로 결정하므로 width와 height 속성을 생략할 수 있습니다.
외부 이미지
외부 도메인의 이미지를 사용하려면 next.config.js 파일에 해당 도메인을 등록해야 합니다:
// next.config.js
module.exports = {
images: {
domains: ['example.com', 'cdn.example.com'],
// 또는 더 세밀한 패턴 매칭을 위한 remotePatterns 사용
remotePatterns: [
{
protocol: 'https',
hostname: '**.example.com',
port: '',
pathname: '/images/**',
},
],
},
}
그 후 컴포넌트에서 사용:
<Image
src="https://example.com/images/profile.jpg"
alt="프로필 사진"
width={500}
height={500}
/>
외부 이미지는 항상 width와 height를 명시해야 합니다.
반응형 이미지 구현
다양한 화면 크기에 최적화된 이미지를 제공하는 몇 가지 패턴을 알아보겠습니다.
1. 고정 크기 이미지
<Image
src="/images/product.jpg"
alt="제품 이미지"
width={300}
height={300}
/>
이 방식은 이미지 크기가 항상 동일하게 유지됩니다.
2. 반응형 너비 이미지
<div className="w-full">
<Image
src="/images/banner.jpg"
alt="배너"
width={1200}
height={400}
style={{
width: '100%',
height: 'auto',
}}
/>
</div>
이 방식은 컨테이너 너비에 맞게 이미지 크기가 조정되며, 원본 비율을 유지합니다.
3. fill 속성을 활용한 반응형 이미지
<div className="relative w-full h-[50vh]">
<Image
src="/images/hero.jpg"
alt="히어로 이미지"
fill
sizes="100vw"
style={{ objectFit: 'cover' }}
/>
</div>
이 방식은 전체 영역을 채우는 이미지에 적합하며, objectFit 속성으로 이미지 비율과 크롭 방식을 조정할 수 있습니다.
이미지 최적화 고급 기법
1. 이미지 포맷 자동 변환
Next.js는 브라우저 지원에 따라 WebP나 AVIF 같은 최신 이미지 포맷으로 자동 변환합니다. 추가적인 설정은 불필요합니다.
2. 아트 디렉션 (다양한 이미지 제공)
화면 크기에 따라 다른 이미지를 제공하고 싶을 때:
import { useEffect, useState } from 'react';
import Image from 'next/image';
import desktopImage from '../public/images/hero-desktop.jpg';
import mobileImage from '../public/images/hero-mobile.jpg';
function ResponsiveHero() {
const [isMobile, setIsMobile] = useState(false);
useEffect(() => {
const checkIfMobile = () => {
setIsMobile(window.innerWidth < 768);
};
checkIfMobile();
window.addEventListener('resize', checkIfMobile);
return () => {
window.removeEventListener('resize', checkIfMobile);
};
}, []);
return (
<Image
src={isMobile ? mobileImage : desktopImage}
alt="히어로 이미지"
priority
/>
);
}
3. 커스텀 로더 사용
외부 이미지 최적화 서비스(Cloudinary, Imgix 등)를 사용하는 경우:
// next.config.js
module.exports = {
images: {
loader: 'custom',
loaderFile: './my-loader.js',
},
}
// my-loader.js
export default function myImageLoader({ src, width, quality }) {
return `https://example.com/image-optimizer?url=${src}&w=${width}&q=${quality || 75}`
}
// 컴포넌트에서 사용
<Image
loader={myImageLoader}
src="/me.png"
alt="내 사진"
width={500}
height={500}
/>
성능 최적화 팁
1. 뷰포트에 들어오는 이미지만 로드하기
기본적으로 Next.js Image 컴포넌트는 지연 로딩됩니다. 단, LCP(Largest Contentful Paint) 이미지에는 priority 속성을 사용하세요:
<Image
src="/hero.jpg"
alt="히어로 이미지"
width={1200}
height={600}
priority
/>
2. 적절한 이미지 크기 선택
불필요하게 큰 이미지는 대역폭을 낭비합니다. 필요한 크기만큼만 요청하세요:
<Image
src="/images/profile.jpg"
alt="프로필"
width={40} // 아바타처럼 작게 표시될 경우
height={40}
/>
3. 이미지 사전 로드
중요한 이미지는 사전 로드할 수 있습니다:
// pages/_document.js
import { Html, Head, Main, NextScript } from 'next/document'
export default function Document() {
return (
<Html>
<Head>
<link
rel="preload"
href="/images/hero.jpg"
as="image"
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
4. 이미지 캐싱 최적화
next.config.js에서 이미지 캐시 동작을 설정할 수 있습니다:
module.exports = {
images: {
minimumCacheTTL: 60, // 초 단위, 기본값은 60
},
}
실제 사용 사례
1. 제품 갤러리
function ProductGallery({ images }) {
return (
<div className="grid grid-cols-2 md:grid-cols-3 gap-4">
{images.map((image, index) => (
<div key={index} className="relative h-64">
<Image
src={image.src}
alt={image.alt || "제품 이미지"}
fill
sizes="(max-width: 768px) 50vw, 33vw"
style={{ objectFit: "cover" }}
className="rounded-lg hover:opacity-90 transition-opacity"
/>
</div>
))}
</div>
);
}
2. 히어로 섹션
function HeroSection() {
return (
<div className="relative h-[70vh] w-full">
<Image
src="/images/hero-background.jpg"
alt="히어로 배경"
fill
priority
sizes="100vw"
style={{ objectFit: "cover" }}
/>
<div className="absolute inset-0 bg-black bg-opacity-50 flex items-center justify-center">
<h1 className="text-white text-4xl md:text-6xl font-bold">
웹사이트에 오신 것을 환영합니다
</h1>
</div>
</div>
);
}
3. 블로그 포스트 이미지
function BlogPost({ post }) {
return (
<article>
<div className="relative aspect-video mb-6">
<Image
src={post.coverImage}
alt={post.title}
fill
priority
sizes="(max-width: 768px) 100vw, 900px"
style={{ objectFit: "cover" }}
className="rounded-xl"
/>
</div>
<h1 className="text-3xl font-bold">{post.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.content }} />
</article>
);
}
주의사항 및 한계
1. 서버 컴포넌트에서 사용 시 주의점
App Router를 사용하는 Next.js 13 이상에서는 서버 컴포넌트에서도 Image 컴포넌트를 사용할 수 있습니다. 단, 동적 src를 사용하는 경우 주의해야 합니다:
// 서버 컴포넌트
async function ProductImage({ productId }) {
const product = await getProduct(productId);
return (
<Image
src={product.imageUrl} // 동적 src
alt={product.name}
width={500}
height={500}
/>
);
}
이런 경우 next.config.js에 해당 도메인을 추가해야 합니다.
2. 로컬 개발 시 제한사항
이미지 최적화는 프로덕션 빌드에서 가장 잘 작동합니다. 개발 모드에서는 일부 최적화가 적용되지 않을 수 있습니다.
3. 이미지 로더 제한
내장 이미지 최적화는 Node.js 기반 환경에서만 작동합니다. 정적 내보내기(Static Export)를 사용하는 경우 Cloudinary나 Imgix 같은 외부 최적화 서비스를 사용해야 합니다.
결론
Next.js의 Image 컴포넌트는 웹 성능 최적화에 큰 기여를 합니다. 자동 이미지 최적화, 지연 로딩, 리사이징 등의 기능을 통해 Core Web Vitals 점수를 향상시키고 사용자 경험을 개선할 수 있습니다.
여기서 설명한 다양한 속성과 사용 패턴을 활용하면, 모든 디바이스에서 최적의 이미지를 제공하는 웹사이트를 쉽게 구축할 수 있습니다. 이미지가 많은 웹사이트를 개발할 때 next/image를 적극 활용하여 성능과 사용자 경험을 향상시켜 보세요.
'TypeScript' 카테고리의 다른 글
브레드크럼(Breadcrumb): 사용자 경험을 향상시키는 네비게이션 요소 (1) | 2025.04.15 |
---|---|
Next.js에서 class-variance-authority(CVA)로 재사용 가능한 UI 컴포넌트 만들기 (0) | 2025.04.14 |
Next.js Script 컴포넌트 : 최적화된 스크립트 로딩 (1) | 2025.04.13 |
웹사이트 SEO를 위한 메타데이터 최적화 완벽 가이드: 검색 노출부터 소셜 공유까지 (1) | 2025.04.11 |
React Context API: 상태 관리 (0) | 2025.04.10 |