[HEATH 프로젝트] NextJS의 Image 태그를 활용한 이미지 최적화

Zoey·2023년 11월 10일
0

HEATH project

목록 보기
3/3
post-custom-banner

Next/Image 적용 이유

파일 사이즈가 커서 이미지가 점진적으로 로딩되는 상태로 인한 페이지가 뚝뚝 끊겨 보이는 현상을 방지하기 위해서 NextJS의 Image 태그를 적용해보려 한다.

Next/Image 컴포넌트의 기능

Next/Image 컴포넌트에서 제공하는 대표적인 기능은 다음의 3가지이다.

  • lazy loading
  • 이미지 사이즈 최적화
  • placeholder 제공
    각 기능에 대해 어떤 이점이 있는지 정리해보자

lazy loading

lazy loading에 대해서 간단하게 설명하자면, 이미지 로드하는 시점을 필요할 때까지 지연시키는 기술을 의미한다. 예를 들어 스크린 밖에 있는 이미지들은 로딩을 지연시키고 스크린 안에 있는 이미지만을 로드해서, 불필요한 대역폭 사용을 줄이고 필요한 이미지만 빠르게 로드할 수 있도록 하는 것이다.

모든 브라우저에서 잘 동작하는 lazy loading을 구현하기 위해서는 Intersection Observer 혹은 scroll 이벤트를 통해 스크린에 element가 보일 때를 캐치하여 이미지를 로드하도록 구현해야 한다.(크롬 76 버전 이상부터는 img 태그에 loading="lazy" 속성을 추가하면 간단하게 적용할 수 있다.) 즉, FE 개발자라면 반드시 알아야하는 부분이다.

Next/Image를 사용하게 되면 자동으로 lazy loading이 적용된다. 물론 중요한 이미지 일부에 lazy loading을 적용하고 싶지 않은 경우 해당 기능을 끌 수도 있다. Image 컴포넌트의 priority라는 prop을 true로 설정하거나, loading prop에 eager 값을 설정하면 된다. prioty 값을 설정하는 것이 더 권장되는 방식이다.

Next/Image를 적용함으로써 100개의 이미지를 로드하던 기존 방식에서 스크린 내에 노출되는 이미지 26개만 로드되도록 변경할 수 있다. 이를 통해 기존보다 페이지 로드가 빨라진다,

이미지 사이즈 최적화

기존 표시되는 영역에 비해 5배가 큰 이미지를 로드한다고 생각해보자. Next/Image는 디바이스 크기 별로 srcSet을 미리 지정해두고, 사용자의 디바이스에 맞는 이미지를 다운로드할 수 있게 지원한다. layout prop 설정에 따라 어떤 srcSet 목록이 변경된다. 또한 Next.js는 이미지를 webp와 같은 용량이 작은 포맷으로 이미지를 변환해서 제공한다.

적용 결과 디바이스 크기에 맞게 작은 이미지를 서빙하고 jpeg에서 webp 포맷으로 변경되어, 기존 스테이지에서 사용하던 500KB의 이미지가 40KB의 용량으로 1/12 이상 줄어들었다.

사용자의 디바이스에 맞는 이미지 사이즈를 만들고, 용량이 작은 webp 포맷으로 변환하는 작업은 이미지에 대한 최초 요청 시에 Next.js 서버에서 진행된다. 이후 요청에는 캐시가 만료될 때까지 캐시 된 이미지가 제공되기 때문에 첫 번째 요청보다 훨씬 빠르게 이미지를 서방할 수 있다. 캐시가 만료된 후 요청이 들어오면 오래된 이미지를 우선 제공하고, 백그라운드에서 이미지 최적화를 다시 진행한다.

이미지가 캐싱되는 기간은 next.config.js의 images.minimumCacheTTL 구성 또는 CDN에서 응답한 이미지의 Cache-Control 헤더 중 더 큰 것으로 정의된다.

페이지에 접근 시 다운로드 되는 이미지 총용량이 기존 25MB에서 589KB로 감소된 걸 확인할 수 있었다.

placeholder 제공

