ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 이미지 최적화를 위한 방법들과 Next/Image
    concept/React, Redux, RN 2023. 11. 5. 00:25

    배경

    Web Vital 이란 웹에서 우수한 사용자 경험을 제공하는데 필수적인 품질 신호에 대한 통합 지침을 제공하기 위한 Google의 이니셔티브이다.

    Web Vital 의 하위 집합으로 Core Web Vitals가 있는데 20년 기준으로는 UX 기준의 세 가지 측면인 1. Loading (로딩) 2. Interactivity (상호 작용) 3. Visual Stability (시각적 안정성) 에 중점을 두고 있다.

     

    • LCP (최대 콘텐츠풀 페인트) - 로딩 성능을 측정. 2.5초 이내에 LCP가 발생해야 우수하다고 평가한다.
    • FID (최초 입력 지연) - 상호 작용 측정. 100 ms 이내에 상호 작용이 가능해야 우수하다고 평가한다.
    • CLS (누적 레이아웃 시프트) - 시각적 안정성 측정. 레이아웃이 이동하는 데 소요되는 시간을 측정해서 점수로 표현. 0.1 이하의 CLS 를 유지해야 우수하다고 평가한다.

    이 중 LCP가 페이지를 처음 로드한 시점을 기준으로 화면에 있는 가장 큰 이미지, 텍스트 블록의 렌더링 시간을 알려주는 지표이다. 특히 텍스트보다는 이미지 렌더링에 따라 이 시간이 좌우되기 때문에 이미지를 최적화 하는 것은 성능 최적화의 여러가지 요소 중 가장 먼저 고려되는 요소이다.

     

     💡 이미지를 최적화 하는 것은 성능 최적화의 여러가지 요소 중 가장 먼저 고려되는 요소

     

    기본 HTML 에서의 이미지 최적화 전략

    1. 이미지 형식 변경 (jpg → png → webp → avif)

    • webp 는 png보다 파일 크기를 26% 까지 줄일 수 있음.
    • avif 는 webp 대비 20% 더 높은 압축률을 보여줌.

    2. lazy loading

    • 특정 리소스를 네트워크에 요청하지 않고 있다가, 필요한 순간에만 리소스를 요청하는 최적화 전략
    • <img> 태그에서 loading='auto | lazy | eager' 속성을 활용해 레이지 로딩을 적용할 수 있음.

    3. 이미지 Resizing

    • 모바일, 태블릿, 노트북, 데스크탑 등 브라우저 화면에 알맞는 이미지를 가져와서 보여주는 방법
    <img srcset="pikachu-320w.jpg 320w,
                 pikachu-480w.jpg 480w,
                 pikachu-800w.jpg 800w"
         sizes="(max-width: 320px) 280px,
                (max-width: 480px) 440px,
                800px"
         src="pikachu-800w.jpg" alt="잠자는 피카츄">
    
    • srcset - 브라우저에게 어떤 크기의 이미지를 보여주면 되는지 알려주는 역할
    • sizes - 미디어 조건문 설정
      • 미디어 조건문: (max-width: 320px)
      • 조건이 참일 때 이미지의 너비: 280px
    • 위와 같이 코드를 작성했을 때 브라우저에서 일어나는 순서
      1. 기기의 너비를 확인
      2. sizes 에서 참이 되는 조건문과 이미지 너비 확인
      3. srcset 에서 해당 너비와 가장 근접한 이미지를 찾기

    4. 이미지 용량 압축

    • 라이브러리를 활용할 수 있음.

    npm: browser-image-compression

    5. 이미지 캐싱

    Next/Image 에서의 이미지 최적화 전략

    1. lazy loading

    • 레이지로드를 기본적으로 사용하고 있기 때문에 뷰포트에 노출되었을 때 이미지 로드. 선택적으로 블러링 처리한 이미지를 먼저 노출하는 기능
    • 중요한 이미지일 경우 레이지로딩을 사용하고 싶지 않다면 priority 속성을 주거나, loading prop 에 eager 값을 설정할 수 있음.

    2. 이미지 사이즈 최적화

    • 장치의 크기에 맞춘 적절한 이미지 사이즈와 최신 이미지 포맷 지원
    • 이미지 최초 요청 시 cache/images 폴더에 최적화한 이미지를 저장. 이 후 동일한 요청에 대해서는 이미 만들어진 이미지를 캐시로서 재사용.
    • 모든 이미지를 최적화하지는 않는다. (ex. svg, gif)
    • next.config.js의 deviceSizes와 imageSizes를 통해 자동적으로 srcset이 설정되어 뷰포트 너비에 따라 최적화된 이미지가 로드된다.
      • deviceSizes
        • 웹 사이트 사용자로부터 예상되는 장치의 width를 알고 있는 경우에 deviceSizes 프로퍼티를 사용하여 특정 장치 사이즈의 breackpoint를 지정할 수 있다. 이 width는 next/image 컴포넌트가 layout="responsive" 또는 layout="fill"을 사용할 때나 장치에 따른 올바른 이미지가 제공된다.
      • imageSizes
        • imageSizes 프로퍼티를 이용하여 특정 이미지 width 목록을 지정할 수 있다. 이러한 width는 deviceSizes의 배열과 연결되어 있으므로 deviceSizes배열에 정의 된 width와 달라야하고, 일반적으로 그 배열의 width보다 작아야 한다. 이 width는 next/image 컴포넌트가 layout="fixed"또는 layout="intrinsic"를 사용해야한다. 만약 따로 imageSizes 프로퍼티를 지정하지 않으면 아래 값이 default로 사용된다.next.config에서 deviceSizes 와 imageSizes 설정을 통해 srcset을 설정할 수 있다. 만약 아무것도 설정하지 않으면 기본값은 아래 코드와 같다.

    기본값으로 설정되어 있는 이미지 srcset

    • module.exports = { images: { deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840], imageSizes: [16, 32, 48, 64, 96, 128, 256, 384], }, }

    3. placeholder 제공을 통한 Web Vitals의 CLS 발생을 방지

    • 이미지가 로드될 때 자동으로 레이아웃 이동을 방지

    4. sharp vs squoosh

    • 둘 다 다양한 크기와 형식의 이미지들을 (jpeg, png, webp, gif, avif) 더 작은 크기로, 웹에 진화적으로 변환해 주는 매우 빠른 속도의 모듈
    • 기본 내장 라이브러리는 squoosh 인데 Next.js 는 공식문서에서 sharp 라이브러리 활용을 적극 권장.
    • Sharp Missing In Production
    • sharp를 설치하면 기존 squoosh를 활용한 이미지 최적화 결과보다 훨씬 빠른 응답을 받을 수 있음.

     

    img 태그와 Next/Image 를 쓴 경우 비교
    sharp와 squoosh 성능 비교
    naoda-cobalt에 sharp 라이브러리 설치 전
    naoda-cobalt에 sharp 라이브러리 설치 후

    • 큰 차이는 아니지만, 이미지 사이즈와 로딩 시간 측면에서 조금의 차이가 있는 것을 확인할 수 있음.

    샘플 코드

    https://github.com/KunHwanAhn/next-image-opt-example

    참고 자료

    Web Vitals

    Optimizing: Images

    NEXT.JS의 이미지 최적화는 어떻게 동작하는가? | 올리브영 테크블로그

    Next/Image를 활용한 이미지 최적화 | 카카오엔터테인먼트 FE 기술블로그

     

    댓글

Designed by Tistory.