Next Image

김동현·2022년 9월 17일
3

NextJS

목록 보기
10/12
post-thumbnail

Next Image의 장점

이미지를 최적화하지 않은 채로 배포시 원본 이미지의 크기와 유형이 그대로 불러와 사용하기 때문에 배포시에는 적합하지 않습니다.

"next/image"의 Image 컴포넌트를 사용하여 이미지를 최적화할 수 있습니다. Next Image를 사용하면 아래와 같은 장점을 가질 수 있습니다.

  1. Image 컴포넌트 사용시 이미지를 Lazy Loading 합니다. 즉, 현재 페이지내 필요한 이미지만 필요한 시점에 이미지를 자동적으로 로드해주기 때문에 불필요한 요청을 보내지 않습니다.

  2. Image 컴포넌트를 사용하면 NextJS가 요청이 들어올 때마다 각 디바이스와 브라우저에 최적화된 이미지를 생성하여 응답으로 전달해줍니다.
    디바이스마다 적절한 사이즈의 이미지를 전달하고, 크롬 브라우저의 경우 이미지를 webp 포맷으로 변경하여 전달해줍니다.

  3. 생성된 이미지는 캐싱되어 동일한 요청을 보내지 않고 캐싱된 이미지를 사용합니다.

  4. 이미지가 로드되기 전 해당 영역의 너비가 0이었다가 로드된 이후 이미지가 너비를 차지하게 되어 레이아웃이 흔들리는 CLS(Cumulative Layout Shift) 현상이 발생하지 않도록 placeholder를 제공합니다.
    즉, 로드되기 전 이미지가 표시될 영역을 미리 표시하여 레이아웃이 흔들리지 않도록 만들어줄 수 있습니다.

Image Component

import Image from 'next/image';

import exampleImage from '../public/example.png';

// 1. Remotes Images
<Image 
  src="/example.png" // -> public 폴더 내 정적 파일들은 루트 경로로 접근, 확장자까지 작성해주어야 함
  alt="대체 텍스트" 
  width={가로 너비} 
  height={세로 너비} />

// 2. Local Images
<Image 
src={exampleImage} 
alt="대체 텍스트" />

// 3. Outer Paths
<Image 
  src="https://domain-name.com/image.png" 
  alt="대체 텍스트" 
  width={가로 너비} 
  height={세로 너비} />
  • src (필수)
    : src 어트리뷰트에는 이미지의 경로를 문자열 혹은 import한 파일을 작성해줍니다.

    • Remote Images(NextJS 서버 이미지 파일)
      : public 폴더 내 파일들은 프로젝트 빌드된 이후 NextJS 서버측 루트 경로에 존재하게 됩니다.
      빌드시에는 해당 경로의 이미지 파일에 접근할 수 없기 때문에 width, height 어트리뷰트 값을 필수로 작성해주어야 합니다.
      또한 blur 이미지도 생성하지 않기 때문에 별도로 blurDataURL 어트리뷰트 값으로 base64로 인코딩된 이미지 데이터를 작성해주어야 합니다.

    • Local Images(import한 이미지 파일)
      : 빌드시 각 파일에서 import된 정적 이미지 파일을 기준으로 자동으로 widht, height 값을 파악하여 설정되고, base64로 인코딩된 blur 이미지도 자동 생성하여 별도의 작업 없이 placeholder="blur"를 사용할 수 있습니다.

    • Outer Path(외부 절대 경로)
      : 값으로 외부의 이미지 파일 절대 경로로 작성할 수 있습니다. 그리고 next.js.config 파일에서 따로 사용되는 도메인 이름을 작성해주어야 합니다.
      Remote Images처럼 빌드시에는 해당 경로에 접근하지 않아 width, height 값을 필수로 작성해주어야 하며, blur 이미지도 생성해주지 않기 때문에 따로 blurDataURL 값으로 blur 이미지를 base64로 인코딩된 값을 작성해주어야 합니다.

  • alt (필수)
    : 이미지의 대체 텍스트를 문자열로 작성해줍니다.

  • layout
    : 이미지를 뷰포트가 변경될 때 어떤 너비로 렌더링할지 지정

    • instrinsic(기본값)
      : width, height 어트리뷰트 값으로 이미지 렌더링
      만약 이미지의 부모 요소의 너비가 이미지 사이즈보다 작아지는 경우 이미지 너비도 그에 맞게 줄어듭니다.

    • fixed
      : 부모 요소의 너비와는 상관없이 width, height 어트리뷰트 값으로 렌더링. 즉, 뷰포트가 변경되더라도 이미지 너비 변경되지 않고 width, height 값으로 고정됩니다.

    • responsive
      : 부모 요소의 display 속성값이 반드시 block이어야 합니다.
      부모 요소의 가로 너비 100%를 차지하도록 이미지가 렌더링됩니다. 렌더링될 때 항상 이미지의 비율이 일정하게 유지됩니다.

    • fill
      : position: relative;인 상위 요소의 가로, 세로 너비 100%를 차지하도록 렌더링됩니다.
      즉, 언제나 부모 요소의 가로, 세로 너비 전체를 채우게 됩니다. reponsive처럼 이미지가 일정한 비율로 유지되지 않고 렌더링됩니다.

  • width (필수, 로컬 이미지 혹은 layout="fill"인 경우 제외)
    : layout이 "intrinsic", "fixed"인 경우 렌더될 이미지의 가로 너비
    "responsive""fill"인 경우 이미지의 원본 가로 너비를 숫자값으로 작성(이미지 비율을 추정하는데 사용)

  • height (필수, 로컬 이미지 혹은 layout="fill"인 경우 제외)
    : layout이 "intrinsic", "fixed"인 경우 렌더될 이미지의 세로 너비
    "responsive""fill"인 경우 이미지의 원본 세로 너비를 숫자값으로 작성(이미지 비율을 추정하는데 사용)

  • placeholder
    : 이미지가 로드되는 동안 사용될 placeholder 설정. empty와 blur 값 작성 가능
    기본값은 "empty"이며 이미지가 로드되기 전 이미지가 렌더링될 영역을 빈 공간으로 설정
    "blur" 값은 blurDataURL 어트리뷰트 값으로 작성한 이미지가 로드되기 전에 이미지 영역에 표시됩니다.
    로컬 이미지인 경우 placeholder 값을 blur로만 설정해주면 빌드시 생성된 blur 이미지가 자동적으로 로드되기 전 이미지 영역에 표시됩니다.

  • blurDataURL
    : placeholder 어트리뷰트 값이 blur인 경우에 사용되며, 로드되기 전 이미지가 렌더링될 영역에 표시할 이미지를 base64 형식으로 인코딩된 이미지 데이터를 작성

