Next.js Image 컴포넌트 심화
Next.js의 Image 컴포넌트는 자동 리사이징, WebP/AVIF 변환, 지연 로딩을 기본 제공합니다. 여기서 더 나아가 blur placeholder와 CDN 연동을 통해 사용자 경험을 극대화할 수 있습니다.
정적 이미지 blur placeholder
// 정적 import — 자동으로 blur placeholder 생성
import heroImage from '@/public/images/hero.jpg';
export default function Hero() {
return (
<Image
src={heroImage}
alt="히어로 이미지"
placeholder="blur"
priority
sizes="100vw"
quality={85}
/>
);
}
동적 이미지 blur placeholder 생성
// lib/image-utils.ts
import { getPlaiceholder } from 'plaiceholder';
export async function getBlurDataUrl(src: string) {
try {
const res = await fetch(src);
const buffer = Buffer.from(await res.arrayBuffer());
const { base64 } = await getPlaiceholder(buffer, { size: 10 });
return base64;
} catch (e) {
return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==';
}
}
export default async function PostImage({ src, alt }) {
const blurDataUrl = await getBlurDataUrl(src);
return (
<Image
src={src}
alt={alt}
width={800}
height={450}
placeholder="blur"
blurDataURL={blurDataUrl}
/>
);
}
외부 CDN 설정 (next.config.js)
/** @type {import('next').NextConfig} */
const nextConfig = {
images: {
remotePatterns: [
{ protocol: 'https', hostname: '**.cloudinary.com' },
{ protocol: 'https', hostname: 'images.unsplash.com' },
],
loader: 'custom',
loaderFile: './lib/cloudinary-loader.ts',
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048],
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
formats: ['image/avif', 'image/webp'],
},
};
module.exports = nextConfig;
Cloudinary 커스텀 로더
// lib/cloudinary-loader.ts
export default function cloudinaryLoader({ src, width, quality }) {
const params = [
'f_auto', 'c_limit',
'w_' + width,
'q_' + (quality || 'auto'),
];
return 'https://res.cloudinary.com/mycloud/image/upload/' + params.join(',') + '/' + src;
}
반응형 이미지 sizes 속성
<Image
src="/photos/landscape.jpg"
alt="풍경"
fill
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw"
style={{ objectFit: 'cover' }}
/>
{images.map((img) => (
<div key={img.id} className="relative aspect-video">
<Image
src={img.url}
alt={img.alt}
fill
sizes="(max-width: 768px) 100vw, (max-width: 1024px) 50vw, 33vw"
placeholder="blur"
blurDataURL={img.blurUrl}
/>
</div>
))}
- LCP(Largest Contentful Paint) 이미지에는 반드시
priority를 설정합니다 sizes속성을 정확히 지정해야 불필요한 큰 이미지 다운로드를 방지합니다- AVIF는 WebP 대비 20-30% 더 작지만, 인코딩 시간이 깁니다
- blur placeholder는 CLS(Cumulative Layout Shift) 방지에도 효과적입니다
이미지 최적화는 웹 성능의 가장 큰 개선 포인트입니다. Next.js Image 컴포넌트와 CDN을 적절히 조합하면 최소한의 코드로 최대의 성능 개선을 달성할 수 있습니다.
댓글 0