프론트엔드 이미지 최적화 (+ Next.js)

3

리펙토링

목록 보기
5/5
post-thumbnail

🎀 들어는 봤나 picture 와 source 태그

참고 자료 출처

이미지 최적화를 이야기하기 위해서는 picturesource태그 이야기가 빠질 수 없다.

퍼블리셔로 일할 때 은근 많이 사용했었던 태그들이다. 🤓 📚

반응형에 따라 이미지를 변화시키기에 유리하고, 최적화를 통한 성능 개선에도 도움을 준다.

📌 picture 태그란?

picture 태그는 source 태그를 이용한 반응형 이미지를 사용함으로써 대역폭을 절약하고 페이지 로드 시간 단축을 위한 목적으로 사용된다.

❗️ picture 태그는 그 단어의 의미인 picture(사진)와는 직접적인 관계가 없다. 하나의 img 태그에 대해 0개 이상의 반응형 이미지를 제공하는 source 태그의 범위를 알려주는 컨테이너(부모 요소)라는 의미일 뿐이다.

📌 source 태그란?

source 태그는 picture 태그 내에서 반응형 이미지 소스를 설정하는 요소를 뜻한다.

이제 아래 예시 코드를 보면서 이해해보자.

❗️코드펜 로고를 눌러서 큰 화면에서 직접 테스트해보는게 좋음!

<picture>
  <!-- 최소 1280까지만 이 이미지를 보여주겠다는 의미 -->
  <source media="(min-width: 1280px)" srcset="https://images.unsplash.com/photo-1536532184021-da5392b55da1?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8Mnx8Ymx1ZSUyMHNreXxlbnwwfHwwfHx8MA%3D%3D&w=1000&q=80">
  <!-- 최소 980까지만 이 이미지를 보여주겠다는 의미 -->
  <source media="(min-width: 980px)" srcset="https://cdn.pixabay.com/photo/2017/08/06/08/55/key-chain-2590442_1280.jpg">
  <!-- 모든 이미지를 불러오지 못했을 때 fallback으로 보여줌 -->
  <img src="https://cdn.pixabay.com/photo/2022/09/02/19/55/crystal-7428278_1280.jpg" alt="대체 이미지가 여기 들어갑니다.">
</picture>
  • source 태그 안에 media 속성에는 미디어 쿼리를 넣어주면 된다.
    내가 설정해준 미디어 쿼리에 따라 srcset에 넣어준 이미지가 보여지게 된다.

  • 위 예제처럼, 반응형에 따라 다양한 이미지가 보여질 수 있도록 설정해도 좋다.
    혹은, 하나의 이미지 사이즈나 용량의 이미지를 넣어주어 알맞게 렌더링 될 수 있도록 해주면 된다.

  • img 태그는 있어도 되고, 없어도 된다.

  • 단, 웹 접근성을 위해서 img태그를 반드시 넣어주는게 좋다.

  • 또, img 태그는 fallback(source 이미지를 불러오지 못했을 경우 img태그를 대체해서 보여줌) 의 역할을 해주기 때문에 반드시 넣어주는 편이다.

🎀 webp 로 가벼운 이미지 생성

webp는 구글에서 개발한 용량이 아주 작은 이미지를 뜻한다.
사진과 그래픽의 크기를 줄여 웹 사이트가 빠르게 로드되고 사용자에게 더 나은 경험을 제공한다고 한다.

png to webp 변환 전

588.87 KB의 이미지를 webp로 변환해 보았다.

png to webp 변환 후

44.33 KB로 용량이 확실하게 줄어든것이 확인된다!

webp로 변환해주는 사이트들이 많으니 이용해보면 좋을 것 같다.
webp 로 변환하러 가기

🎀 Next.js Image는 알아서 해줌

갓스트 js에서는 이 모든 귀찮은 작업을 쉽게 가능하도록 해준다.

📌 lazy loading

갓스트 Image는 기본 값으로 lazy loading을 제공한다.
뷰포트에 보여지는 이미지만 우선 보여주고 , 그 밖에있는 이미지들은 로딩을 지연시킨다.

불필요한 이미지 제외하고 필요한 이미지만 빠르게 로드하는 것!!

필요에 따라 사용하지 않도록 설정 가능함.

📌 이미지 최적화

Image 컴포넌트를 사용했으면 반드시 너비와 높이를 지정해주어야 한다.

<Image
  src='...'
  alt='...'
  width={276}
  height={276}
  />

작은 사이즈의 이미지가 필요한데, 원본 사이즈는 어마어마하게 클 경우를 대비해서
너비와 높이를 미리 지정해두고 해당하는 사이즈로 변환된 이미지를 다운로드 한다.

또, 기본적으로 webp 이미지로 제공된다.

메인에서 일반 img 태그를 사용했었다.

<img src={banner.imageSrc} alt={banner.title} />

그럼 위 이미지에서 보이는 것 처럼 458KB 사이즈를 가진다.

import Image from 'next/image';

<Image src={banner.imageSrc} alt={banner.title} fill sizes='1195px' priority />

img태그 대신 next.js image 컴포넌트로 바꿔주면 어떻게 될까?

35.6KB의 webp로 자동 변환하여 이미지가 제공되고 있는 것을 확인할 수 있다!

fill : 이미지를 감싸고있는 부모 요소의 너비와 높이를 가진다.
sizes : 위 source 태그의 media 프로퍼티와 동일하다. 현재 내가 올린 코드는 분기점이 없이 하나의 px 사이즈만 들어가있는데, 이는 아직 디자인 반응형 분기 처리가 되어있지 않기 때문 (반응형 작업할 때 추가할 예정)
priority : true 값을 넣어주면, 해당 이미지를 최우선적으로 preload(미리 로드)한다. 배너 이미지에 LCP 에러가 떴기 때문에 넣어주었다. (공식문서)

📌 placeholder 사용 가능

CLS(Cumulative Layout Shift) 즉, 레이아웃이 흔들리는 현상을 막아줄 수 있는 placeholder를 제공할 수 있다.

<Image
  src='...'
  alt='...'
  width={276}
  height={276}
  placeholder='blur'
  blurDataURL='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNcvHhTPQAGYgJ5cH4fHAAAAABJRU5ErkJggg=='
  />

빈 영역을 넣어줄 수도 있고 blur 속성을 사용해서 이미지를 넣어줄 수도 있다.
원본 이미지를 넣으면 당연히 안되고,
base64로 인코딩된 data url을 넣어주어야 한다.

아래 링크에서 손쉽게 컬러로만 이뤄진 픽셀 이미지를 생성할 수 있으니 해보시길!

Base64 Encoded Pixel 생성하러 가기

placeholder 사용 결과

placeholder가 적용되고

이미지가 적용되고 있는것을 확인할 수 있다.

역시 갓스트 ..
세상 각박한 개발 환경에 한줄기 빛..






📚 압도적 감사 (출처)
Next/Image를 활용한 이미지 최적화
Next.js 공식사이트

profile
일단 해. 그리고 잘 되면 잘 된 거, 잘 못되면 그냥 해본 거!

2개의 댓글

comment-user-thumbnail
2024년 4월 29일

이미지를 최적화해서 좋은 기능이죠!
이 기능이 어떻게 만들어졌는지도 한번 알아보시면 더 재밌어요😁

1개의 답글