thumbnail

Next.js에서 이미지 블러 적용하기

Next.js에서 이미지 블러를 적용하여 UI/UX를 개선하는 방법을 알아봅니다.

Contents

Static Image

먼저 정적 이미지에 blur를 적용하는 방법을 알아보겠습니다.

정적 이미지에서 blur를 적용하려면 <Image/>placeholder 속성을 blur로 설정하면 됩니다.

Static Image 정적 이미지

src/app/static/page.tsx
import Image from "next/image";
import Link from "next/link";
import BackgroundImage from "@/../public/background.webp";
 
export default function StaticPage() {
  return (
    <div className="p-10">
      <Link href="/static">
        <h1 className="text-4xl font-bold">Static</h1>
      </Link>
      <Image
        src={BackgroundImage}
        alt="background"
        placeholder="blur"
        width={330}
        height={120}
      />
    </div>
  );
}

Dynamic Image

다음은 동적 이미지에 blur를 적용하는 방법을 알아보겠습니다.

동적 이미지의 경우 두 라이브러리의 설치가 필요합니다.

pnpm install plaiceholder sharp

설치 후 getBlurDataURL 함수를 만들어 사용합니다.

src/utils/getBlurDataURL.ts
import { getPlaiceholder } from "plaiceholder";
import fs from "fs";
import path from "path";
 
const getBlurDataUrl = async (imgSrc: string) => {
  try {
    if (imgSrc.startsWith("/")) {
      const publicDir = path.join(process.cwd(), "public");
      const filePath = path.join(publicDir, imgSrc);
 
      if (!fs.existsSync(filePath)) {
        console.error(`이미지 파일이 존재하지 않습니다: ${filePath}`);
        return "";
      }
 
      const buffer = fs.readFileSync(filePath);
      const { base64 } = await getPlaiceholder(buffer, { size: 10 });
      return base64;
    } else {
      const buffer = await fetch(imgSrc).then(async (res) =>
        Buffer.from(await res.arrayBuffer())
      );
      const { base64 } = await getPlaiceholder(buffer, { size: 10 });
      return base64;
    }
  } catch (e) {
    console.error("Blur 이미지 생성 오류:", e);
    return "";
  }
};
 
export default getBlurDataUrl;

함수를 만든 뒤, 동적 이미지에 정적 이미지와 같이 placeholder 속성을 blur로 설정합니다. 그리고 getBlurDataURL을 호출하여 blurDataURL을 가져옵니다.

src/app/dynamic/page.tsx
import Image from "next/image";
import Link from "next/link";
import getBlurDataUrl from "@/utils/getBlurDataURL";
 
const ImageList = [
  { src: "/1.webp", alt: "1" },
  { src: "/2.webp", alt: "2" },
  { src: "/3.webp", alt: "3" },
  { src: "/4.webp", alt: "4" },
];
 
export default function DynamicPage() {
  return (
    <div className="p-10">
      <Link href="/dynamic">
        <h1 className="text-4xl font-bold">Dynamic</h1>
      </Link>
      {ImageList.map(async (image, index) => {
        const blurDataURL = await getBlurDataUrl(image.src);
        return (
          <Image
            width={400}
            height={225}
            key={index}
            src={image.src}
            alt={image.alt}
            placeholder="blur"
            blurDataURL={blurDataURL}
          />
        );
      })}
    </div>
  );
}

Dynamic Image 동적 이미지

라이브러리 사용하기

만약 함수를 직접 추가하는 것이 아닌 라이브러리 사용을 원하신다면 next-image-blur 라이브러리를 사용할 수 있습니다.

참고 사항

위 첨부된 gif를 보신다면 개발자 도구 내 Network 탭에서 data:image로 시작하는 blur 이미지가 먼저 전송되고 이후 image?url=로 시작하는 원본 이미지가 전송되는 것을 확인할 수 있습니다. 하지만 개발 서버를 사용 중 이거나 캐시가 남아있다면 원본 이미지가 blur 이미지보다 먼저 전송될 수 있습니다. 이에 따라 적용을 확인하기 위해서는 인터넷 사용기록을 삭제하고 Network 탭의 throttle 설정을 조절하여 확인해주세요.

chrome 인터넷 사용기록 삭제

그래도 안된다면 build 후 start 명령어로 확인해보시길 바랍니다.

GitHub 코드 확인

예제 페이지 확인

🔗 공유