[developic] Image Component - Next.js 이미지 최적화 기능 적용

sue·2021년 4월 22일
0

developic project

목록 보기
10/28
post-custom-banner

Next.js의 장점을 SEO 초점에 맞춰 생각하다 보니 대부분 놓치게 되는 유용한 기능이 있다. 바로 Next.js에서 자체적으로 제공하는 Image Component를 통한 이미지 최적화 기능이다.

최적화되지 않은 이미지

일반 HTML을 사용하면 다음과 같이 프로필 사진을 추가한다.

<img src="/images/profile.jpg" alt="Your Name" />

이는 다음을 수동으로 처리해야 함을 의미한다.

  • 이미지가 다양한 화면 크기에서 반응하는지 확인
  • 타사 도구 또는 라이브러리로 이미지 최적화
  • 뷰포트에 들어갈 때만 이미지 로드(lazy-loading)

Next.js는 이러한 문제를 처리할 수 있는 <Image> 컴포넌트를 기본적으로 제공한다.

이미지 컴포넌트를 사용한 이미지 최적화 기능 특징

Next.js 버전 10.0.0 이후로 <Image> 컴포넌트를 통해 이미지 최적화 기능을 사용할 수 있다.

<Image> 컴포넌트를 사용한 최적화 기능 특징

  • 크기 조정 : 각 화면 크기에 맞는 파일 크기 제공

  • 외부 소스 최적화 : 모든 이미지 소스에서 작동한다. 이미지가 CMS와 같은 외부 데이터 소스에서 호스팅되는 경우에도 최적화 할 수 있다

  • 낮은 빌드 시간 : 이미지 최적화가 주문형으로 수행되므로 크기와 형식이 다른 여러 이미지를 만들 필요가 없다. 따라서 빌드 시간은 영향을 받지 않는다. (빌드시 이미지를 최적화하는 대신, 사용자가 이미지를 요청할 때 요청된 이미지를 최적화. 정적 사이트 생성기(SSG) 및 정적 전용 솔루션과 달리 빌드 시간은 이미지 10개를 전송하든 1천만개 이미지를 전송하든 증가하지 X)

  • 지연 로드(lazy-loading) : 이미지는 기본적으로 지연 로드된다. 즉, 뷰포트 외부의 이미지에 대해 페이지 속도가 불이익을 받지 않는다. 이미지는 뷰포트로 스크롤 될 때 로드된다.

  • 브라우저가 지원하는 경우 WebP과 같은 최신 형식으로 이미지의 크기를 조정하고 최적화하고 제공한다. 이렇게 하면 뷰포트가 더 작은 장치로 큰 이미지가 전송되는 것을 방지 할 수 있다.

  • 이미지는 Cumulative Layout Shift 을 피하기 위해 항상 같은 방식으로 렌더링된다. 이는 핵십 웹 필수 요소 중 하나이다. (https://web.dev/vitals/#core-web-vitals)
    => https://developers.google.com/search/blog/2020/05/evaluating-page-experience 구글의 페이지 경험 평가 기준에 반영

이렇게 이미지 컴포넌트는 서버에 무리도 덜 가고, 프론트 로딩도 빨라지게 만들면서 기존에 직접 처리해줘야 했던 이미지 관련 최적화 작업을 도와준다.

이미지 컴포넌트 필수 속성

import Image from 'next/image'

function Home() {
  return (
    <>
      <h1>My Homepage</h1>
      <Image
        src="/me.png"
        alt="Picture of the author"
        width={500}
        height={500}
      />
      <p>Welcome to my homepage!</p>
    </>
  )
}

export default Home

<Image /> 컴포넌트는 다음과 같은 속성을 필요로 한다.

  • src
    : 이미지의 경로 또는 URL, 필수 기재 사항
    외부 URL을 사용하는 경우에 next.config.js에서 domains 추가
    module.exports = {
      images: {
        domains: ['example.com'],
      },
    }
  • width
    : 이미지의 너비(픽셀), 단위가 없는 정수, 필요하지 않는 한 layout="fill"
  • height
    : 이미지의 높이(픽셀). 단위가 없는 정수, 필요하지 않는 한 layout="fill"

그 외 선택적 속성은 next/image 에서 확인할 수 있다.


<Image> 컴포넌트 적용

먼저 이미지 최적화 전 블로그 페이지의 프로필 이미지의 정보를 크롬 검사탭에서 확인해 보았다.

현재 뷰에서 렌더링 된 크기는 90 x 90px이지만, 브라우저가 서버에서 받은 이미지 크기인 고유 크기는 400 x 381px이며 이미지 원본 크기이다. 파일의 크기는 78.9kB이다.

크고 무거운 이미지를 요청한 다음 작은 크기로 표시했기 때문에 효율적이지 않다.

Next.js 없이 이미지 문제를 해결할 경우

Next.js의 도움 없이 위에서 언급한 문제를 해결하려면 어떻게 해야 할까?

  • 크기 조정의 경우 : 예를 들어 CMS에 저장된 이미지 크기가 서로 다른 경우 화면 너비를 감지 한 다음 적절한 이미지 크기를 요청하는 코드를 작성해야 한다.
  • 최신 이미지 형식 : 이미지의 WebP 버전을 생성하여 어딘가에 저장할 수 있다. 그런 다음 브라우저가 WebP 이미지를 지원하는 경우 먼저 조건부로 제공하고 그렇지 않으면 다른 형식을 제공하는 코드를 작성해야한다.
  • 지연로드의 경우 : "react-lazyload"( https://www.npmjs.com/package/react-lazyload) 와 같은 라이브러리를 사용해야 한다.

이런 방법 대신 Image 컴포넌트를 사용할 수 있다.

Next.js 적용 예제

  • <img> 태그를 사용한 기존 코드
<img src={blogUserData.avatar} alt="profile" />
  • <Image> 컴포넌트를 사용해 수정한 코드
import Image from 'next/image'

<Image src={blogUserData.avatar} alt="profile" width={90} height={90} />

이제 이미지의 고유 크기는 400 x 381px 대신 96 x 91px 이다. 그리고 파일 크기는 78.9kB 대신 1.3kB로 줄어든 것을 확인할 수 있다.

또한 네트워크 탭에서 요청된 이미지의 형식을 살펴 보자.

JPG 대신 WEBP로 제공되고 있음을 알 수 있다.

많은 작업 없이 JPG에서 WEBP로 변환된 최적화 이미지를 제공하고 있으므로, 페이지에서 방문자가 다운로드하는데 필요한 콘텐츠가 줄어들어 페이지 로드 속도가 빨라진다.


블로그 포스트 썸네일 이미지에 적용

네트워크 탭을 통해 lazy-loading이 확실히 적용되고 있는 것을 확인할 수 있다.

References

post-custom-banner

0개의 댓글