⭐ 이미지 최적화의 중요성
회사에서 개발한 이벤트 페이지에 일부 이미지가 로드되지 않는다는 CS건이 들어왔다.
네트워크 통신 장애로 인해 느린 리소스 다운로드 현상이었던 것을 확인하였다. 종종 웹사이트 접속 시 이미지가 느리게 로드되는 것을 확인할 수 있다.
인터넷이 느린 환경이더라도 사용자에게 최대한 빨리 많은 자원이 로드될 수 있도록 해야 한다. (사이트 방문자 40%가 3초 안에 웹페이지가 로딩되지 않으면 떠난다고 한다. )
그중에서도 웹 페이지(특히 이미지가 중점인 이벤트성의 웹뷰)에서 대부분의 용량을 차지하는 이미지 최적화를 통해 이미지 용량을 줄이고자 한다.
이미지 사이즈를 적절히 줄이고, 렌더링 속도를 빠르게 하면 웹사이트 렌더링 성능이 향상된다. 웹 페이지 바이트를 절약하여 사이트 성능 향상 및 브라우저가 다운로드해야 하는 바이트가 줄어 클라이언트 대역폭에 여유가 생긴다. 이로 인해 콘텐츠를 더 빨리 다운로드하여 화면에 렌더링함으로써 최적의 사용자 경험을 제공할 수 있다.
추가적으로, 구글의 SEO 순위를 결정할 때 모바일 응답성을 고려하여 검색순위에 노출한다고 한다. 이미지 최적화를 통해 모바일 응답성을 빠르게 한다면, 검색 결과 상위권에 노출될 수 있다.
➰ 이미지 종류와 포맷에 대해서
레스터 이미지와 벡터 이미지
레스터 이미지는 픽셀에 표현하고자 하는 색상을 그려 이미지 형태로 표현하는 방식으로, 대표적으로 JPEG, PNG, GIF 등이 있다. 여러 픽셀이 모여 하나의 이미지를 만들기 때문에, 사이즈가 크거나 품질이 더 좋은 이미지를 만들기 위해서는 그만큼의 정보를 담은 픽셀들을 추가해야만 컴퓨터가 이를 정상적으로 표현할 수 있다. 사이즈가 커질수록 이미지 용량도 늘어나고, 렌더링 속도도 현저히 떨어지게 된다.
벡터 이미지는 픽셀값으로 그림을 그리는 것이 아닌, 이미지 안에 수많은 수학 방정식을 포함하고 있는 방식의 이미지 형태이다. 컴퓨터는 선의 표현, 크기, 색상 등 정보를 이미지 안에 있는 계산식으로 연산하여 이미지를 제공한다. 따라서 벡터 이미지는 사이즈가 커지거나, 작아져도 이미지가 깨지거나 정보가 달라지지 않는다. 벡터 이미지는 주로 아이콘, 폰트 등에 사용되며, 대표적인 W3C 포맷인 SVG가 많이 사용된다. 다만, 이미지가 복잡할수록 그 안에 수학적 정보는 계속 늘어나고 이미지 용량 또한 늘어나게 된다.
무손실 이미지와 손실 이미지
이미지를 구분하는 또 다른 기준은 이미지 정보 손실을 허용하는지 안 하는지의 여부이다.
무손실 이미지는 원본 이미지에서 이미지를 렌더링하는데 필요하지 않은 정보들을 제거한 이미지이다. 따라서 무손실 이미지는 원본 이미지보다 용량이 줄어들 수 있으며, 대표적으로 GIF, PNG가 있다.
손실 이미지는 무손실 이미지의 화질 감소를 감수하면서도 사이즈를 줄여 빠른 렌더링을 할 수 있는 이미지이다. 무손실 이미지보다 상대적으로 빠른 렌더링이 가능하므로 사용자에게 꼭 필요한 정보를 주는 이미지가 아닌 경우 사용되는 이미지이다. JPEG가 가장 대표적인 손실 이미지이며, 그 외로 JPEG 2000등이 있다.
이미지 포맷
이미지 렌더링 속도는 이미지 용량에 비례한다. 화질이 중요한 배너 이미지나 메인 이미지는 좀 더 손실이 적은 이미지로, 화질과 상관없는 이미지는 손실률이 높지만, 용량이 적은 이미지로 선택을 고려하는 것이 좋다.
WebP 포맷
구글에서 개발한 이미지 포맷으로 손실 압축과 비손실 압축을 전부 지원한다. WebP(Web + Picture)라는 단어에서 알 수 있듯, 웹에서 사용되는 기존 GIF, JPG, PNG 등의 상용 이미지 포맷을 대체할 수 있다.
가장 큰 특징으로, 같은 품질의 이미지를 만들 때 기존의 이미지 포맷보다 파일 크기가 더 작아진다. WebP를 사용하면 기존 대비 25~35% 정도 압축할 수 있다.
하지만, IE에서 지원하지 않으며, 애니메이션 이미지의 경우 GIF 보다 CPU 사용량이 더 높다는 단점이 있다.
AVIF 포맷
AOMedia에서 개발한 이미지 포맷으로, WebP보다 더 압축된 이미지 타입으로 저용량에 고품질의 이미지이다. 손실 압축과 비손실 압축 전부 지원하여 WebP와 마찬가지로 GIF, PNG, JPEG 등 사용 이미지 포맷을 대체할 수 있다.
다만, 최신 포맷인 만큼 낮은 범용성으로 인해 현재는 지원하는 브라우저가 많지 않다.
실제로 598KB의 JPG 포맷 이미지를 WebP와 AVIF 포맷으로 변환해 보았다. 확실히 용량 차이가 큰 것을 볼 수 있다.
이미지 최적화 방법 알아보기 👀
브라우저 사이즈에 맞춘 적절한 이미지 제공하기
1. 미디어 쿼리 사용
다양한 조건 및 사이즈에 따라 스타일이 조정가능한 CSS 문법인 미디어 쿼리를 이용한다.
@media (min-width: 400px) {
.image {
width: 700px;
height: 700px;
}
}
2. <img> 태그의 srcset 속성
<img> 태그의 srcset 속성은 같은 비율의 다양한 크기를 갖는 동일 이미지들을 명시하는 속성이다. 이때, 이미지 크기로 px 단위가 아닌 w디스크립터 혹은 x디스크립터를 입력해야 하며, 작은 크기 이미지부터 순서대로 입력해야 한다. sizes는 미디어 조건과 그에 해당하는 이미지 최적화 출력 크기를 입력하면 된다.
하지만, IE는 지원하지 않는다.
<img
srcset="./small.png 400w, ./medium.png 700w, ./large.png 1000w"
sizes="(max-width: 400px) 400px, (max-width: 700px) 700px, 1000px"
src="./large.png"
/>
3. <picture> 태그 사용
위 <img> 태그는 브라우저가 사용하는 연산 방식이나 메모리, 혹은 파워가 충분한지에 따라 낮은 해상도가 선택될 수도 있고, 해상도별로 다른 비율의 이미지를 사용하거나 부분만 확대한 이미지를 사용할 때 이미지가 비정상적으로 보이는 이슈가 있다.
<picture> 태그는 <img> 태그를 보완한다. 특정 브라우저에서 특정 이미지를 사용할 수 있도록 강제할 수 있으며, 조건에 맞지 않는 이미지는 다운로드하지 않는다.
하지만, HTML 소스가 길어지며, IE 및 안드로이드 구버전 브라우저에서는 지원하지 않는다는 단점이 있다.
type 속성을 이용하여 사용자 환경에 맞는 이미지를 제공할 수 있다.
사용자의 브라우저가 avif를 지원하면 avif를 보여주고, 아니라면 WebP를 보여주며, WebP도 지원하지 않는 브라우저라면 <img> 에서 선언된 이미지 포맷인 jpg를 보여준다.
<picture>
<source srcset="sample.avif" type="image/avif">
<source srcset="sample.webp" type="image/webp">
<img src="sample.jpg" alt="sample">
</picture>
media 속성을 사용하여 브라우저 사이즈(디스플레이 크기)에 맞는 이미지를 제공할 수 있다.
<picture>
<source srcset="sample.webp" media="(max-width: 760px)"> <!-- 브라우저의 넓이가 760px 이하일때 sample.webp 이미지 출력-->
<img src="pc.webp" alt>
</picture>
이미지 Lazy Loading
웹사이트 이미지는 최대한 사용자가 보이는 부분부터 로드되도록 처리하며, 사용자가 보이지 않는 부분은 Lazy Loading을 적용하는 것이 좋다.
<img> 태그의 loading 속성을 사용하여 이미지에 레이지 로딩을 적용하는 방법이 있다.
<img src="sample.jpg" loading="lazy" alt>
자바스크립트와 <img> 태그의 data-src 속성을 이용하여 레이지 로딩을 적용하는 방법이 있다.
<img src="1px.gif" data-src="sample.jpg" onload="loadReal(this)"/>
function loadReal(img) {
if(img.style.display != "none"){
img.onload = null;
img.src = img.getAttribute("data-src");
}
}
src 속성에 1px 짜리 작고 투명한 파일을 설정해두고 추후 data-src에 들어가 있는 진짜 이미지를 로드해서 넣어주는 방법이다.
<img> 태그에서 지원하는 loading 속성은 아직 비표준이므로, 자바스크립트를 이용한 방법을 추천한다.
위 예시는 간단한 예시이며 실제 운영에서는 지연 로딩을 지원하는 라이브러리를 사용하는 것이 좋다. (참고)
이미지 CDN 사용
이미지 CDN(Content Delivery Network)은 이미지 변환, 최적화 및 전송을 담당하는 서버로 이를 사용하면 이미지 다운로드 속도를 40~80%로 줄일 수 있다.
Sprite 이미지 사용
Sprite 이미지는 여러 개의 이미지를 합친 하나의 이미지 셋을 말한다. css의 background-position 속성을 사용하여 부분적으로 이미지를 사용할 수 있다. 이미지 파일 개수 자체를 줄여 네트워크상에서 실제로 10번의 이미지 요청을 1번의 요청으로 해결하여 트래픽이 절약되는 효과를 볼 수 있다.
참고
https://oliveyoung.tech/blog/2021-11-22/How-to-Improve-Web-Performance-with-Image-Optimization/
'Devlog > Front-End' 카테고리의 다른 글
[React.js] useEffect와 addEventListener (can't perform a react state update on an unmounted component) (0) | 2022.10.21 |
---|---|
[NextJS] SSR 이슈 (Warning: Prop dangerouslySetInnerHTML did not match.) (0) | 2022.10.19 |
[NextJS] 빌드 에러(Error: Unexpected '/'. Escaping special characters with \ may help.) (0) | 2022.09.30 |
리액트에 대해 알아보기 ! (1) | 2022.09.20 |
프론트엔드 프레임워크 비교(React, Vue, Angular), SPA란? (1) | 2022.08.30 |