어떤 웹 사이트에 방문했을 때 이미지가 로드되기 전까지 영역의 높이가 0이었다가 이미지가 로드된 후 이미지만큼 영역이 늘어서 레이아웃이 흔들리는 바람에 다른 링크를 클릭하는 경험을 해본 적이 있을 것이다. 이를 CLS(Cumulative Layout Shift)라고 부른다. Next/Image는 레이아웃이 흔들리는 현상을 방지하기 위해 placeholder를 제공한다. 이미지가 로드되기 전에는 이미지 높이만큼 영역을 표시해서 이미지가 로드된 후에 레이아웃이 흔들리지 않도록 하는 것이다. placehldoer는 빈 영역 또는 blur 이미지(로컬 이미지의 경우 bulid 타임에 생성, 리모트 이미지의 경우에는 base64로 인코딩된 data url을 지정해 줘야 한다.)로 적용할 수도 있고, 커스텀하게 설정할 수도 있다.

Image의 장점

  • 성능 향상: 디바이스마다 적절한 사이즈의 이미지를 서빙하고, webp와 같은 작은 용향의 포맷을 사용함
  • 시각적인 안정성: 이미지 로드 전 placeholder를 제공하여 CLS 방지
  • 빠른 페이지 로딩: viewport에 들어왔을 때만 이미지를 로드하고, 작은 사이즈의 blur 이미지를 미리 로딩하여 사용자에게 더 빠른 페이지를 보여줄 수 있다.

사용법

로컬 이미지의 경우

import image from 'next/image';
import profilePic from '../public/me.png';

function Me() {
	return (
    	<Image
      		src={profilePic}
			alt="picture of me"
			placeholder="blur" 
			/*
            로딩 이미지의 경우 빌드 타임에 import 된 이미지 파일을 기준으로 
			자동으로 width, height를 지정하고, base64로 인코딩된 blur 
			이미지가 생성되어 별도의 작업 없이 placeholder="blur"를 사용할 
            수 있다.
            */
      	/>
    )
}

리모트 이미지의 경우

// next.config.js
module.exports = {
  images: {
    domains: ['your-cdn-image-domain'],
  },
};

리모트 이미지의 경우 Next.js 서버에서 이미지를 가지고 있는 리모트 서버에 직접 요청을 하기 때문에 모든 url에 대한 접근을 허용할 경우 악의를 가진 사용자에 의해 공격을 받은 가능성이 있다. 이를 방지하기 위해 이미지를 서벙하는 서버가 안전한 서버라는 것을 Next.js에 알려줘야 한다.
next.config.js 파일에 CDN의 host를 명시해야 한다.

import Image from 'next/image';

export default function Me() {
  return <Image src="/me.png" alt="Picture of me" width={500} height={500} />;
}

리모트 이미지의 사용법은 로컬 이미지와 거의 동일하다 이미지 파일을 import 하는 대신 src에 이미지 경로를 작성하면 된다. 로컬 이미지와 달리 리모트 이미지의 경우에는 빌드 타임에 이미지 파일에 접근하는 것이 불가능하기 때문에 width, height 정보를 기입해 줘야 하고, blur 이미지도 생성되지 않는다. blur 이미지도 생성되지 않는다. 이미지가 로드되기 전 placeholder로 blue 이미지를 사용하고 싶은 경우에는 별도로 blurDataURL 속성에 base64로 인코딩된 이미지 데이터를 작성해 줘야한다.

Image의 layout 속성

Next/Image 컴포넌트에는 컨테이너 사이즈가 변경되었을 때 이미지 레이아웃이 어떻게 변경될지를 정할 수 있는 layout이라는 prop이 있다.

  • intrinsic: deafult값, 컨테이너 사이즈가 이미지 사이즈보다 작아졌을 때 컨테이너에 맞게 크기를 줄임
  • fixed: (컨테이너 사이즈와 관계없이)이미지 사이즈를 width, height 속성 값으로 고정
  • reponsive: 작은 컨테이너에서는 크기가 줄어들고, 큰 컨테이너에서는 크기가 늘어남(이미지 비율 유지)
  • fill: relative 포지션을 가진 조상의 너비, 높이와 동일하게 조정함, 주로 odjectFit 속성과 함께 사용됨
    이외의 자세한 속성들은 공식문서를 참조
profile
프론트엔드 개발자가 되기위해 기록하고 공유하는 Zoey 블로그입니다.
post-custom-banner

0개의 댓글