Developer/React

리액트에서 라이브러리없이 간단하게 이미지 최적화하기

jaddong 2024. 1. 3. 16:10
320x100

서비스가 심미적이나 기능적으로 모두 구현되었다고 끝이 아님을 대부분 개발자들이 알고 있을 것이라 생각한다. 그중에 꼭 짚고 넘어가야 할 것이 어셋들(image, video, sound 등)에 대한 성능 최적화 작업이다. 성능 최적화 작업은 프론트엔드, 벡엔드, 디자이너 단에서 모두 각자의 방식으로 작업이 가능하나 그중 나는 프론트엔드 쪽에서 작업한 경험을 간단하게 정리해 보았다.

이미지 최적화하기

svg

svg 이미지는 sources로 사용하는 것보다 svg그대로 사용하는 것이 성능에 좋다.

import { ReactComponent as Logo } from "assets/icons/logo_bg.svg";

const LogoComponent = () => {
  return (
      <Logo title="logo image" />
  );
};

 

sources

하나의 소스를 제공하는 것이 아니라, 최적화를 위해 여러 이미지는 제공하고 브라우저가 렌더링 할 수 있는 이미지를 사용한다.

아래의 예시에서는 브라우저가 AVIF 이미지를 렌더링할 수 있는 경우 선택한 이미지 파일이다. 그렇지 않으면 다음 요소로 이동해 두 번째 요소는 WebP 형식source 의 이미지를 가리키게 된다. 브라우저가 WebP 이미지를 렌더링할 수 있는 경우 해당 이미지 파일을 사용하고 그렇지 않으면 img에 있는 이미지 파일(JPEG)로 대체된다.

<picture>
  <source srcset="image.avif" type="image/avif">
  <source srcset="image.webp" type="image/webp">
  <img src="image.jpg" alt="A description of the image." 
    width="300" height="200" loading="lazy" decoding="async">
</picture>

 

WebP 파일이 PNG 파일보다 26% 작고 JPEG 파일보다 최대 34% 작기 때문에 매우 빠른 로딩 시간을 제공한다.

Can I Use 에 따른 글로벌 WebP 및 AVIF 지원 수치는 다음과 같다.
- WebP : 웹 사용자의 약 96.30%가 WebP를 지원하는 브라우저를 사용하고 있습니다.

- AVIF : 웹 사용자의 약 79.81%가 AVIF를 지원하는 브라우저를 사용하고 있습니다.

 

 

lazy

true로 설정하면 페이지에서의 위치에 관계없이 리소스를 즉시 로드하지 않고 뷰포트로부터 계산된 거리에 도달할 때까지 리소스 로딩을 지연시킨다. 스크롤 해야 보이는 이미지의 경우는 lazy를 처리하는 것이 첫 로딩에 부하를 줄일 수 있다.

 

<img src="image.png" loading="lazy" alt="…" width="200" height="200">
img lazy 역할 network 탭에서 확인해보기

 

srcSet

디스플레이 사양(1x, 2x, 3x) 에 따라 w 디스크립터(Width descriptor)를 사용해 포트 너비에 최적화된 이미지를 선택해 출력할 수 있다. 다른 해상도의 이미지를 각각 제공하는 것이 시각적으로도 좋고 데이터 낭비도 줄여서 유저 경험에 긍정적인 효과를 줄 수 있다.

 

 

 

다른 확장자와 dpr에 따른 이미지가 필요하다면 아래와 같이 구현이 가능하다. 

 

 

위의 이미지처럼 html 코드가 길어지기 때문에 공통적으로 사용할 수 있는 image 컴포넌트를 따로 만들어 구현하는 것이 서비스 전반적으로 적용하기에 훨씬 나았어서 구현했던 코드를 간단히 공유해본다. -> GitHub Link

import ImagePng from "assets/images/fallback.png";
import ImageAvif1x from "assets/images/image_1.avif";
import ImageAvif2x from "assets/images/image_2.avif";
import ImageAvif3x from "assets/images/image_3.avif";
import ImageWebp1x from "assets/images/image_1.webp";
import ImageWebp2x from "assets/images/image_2.webp";
import ImageWebp3x from "assets/images/image_3.webp";


const MainImage = () => {
  return (
      <Image
        src={ImagePng} // fallback 이미지
        sources={[
          { srcSet: `${ImageAvif1x} 1x, ${ImageAvif2x} 2x, ${ImageAvif3x} 3x`, type: "avif" },
          { srcSet: `${ImageWebp1x} 1x, ${ImageWebp2x} 2x, ${ImageWebp3x} 3x`, type: "webp" },
        ]}
        width="100%"
	/>
  );
};

 

 

출처

 

웹용 브라우저 수준 이미지 지연 로드  |  Articles  |  web.dev

이 게시물에서는 로드 속성 및 이 속성을 사용하여 이미지 로드를 제어하는 방법을 다룹니다.

web.dev

 

사진 요소  |  web.dev

이미지를 더욱 창의적으로 관리할 수 있습니다.

web.dev

 

AVIF vs WebP: Which Image Format Reigns Supreme in 2023?

AVIF and WebP are next-gen formats that reduce file sizes. However, you might not know which to choose. Here's our guide to AVIF vs WebP!

themeisle.com

    반응형