[Next.js] Image 컴포넌트

조아영·2024년 10월 2일

📌

Next.js Image 컴포넌트는 Next.js에서 제공하는 이미지 최적화 도구입니다. 이 컴포넌트를 사용하면 이미지 크기, 형식, 품질을 자동으로 최적화하여 페이지 로딩 속도를 높이고 성능을 개선할 수 있습니다. 개발자가 직접 이미지 최적화 작업을 하지 않아도, 브라우저와 네트워크 상황에 맞춘 최적화된 이미지를 제공합니다.

◼ 주요 기능과 사용법

Lazy Loading

Lazy Loading은 사용자의 뷰포트에 이미지가 들어왔을 때만 로드되도록 하여 초기 페이지 로딩 시간을 단축시키고, 불필요한 데이터 사용을 줄입니다. 중요한 이미지는 priority 속성을 통해 Lazy Loading을 비활성화할 수 있습니다.

// 중요하지 않은 이미지는 기본 설정으로 Lazy Loading 적용
import Image from 'next/image';

function SampleImage({ src, alt }) {
  return <Image src={src} alt={alt} width={100} height={150} />;
}

// 중요한 이미지는 Lazy Loading 비활성화
function ImportantImage({ src, alt }) {
  return <Image src={src} alt={alt} width={100} height={150} priority />;
}

이미지 사이즈 최적화

Next.js는 사용자의 디바이스 크기에 맞춰 이미지를 최적화합니다. 이를 통해 이미지 용량을 최소화하며, WebP와 같은 이미지 형식으로 변환하여 용량을 줄입니다. 로컬 이미지의 경우 widthheight 속성을 지정하지 않아도 자동으로 적용됩니다. 원격 이미지를 사용할 때는 next.config.js 파일에 이미지 도메인을 명시해야 합니다.

// next.config.js 설정
module.exports = {
  images: {
    domains: ['cdn.example.com'],
  },
};

// 리모트 이미지 적용 예시
import Image from 'next/image';

function RemoteImage({ src, alt }) {
  return (
    <Image
      src={`https://cdn.example.com/${src}`}
      alt={alt}
      width={100}
      height={150}
    />
  );
}

Placeholder 제공

이미지가 로드되기 전에 Placeholder를 제공하여 레이아웃이 흔들리는 현상(CLS)을 방지할 수 있습니다. Placeholder로 빈 영역이나 블러 효과를 적용할 수 있습니다.
로컬 이미지는 placeholder="blur" 속성을 사용하고, 외부 이미지는 blurDataURL을 사용하여 Base64 인코딩된 작은 이미지를 지정해야 합니다.

// 로컬 이미지
<Image src={localImage} alt="Example" placeholder="blur" />

// 리모트 이미지
<Image
  src={remoteImage}
  alt="Example"
  width={100}
  height={150}
  placeholder="blur"
  blurDataURL="data:image/png;base64,..."
/>

◼ 한계점

모든 파일 형식 최적화 불가

Next.js는 애니메이션 이미지(SVG, WebP, GIF)의 최적화를 지원하지 않습니다.

서버 부하 증가

서버에서 이미지 다운로드 및 변환을 처리하므로 서버 부하가 증가할 수 있습니다. 특히 이미지가 많을수록 서버의 부담이 커집니다. 기본적으로 Next.js는 16개의 다양한 사이즈로 이미지를 최적화하지만, 필요한 사이즈만 생성하도록 조정하여 서버 자원을 절약할 수 있습니다.

// next.config.js
module.exports = {
  images: {
    deviceSizes: [640, 750, 828],
    imageSizes: [16, 32, 48],
  },
};

비용 이슈

Next.js 이미지 최적화는 무료로 1000개의 이미지까지 제공되지만, 그 이상은 추가 비용이 발생합니다. 비용 절감을 위해 최적화가 불필요한 작은 이미지는 unoptimized 속성을 사용할 수 있습니다.

<Image src={smallImage} alt="Small Image" unoptimized />

