🚀   새로운 블로그로 이전했습니다.

Next.js 블로그 Image Optimization

2022.11.14
3분

기본적으로 next/image를 활용하면 이미지를 최적화시킬 수 있습니다.
하지만 static-html-export 환경에서는 이를 제공해주지 않는다고 합니다.

Custom Loader를 활용해야한다고 하는데 갈 길이 보이지 않습니다...
라이브러리의 도움을 받아 보도록 합시다!

next-export-optimize-images

github star가 100개 정도인 조금은 빈약한 오픈소스 라이브러리입니다.
하지만 기존 next/image의 option에 100% 호환할 만큼 강력하고 적용하는 방법 또한 간편하기에 이를 사용해보기로 했습니다.

아래 기능들을 제공해준다고 합니다.

  • Optimize images at build time.
  • All options for next/image available
  • Convert formats (png → webp, etc.)
  • Download external images locally.
  • Using sharp, so it's fast.
  • Cache prevents repeating the same optimization
  • Support TypeScript
  • Support next/future/image

환경 세팅하기

공식문서 참고하면 되는데 아래 설정파일 하나면 끝입니다 🫢

next.config.js

const withExportImages = require('next-export-optimize-images');

/** @type {import('next').NextConfig} */
const nextConfig = withExportImages({
  //...
});

module.exports = nextConfig;

next export 이후에 따로 최적화 빌드를 실행해줘야 합니다.

{
  "scripts": {
    "build": "next build && next export && next-export-optimize-images"
  }
}

실험 해보기

공식문서대로 placeholder 속성을 지정해보겠습니다.

import Image from 'next/image';

//...

<Image
  src="/forest.jpg"
  alt="forest"
  width={324}
  height={486}
  placeholder="blur"
  className="h-auto"
/>;

dev 환경에서의 변환 결과

<img
  alt="forest"
  srcset="/forest.jpg?width=384 1x, /forest.jpg?width=750 2x"
  src="/forest.jpg?width=750"
  width="324"
  height="486"
  decoding="async"
  data-nimg="1"
  class="h-auto"
  loading="lazy"
  style="color: transparent;"
/>

build 환경에서의 변환 결과

<img
  alt="forest"
  srcset="
    /_next/static/chunks/images/forest_384_75.jpg 1x,
    /_next/static/chunks/images/forest_750_75.jpg 2x
  "
  src="/_next/static/chunks/images/forest_750_75.jpg"
  width="324"
  height="486"
  decoding="async"
  data-nimg="1"
  class="h-auto"
  loading="lazy"
  style="color: transparent;"
/>

dev 환경에서는 사진 원본을 사용하며 build를 거친 후 3000px 이상의 image가 700px대로 잘 최적화되었습니다!

// 로딩 중
style = "color:transparent;background-size:cover;background-position:50% 50%;background-repeat:no-repeat;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http%3A//www.w3.org/2000/svg' viewBox='0 0 324 486'%3E%3Cfilter id='b' color-interpolation-filters='sRGB'%3E%3CfeGaussianBlur stdDeviation='20'/%3E%3C/filter%3E%3Cimage preserveAspectRatio='none' filter='url(%23b)' x='0' y='0' height='100%25' width='100%25' href='/_next/static/chunks/images/forest_8_10.jpg'/%3E%3C/svg%3E")";

// 로딩 완료
style = 'color: transparent;';

이미지가 로딩되기 전에 background-image로 placeholder를 표시합니다.
하지만 blur된 이미지는 잘 표시되는진 않는 것 같습니다...

230107-164837

언젠가는 새로 손을 봐야할 것 같군요...