srcset 어트리뷰트

srcset이란 뷰포트 너비에 따라 로드될 이미지 후보들을 설정하는 CSS 속성입니다. 이때 srcset에 작성된 이미지 파일들은 뷰포트 너비에 맞는 이미지를 로드하여 렌더링되며 렌더링될 최적화 너비는 sizes CSS 속성을 통해 작성할 수 있었습니다.

NextJS는 srcset 어트리뷰트를 자동으로 설정하여 이미지 후보들을 생성하고 뷰포트 너비에 따라 로드될 이미지 후보들 중에서 선택하여 로드합니다 .


layout이 "intrinsic"이나 "fixed"인 경우 1x와 2x, 즉 2개의 srcset만 생성하여 최초 이미지를 생성하고 로드하는데 상대적으로 빠릅니다.

layout이 "responsive""fill"인 경우 next.config.js의 next.config.js의 imageSizes, deviceSizes에 의해 srcset이 생성됩니다.

next.config.js 파일의 imageSizes, deviceSizes의 기본값은 아래와 같습니다.

// next.config.js

module.exports = {
    images: {
        // 기기의 너비 중단점 목록
        deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840]
    
        // 이미지 가로 너비(px) 목록, 
        // deviceSizes 배열과 연결되어 이미지 srcset 생성하는데 사용
        imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
    },
}

deviceSizes는 디바이스의 중단점 목록을 작성합니다. 사용자의 기기에 따라 올바른 이미지를 제공하기 위해서 사용됩니다.

imagesSizes는 이미지의 너비 목록을 작성합니다. 이 너비들은 deviceSizes 배열과 연결되어 srcset을 생성하는데 사용됩니다.

명시된 모든 사이즈를 포함하는 srcset을 가지게 되며 지나치게 세분화된 사이즈에 대응되는 이미지 파일을 생성하고 로드하게 됩니다.

sizes 어트리뷰트

Image 컴포넌트에는 sizes 어트리뷰트를 작성하여 현재 뷰포트의 너비에 따라 로드될 이미지를 설정할 수 있습니다.

sizes 어트리뷰트는 layuout 어트리뷰트 값이 "responsive""fill"인 경우에만 사용되는 어트리뷰트 입니다.

next.config.js의 deviceSizes와 imageSizes를 통해 자동적으로 srcset이 설정되어 뷰포트 너비에 따라 최적화된 이미지가 로드됩니다. srcset만 사용하는 경우 브라우저가 뷰포트의 너비에 따라 로드될 이미지를 결정합니다.

만약 이를 변경하고자 한다면 Image 컴포넌트에 sizes 어트리뷰트로 직접 뷰포트 너비에 따라 로드될 이미지를 설정할 수 있습니다.
주의할 점으로 html sizes 어트리뷰트와는 달리 렌더링되는 너비를 설정하지는 않습니다. 단지 로드될 이미지 파일만을 설정할 수 있습니다.

sizes 어트리뷰트의 기본값은 "100vw"로 srcset 어트리뷰트에 작성된 이미지 후보들 중에서 현재 뷰포트의 가로 너비 100% 값에 최적화된 이미지 파일을 로드하여 사용합니다.

만약 sizes 값으로 "500px"을 작성한다면 뷰포트가 500px일 때 해당되는 이미지 파일 하나만을 계속해서 사용하게 됩니다.


import Image from 'next/image';

<Image 
  src="경로" 
  alt="대체텍스트"
  layout="responsive"
  sizes="(max-width: 768px) 50vw,
         (max-width: 1024px) 100vw" />

위 코드에서 sizes 어트리뷰트 값으로 인해 뷰포트가 768px미만인 경우에는 뷰포트 가로 너비 50%일 때 해당되는 이미지를 로드하고, 768px 이상 1024px 미만 경우에는 뷰포트 가로 너비 100%일 때 해당되는 이미지를 로드하도록 설정되어 있습니다.

profile
Frontend Dev

0개의 댓글