◼ Image 컴포넌트를 사용하지 않는 최적화 대안

이미지 형식을 미리 최적화

이미지를 미리 WebP 또는 AVIF 형식으로 변환하고, <picture> 태그를 사용하여 브라우저 호환성을 확보할 수 있습니다.

<picture>
  <source srcset="image.avif" type="image/avif">
  <source srcset="image.webp" type="image/webp">
  <img src="image.jpg" alt="예제 이미지">
</picture>

HTML의 loading="lazy" 속성 사용

이미지를 뷰포트에 들어올 때까지 로드하지 않도록 지연시켜 초기 로딩 속도를 향상시킬 수 있습니다.

<img src="image.jpg" alt="예제 이미지" loading="lazy">

priority 속성 사용

중요한 이미지를 우선적으로 로드하여 사용자에게 빠르게 보여줍니다. 일부 브라우저와 라이브러리에서 지원하는 fetchpriority 속성을 사용하여, 중요한 리소스를 우선 로드할 수 있습니다.
다만, 모든 브라우저에서 지원되지 않을 수 있기 때문에, 핵심 이미지에만 사용하는 것이 좋습니다. 과도한 사용은 성능 저하를 유발할 수 있으니 주의해야 합니다.

<img src="image.jpg" alt="예제 이미지" fetchpriority="high">

Prefetch 및 Preload 사용

브라우저가 페이지 렌더링 전에 미리 중요한 리소스를 로드하도록 하는 방법입니다.

link 태그를 활용하여 미리 이미지를 로드합니다. prefetch는 페이지 렌더링 이후의 리소스 로드에 적합하고, preload는 즉시 필요한 리소스에 적합합니다.

<link rel="prefetch" href="image.jpg" as="image">
<link rel="preload" href="critical-image.jpg" as="image">

JavaScript를 이용한 프리패칭

동적으로 여러 이미지를 미리 로드하여, 사용자가 해당 이미지를 요청하기 전에 준비해 놓습니다.

function preloadImages(...imageUrls) {
  imageUrls.forEach((url) => {
    const img = new Image();
    img.src = url;
  });
}

// 프리로드할 이미지 URL 배열
const imagesToPreload = [
  'image1.jpg',
  'image2.jpg',
  'image3.jpg',
];

// 페이지 로드 후 이미지 프리로드 실행
window.addEventListener('load', () => {
  preloadImages(...imagesToPreload);
});

SVG 이미지 사용

로고나 아이콘 같은 단순한 그래픽은 SVG 형식을 사용하면 해상도에 관계없이 선명하게 표시되며, 파일 크기도 작습니다. JSON 기반으로 애니메이션을 만들어주는 Lottie를 사용하는 방법도 있습니다.

<img src="logo.svg" alt="로고">

CDN(Content Delivery Network) 활용

CDN을 활용하면 지리적으로 가까운 서버에서 이미지를 제공하여 로딩 속도를 개선할 수 있습니다.이미지 파일을 CDN에 업로드하거나, 기존 서버에서 제공하는 이미지를 CDN을 통해 전달하도록 설정합니다. 이를 통해, 글로벌 사용자에게 더 빠른 응답 속도를 제공할 수 있습니다.

이미지 스프라이트 활용 (옛날 방식)

과거에는 HTTP 요청을 줄이기 위해 여러 작은 이미지를 하나의 큰 이미지로 합치는 이미지 스프라이트 기법을 사용했습니다.
CSS의 background-position을 활용하여, 큰 이미지에서 필요한 부분만 표시합니다. 이를 통해 HTTP 요청 횟수를 줄일 수 있지만, 최근에는 주로 Lazy Loading이나 CDN을 활용하여 이미지 성능을 개선하는 방식이 더 많이 사용됩니다.

image

.icon {
  background-image: url('image.png');
}

.icon-home {
  background-position: 0 0;
  width: 32px;
  height: 32px;
}

.icon-settings {
  background-position: -32px 0;
  width: 32px;
  height: 32px;
}

0개의 댓글