코린이의 개발 일지

[Next.js] Image 컴포넌트와 이미지 최적화 본문

웹 (web)/프론트엔드

[Next.js] Image 컴포넌트와 이미지 최적화

폴라민 2023. 7. 13. 00:38
반응형

Image 컴포넌트 기능

Next.js에서 제공하는 Image 컴포넌트가 기본적으로 지원하는 최적화 기능이 있다.

1. 포맷 및 사이즈 변환

용량 최소화를 위해 png 포맷에서 webp 포맷으로 변경되어 다운로드 된 것을 확인할 수 있다.

 

원래 이미지 파일 크기
실제 로드된 이미지 파일 크기

또한 원래 이미지 사이즈가 아닌 현재 컴포넌트에 맞춰서 자동으로 사이즈 변환된 것을 확인할 수 있다.

 

이러한 포맷 및 사이즈 변환 작업은 이미지에 대한 최초 요청시에 Next.js 서버에서 진행되며,

이후 요청에는 캐시가 만료될 때까지 캐시된 이미지가 제공되기 때문에 첫번째 요청보다 훨씬 빠르게 이미지를 서빙할 수 있다.

 

만약 파일 크기 및 포맷 변환을 막고 이미지 퀄리티 그대로 가져오고 싶다면 unoptimized 옵션을 false로 주면 된다.

 

2. lazy loading

Image 컴포넌트를 사용하면 기본적으로 lazy-load 설정이 되어 있다.

만약 preload 할 이미지가 있다면 priority 설정을 줘서 lazy-load 설정을 해제할 수 있다.

priority 설정이 되어있는 경우와 안되어 있는 경우 Waterfall

위 사진을 보면 priority 설정이 되어 있는 이미지의 경우 다른 css, js 파일들과 함께 다운로드 된다.(pre-load)

그외의 이미지들은 lazy-load되기 때문에 나중에 다운받아지는 것을 확인 할 수 있다.

 

스크롤을 내리지 않고 바로 보이는 이미지들은 priority 설정을 해주는 것이 좋다. 

화면에 바로 보이지 않을 이미지들은 반대로 priority 설정을 안하는 것이 성능상 좋다.

 

3. visual stability

Image 컴포넌트는 외부 이미지에 대해서도 width와 height 옵션을 강제하여, 정확한 이미지 비율을 계산해 로딩 중일 때도, layout shift가 일어나지 않도록 한다.

또한 placeholder 기능도 제공한다.

 

 

 

성능 최적화, 따로 해줘야 할까?

이미 캐싱, lazy-loading 등등 다양한 성능 최적화 기능을 지원하기 때문에 따로 부가적으로 해줄 필요는 없다.

하지만 이는 width와 height 옵션을 정확히 넘겨줬을 때만 해당한다.

 

개발을 하다보면 이미지의 정확한 사이즈를 모르는 경우도 많고, object-fit과 같은 css 속성을 사용해서 컴포넌트 사이즈에 이미지를 맞춰줘야하는 경우도 많다.

그럴때는 fill 속성을 사용하면되는데, 이것 저것 세팅해줘야 할 사항들이 좀 있다.

 

 

fill 속성 사용

fill 속성이란?

width와 height을 지정하는 것 대신 이미지가 부모 요소를 채우도록 하게 하는 boolean 타입의 props

 

이때 부모 요소는 반드시 style에 position: "relative, position: "fixed" 혹은 position: "absolute"를 지니고 있어야 한다.

사용 예시를 보자

 

div.top {
  position: relative;
  width: 300px;
  height: 300px;
}
<div className="top">
    <Image
      alt="image"
      src="/testimg.png"
      fill
      priority
      sizes="(max-width: 732px) 50vw, (max-width: 992px) 50vw, 300px"
      style={{ objectFit: "cover" }}
    />
</div>

 

object-fit 속성은 반드시 in-line으로 넣어줘야 적용된다.

위와 같이 했을 때랑, Image컴포넌트에 width와 height를 300으로 직접 지정해줬을 때는 아래와 같이 차이가 난다.

같은 이미지이지만 상단 이미지는 object-fit: cover 속성으로 내용이 종횡비를 유지하면서 정의된 너비와 높이를 가득 채울때까지 확대되었음을 확인 할 수 있다. 아래 이미지는 상대적으로 찌그러졌다.

 

따라서 이미지 사이즈 정보가 확실하지 않을 때는 fill 속성을 사용하는 것이 좋다.

 

이때 유의해야 할 점이 있다.

 

 

sizes 속성으로 이미지 최적화 해주기

위의 맨 처음 이미지 요청이 sizes속성 없이 fill 속성을 사용한 경우이고 아래 세개는 width랑 height를 고정값을 준 경우이다.

 

If you don't specify a sizes value in an image with the fill property, a default value of 100vw (full screen width) is used

Next.js 공식 문서를 보면, fill 속성을 사용할 때, sizes 값을 지정해주지 않으면 100vw가 default 값으로 설정되어 이미지를 가져오게 된다는 것이다.

따라서 아래처럼 작게만 띄워주면 되는 이미지인데도, 100vw 기준으로 이미지를 가져와 이미지 파일 크기가 매우 크게 가져오게 된다.

이는 성능을 떨어뜨리는 요인이 되기 때문에 sizes를 반드시 설정 해주어야한다.

 

fill 속성을 사용하면 기본적으로 설정되는 srcSet을 사용해 뷰포트를 가지고 인식해 로드한다.

기본적으로 아래와 같이 설정되어 있으나, 추가적인 breakpoint 커스텀이 필요하다면 next config 파일에 아래와 같이 커스텀해서 작성하면 된다.

images: {
    imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
    deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
  },

deviceSizes

디바이스 breakpoint 기준점

imagesSizes

이미지 너비 목록으로 deviceSizes와 연결되어 전체 srcSet을 형성한다.

 

 

sizes 속성을 설정해보자.

<div className="top">
    <Image
      alt="image"
      src="/testimg.png"
      fill
      sizes="(max-width: 732px) 30vw, 90vw"
      style={{ objectFit: "cover" }}
    />
</div>

위의 코드를 보면

예를 들어 viewport가 730px일 때,

732px보다 작기 때문에 (max-width: 732px) 30vw의 기준이 적용된다.

이를 바탕으로 계산해서 imageSizes 중 계산 결과 값보다 큰 사이즈 중 가장 작은 값으로 이미지를 최적화 해서 가져오게 된다.

 

 

가져온 이미지 사이즈를 보면

첫번째 이미지가 fill 속성을 적용한 이미지이다.

아까 sizes속성을 지정 안해줬을 때는 545kb였는데 현재는 61.8kb로 현저히 사이즈가 줄어든 것을 확인할 수 있다.

 

 

 

Refs.

https://fe-developers.kakaoent.com/2022/220714-next-image/

 

Next/Image를 활용한 이미지 최적화 | 카카오엔터테인먼트 FE 기술블로그

조지영(esme) 무언갈 빠르게 좋아합니다. 그래서 변화가 빠른 FE 개발이 적성에 잘 맞습니다.

fe-developers.kakaoent.com

https://velog.io/@pds0309/nextjs-%EC%B5%9C%EC%86%8C%ED%95%9C%EC%9D%98-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%B5%9C%EC%A0%81%ED%99%94%ED%95%98%EA%B8%B0

 

[nextjs] 최소한의 이미지 최적화하기

Nextjs에서의 Image 사용에 있어 최소한의 최적화 시도는 해봐야지 않겠나라는 마음가짐으로 공부하고 적용한 과정을 기록해나가고 있다.

velog.io

 

반응형
Comments