-
이미지 최적화를 위한 방법들과 Next/Imageconcept/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
- 위와 같이 코드를 작성했을 때 브라우저에서 일어나는 순서
- 기기의 너비를 확인
- sizes 에서 참이 되는 조건문과 이미지 너비 확인
- 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을 설정할 수 있다. 만약 아무것도 설정하지 않으면 기본값은 아래 코드와 같다.
- deviceSizes
- 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를 활용한 이미지 최적화 결과보다 훨씬 빠른 응답을 받을 수 있음.
- 큰 차이는 아니지만, 이미지 사이즈와 로딩 시간 측면에서 조금의 차이가 있는 것을 확인할 수 있음.
샘플 코드
https://github.com/KunHwanAhn/next-image-opt-example
참고 자료
NEXT.JS의 이미지 최적화는 어떻게 동작하는가? | 올리브영 테크블로그
Next/Image를 활용한 이미지 최적화 | 카카오엔터테인먼트 FE 기술블로그
'concept > React, Redux, RN' 카테고리의 다른 글
[Udemy] 클린코드 리액트 - 소개, State (0) 2024.02.04 채팅 기능 구현을 위한 web socket과 sse 방식 POC (0) 2023.11.06 React에서 DOM에 직접 접근보다 useRef 쓰는 이유 (0) 2022.09.09 redux-persist로 로그인 유지 구현 (0) 2022.09.09 React로 만든 앱에 PWA 적용하기 (0) 2022.09.06