[NEXT.js] 넥스트 JS를 배워보자 3편 - 최적화된 이미지 컴포넌트

2022. 2. 28. 20:29Library,Framework

728x90

개인적으로 Next JS를 처음 접했을 때 가장 흥미로웠던 건 이미지 최적화 (Image Optimization) 관련 부분이었다. 

그냥 React로 이미지 처리를 해야할 경우 뷰포트에 따라 resizing 작업 및 이미지가 뷰포트에 들어와야 로딩이 되도록 lazy loading 등, 성능 향상을 위해 신경써야할 부분을 꽤 있는데 이걸 기본으로 처리해준다.

 

Guide on Lazy Load Images

 

eslint를 사용하고 있다면 next js에서 기존 <img/> 태그를 사용했을 시 아래와 같은 경고를 봤을 수도 있을 것이다

 

Do not use <img/>. Use Image from 'next/image' instead. See https://nextjs.org/docs/messages/no-img-element.eslint@next/next/no-img-element

 

next에서 기본적으로 제공하는 최적화 기능들을 사용하지 않을 거라면 무시해도 되지만

그렇지 않은 경우 위에서 안내한 대로  next js에서 제공하는 태그의 확장 컴포넌트인 <Image/> 컴포넌트를 사용하면 된다.

 

공식문서에 따르면 Image 컴포넌트 사용 시 아래의 이점들을 취할 수 있다.

 

  • 향상된 성능 (Improved Performance): 언제나 디바이스 사이즈에 맞게 최적화된 이미지를 제공하다
  • 시각적 안전감 (Visual Stability): CLS(Cumulative Layout Shift)를 방지해준다. 
  • 빠른 페이지 로드 (Faster Page Loads):  이미지가 뷰포트에 들어왔을 경우만 로드되기 때문에 초기 로드 속도가 빠름.
  • 유연한 에셋 관리 (Asset Flexibility): 외부에 저장되어 있는 이미지까지도 리사이징 가능

그럼 image 컴포넌트를 제대로 사용하기 위해 어떤 props가 있는지 예시를 보며 확인해보자.

 


<Image/> 컴포넌트

필수 - Required props

 src (이미지 소스)

아래 두 개 중 하나의 형식으로 전달해줘야 한다

  1. 정적으로 불러온 이미지 파일 전달
import Image from "next/image";
import randomPic from '../public/randomPick.png';

<Image src={randomPick} width={500} height={500}/>

  2. 외부 path를 string 형식으로 전달

import Image from "next/image";

<Image src="https://firebasestorage.googleapis.com/v0/b/junglee-habit.appspot.com/o/challanges%2FIMQBHIsoNIMngElt9sRf%2F0aWv3BRsSVJMcz5yU4uS?alt=media&token=6dce71b4-e11f-4fa3-9b5a-fab54bb100d8" width={500} height={500}/>

* 보안상의 이유로 외부 path입력 시 루트에 있는 next.config.js 설정 파일에 해당 domain을 입력해줘야 한다.

위 예제 같은 경우는 호스팅 도메인이 파이어 스토리지이기 때문에 아래와 같이 작성해줬다

// next.config.js
module.exports = {
  reactStrictMode: true,
  images: {
    domains: [
      "firebasestorage.googleapis.com",
    ],
  },
};

 

여기까지는 기존의 img 태그랑 크게 다른 점은 없지만 Image 컴포넌트에는 width랑 height 픽셀 값이 필수적으로 들어가야 한다 (빌드 타임 때 계산이 가능한 정적으로 불러온 이미지 + 이후에 알아볼 layout props가 fill인 이미지는 제외).

 

width랑 height를 필수적으로 입력해야 하는 이유는 CLS(Cumulative Layout Shift)를 방지하기 위해서이다.

 


width - 너비 (유닛 없이 입력 시 pixel)

height - 높이 (유닛 없이 입력시 pixel)

 


옵셔널  - Optional Props 

아래에 언급할 props가 전부는 아니며 일단은 프로젝트를 진행했을 때 가장 많이 썼던 props 위주로 정리를 해보았다. 

더 자세한 내용은 공식문서를 참고하길 바란다.

 

layout (뷰포트 변경 시 이미지 레이아웃 처리 방식)

 

intrinsic (기본)

 

큰 화면에서는 지정된 너비와 높이를 유지하지만 작아질수록 부모 컨테이너 요소에 맞게 바뀜

예시 보기

 

fixed

 

지정한 너비와 높이를 화면 상관없이 계속 유지함

예시 보기

 

responsive

 

부모 컨테이너 요소가 display:block 일 경우 이미지가 그에 맞게 바뀜 

예시 보기

 

fill

 

부모 요소의 position 값이 relative일 경우, 이미지가 부모 컨테이너 요소에 맞게 늘어남.

보통 objectFit 속성이랑 같이 사용됨.

예시 보기

 


quality

 

이미지의 품질을 직접 지정할 수도 있다. 1(낮음) ~ 100(높음) 사이 숫자를 입력한다.


priority 

 

우선 로드되어야 할 이미지에게 해당 props를 전달해주면 우선으로 로드한다.
해당 props가 전달된 이미지는 lazy loading이 적용되지 않고 바로 로드된다. 해당 props를 남발하게 되면 최적화의 의미가 사라짐으로 정말 중요한 이미지 대상으로만 적용하도록 하자.


placeholder

 

empty(기본), blur,

 

이미지가 로딩 중일 때 표시할 대체 이미지.

물론 최적화도 중요하지만 사용자들에게 해당 이미지가 로드되고 있다는 걸 명확히 전달하는 것도 중요하다.

이때 사용할 수 있는 게 해당 prop이다. 

 

placeholder="blur"와 함께 blurDataURL="블러 처리된 비교적 작은 이미지 url"를 전달해주게 되면,

네트워크가 느린 환경에서 이미지를 로드할 때 흐린 이미지에서 뚜렷해지는 효과를 볼 수 있다. 

서버에서 동적으로 흐린 이미지를 생성하기 위해서는 https://blurha.sh/ ,

정적인 이미지 파일이 필요하다면 https://plaiceholder.co/ 같은 툴을 추천한다

 

blur 로딩 처리

 

출처: https://nextjs.org/docs/api-reference/next/image

 

next/image | Next.js

Enable Image Optimization with the built-in Image component.

nextjs.org