이미지 확장자와 최적화
1. 개요
이미지는 웹 페이지의 전체 데이터 용량에서 상당한 비율을 차지합니다. HTTP Archive에 따르면, 가장 영향력 있는 리소스는 이미지로 HTML, CSS, JavaScript와 글꼴 전체를 합친량보다 많다고 합니다.
2022 HTTP Archive 보고서 출처
즉 사용자 경험을 향상시키는데 있어서 이미지의 크기를 줄이고 동시에 품질을 유지하는것은 중요하며 상황에 맞게 적절한 이미지 확장자를 사용하면 웹사이트의 성능을 최적화하는데 도움이 될 수 있으며 최적화의 중요 요인입니다.
2. 압축 방식
확장자 소개에 앞서서, 각 이미지 확장자에서 사용되는 압축방식은 크게 2가지가 있습니다.
-
손실 압축
손실 압축 방식은 원본 데이터에서 일부 정보를 제거하여 파일 크기를 줄이는 방법입니다.
일부 데이터가 제거되기 때문에 파일 크기를 상당히 줄일 수 있지만, 이는 이미지 품질의 저하를 불러올 수 있습니다.
손실 압축 방식은 높은 압축률을 제공하며, JPEG 형식에서 주로 사용됩니다.
손실 압축은 주로 사진과 같이 높은 해상도와 복잡한 색상을 가진 이미지에서 사용됩니다.
위 사진은 JPEG확장자를 가진 이미지에 대해서 압축 전, 압축 후 이미지입니다.
105KB 에서 72KB로 약 31.4% 이미지 크기를 줄였는데 눈으로 보기에 큰 차이가 느껴지시나요?? 제 눈엔 비슷해보입니다😅
-
무손실 압축
무손실 압축 방식은 원본 데이터를 보존하면서 파일 크기를 줄이는 방법입니다.
이 방식은 이미지의 반복되는 패턴을 효과적으로 표현하여 공간을 절약합니다. 압축을 풀면 원본 이미지와 완전히 동일한 이미지를 얻을 수 있습니다.
무손실 압축 방식은 품질 저하 없이 이미지를 저장할 수 있지만, 압축률이 상대적으로 낮다는 단점이 있습니다. 이 방식은 PNG와 GIF 형식에서 주로 사용됩니다.
무손실 압축은 로고, 아이콘, 다이어그램 등과 같이 투명성이 필요하거나 색상이 간단한 이미지에 적합합니다.
무손실 압축 알고리즘은 다양하지만 대표적으로 런렝스 부호화 (Run-Length Encoding, RLE) 방법이 있습니다
예를 들어 “AAAAABBBBCC”라는 문자열을 RLE로 압축한다면, “5A4B2C”라는 형태로 압축이 가능합니다. 이는 “A가 5번, B가 4번, C가 2번”이라는 정보를 나타냅니다.
즉 어떤 이미지 A가 있을때, 이 이미지가 단색배경과 간단한 텍스트등 반복되는 패턴이 높다면 PNG로 압축했을때 압축률이 더 높을것이며 반대로 복잡한 사진의경우 JPEG의 형태로 압축했을때 더 작은 파일 크기를 가질 수 있겠죠.
이미지 특성에 맞게 적합한 확장자를 선택하면 효과적으로 이미지 크기를 줄일 수 있습니다.
3. 이미지 유형
이미지는 기본적으로 비트맵(Bitmap)과 벡터(Vector) 두 가지 형식으로 구분할 수 있습니다.
-
비트맵 이미지
특징
-
비트맵 이미지는 디지털 이미지를 구성하는 가장 기본적인 형태로, 개별 픽셀들이 모여 하나의 이미지를 형성하는 방식을 사용합니다.
-
각 픽셀은 고유의 색상 정보를 가지며, 이 정보들이 모여 하나의 이미지를 구성합니다. 이 때문에 비트맵 이미지는 픽셀 단위의 작은 변화나 미세한 색상 변화를 잘 표현할 수 있습니다.
단점
-
이미지 크기를 확대하거나 축소할때 픽셀자체가 확대 & 손실되어 이미지가 깨질 수 있습니다.
-
픽셀 수가 크거나 색상이 많아지면 파일 크기가 커집니다
예시
- JPEG, GIF, PNG
-
-
벡터 이미지
특징
-
이미지를 수학적인 형태, 즉 점, 선, 곡선 등의 기하학적 객체로 표현하는 방식입니다.
-
이미지의 크기를 확대하거나 축소해도 이미지의 품질이 손상되지 않습니다.
-
단순하고 명확한 라인 아트를 요구하는 이미지에는 벡터 이미지 형식이 적합합니다.
단점
- 이미지가 복잡해질수록(즉, 더 많은 점, 선, 곡선 등이 필요할수록) 벡터 이미지의 크기는 커질 수 있습니다.
예시
- SVG
-
고화질의 풍경이나 사람의 얼굴같은 경우 여러 색상과 세부사항을 표현해야하기때문에 비트맵 이미지가 적합합니다.
반대로 회사의 로고나 아이콘같은 경우 간단한 색상과 복잡하지않은 선의 형태와 개수를 가지므로 벡터이미지가 더 적합하겠죠.
+) Lottie의 경우도 벡터기반의 이미지입니다. 따라서 확대 & 축소에 품질이 유지된다는 특징을 가집니다. Lottie를 활용한 애니메이션 추가
4. 확장자 비교
4.1 JPEG
- 손실 압축 방식을 사용하여 높은 압축률을 제공
- 사람의 눈에 덜 민감한 정보를 제거하여 고품질의 사진과 그라데이션을 효과적으로 표현
- 사진, 배경 이미지, 슬라이드 쇼 등 복잡한 이미지를 표현해야 하는 상황에 적합
- 품질과 파일 크기 사이에서 적절한 균형을 유지할 수 있음
4.2 PNG
- 무손실 압축 형식으로 품질 손실 없이 이미지를 표현
- 알파 채널을 지원하여 투명 이미지를 생성 가능
- 투명한 배경이 필요한 로고, 아이콘, 다이어그램 등에 적합
- 파일 크기가 크기 때문에, 웹사이트의 로딩 속도에 영향을 줄 수 있음
4.3 GIF
- 무손실 이미지 형식이며, 간단한 애니메이션을 지원
- 최대 256색까지만 지원하는 색상 제한성이 있음
- 움직이는 아이콘, 로딩 스피너, 짧은 애니메이션 등에 적합
- 색상 수가 제한적이라 복잡한 이미지 표현에는 한계가 있음
4.4 SVG
- 벡터 기반의 이미지 형식으로 확대/축소 시 품질 손실 없음
- CSS나 JavaScript와 함께 사용 가능
- 아이콘, 로고, 일러스트, 그래프 등 크기 조정이 자유로운 경우에 적합
- 배경 이미지와 같이 크기가 변할 수 있는 요소에도 적합하나, 복잡한 디테일을 표현하기에는 한계가 있음
5. WebP
WebP는 구글이 개발한 모던 이미지 포맷입니다.
위 이미지 포멧들의 장점만 모아둔 포맷의 느낌이 강한데요 실제 특징은 아래와 같습니다.
- 손실 압축에 대해서는 JPEG보다 약 25~34% 더 압축률이 높음
- 무손실 압축에 대해서는 PNG보다 약 26%의 압축률이 더 높음
- 투명성 지원
- 애니메이션 지원
- 단 모든 브라우저에서 지원하지 않음 (브라우저 호환성을 고려해야 함)
6. AVIF
AVIF(AV1 Image File Format)는 AOMedia(AOM)에서 개발한 오픈소스 이미지 파일 형식입니다.
AVIF는 AOM에서 개발한 AV1 비디오 코덱에 기반을 두고 있으며, 이 코덱은 Google의 VP9 코덱을 발전시킨 것으로 알려져 있습니다.
AVIF의 특징은 아래와 같습니다.
- WebP보다 평균적으로 더 높은 압축률을 가짐(손실 및 무손실 압축)
- 투명성 지원
- 애니메이션 지원
- 모든 브라우저에서 지원하지 않음
- 압축률이 높은만큼 계산시간이 걸려 실시간 이미지 처리의 경우에는 주의 필요
AVIF은 도대체 어떤방식으로 가장 효과적인 압축률을 가질까?
AV1 비디오 코딩 포맷에 기반을 두고 있으며 AV1은 고급 압축 기법, 블록 분할, 크롬 서브샘플링, 복잡한 예측 모델링 등의 기능을 이용해 이미지를 효율적으로 인코딩한다고 한다!
Q AVIF은 도대체 어떤방식으로 가장 효과적인 압축률을 가질까?
AV1 비디오 코딩 포맷에 기반을 두고 있으며 특징은 아래와 같다
블록 분할: AV1과 AVIF는 이미지를 블록으로 나누고 각 블록을 독립적으로 인코딩하는 기능을 제공
크롬 서브샘플링 : AVIF는 색상 정보 (크로마)와 밝기 정보 (루마)를 분리하고, 크로마 채널을 루마 채널보다 낮은 해상도로 인코딩하는 크롬 서브샘플링을 지원
예측 모델링: AV1은 이전에 인코딩된 블록을 기반으로 새로운 블록을 예측하는 여러 가지 복잡한 모델을 사용
7. 정리
결국, 어떤 이미지 포맷을 사용할 것인지는 해당 포맷의 압축 효율과 웹 브라우저의 호환성, 그리고 용도를 고려하여 결정해야 합니다.
압축 효율 면에서 보면 일반적으로 AVIF가 WebP를, WebP가 JPEG를 압도하는 성능을 보여주고 있습니다.
그러나 문제점은 브라우저의 호환성을 고려해야한다는 점입니다.
따라서 아래처럼 지원여부를 확인하고 해당 이미지를 렌더링하도록 처리한다면 가장 좋은 압축률의 이미지를 우선적으로 사용하되, 브라우저 호환성 문제를 적절하게 처리할 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import React from "react";
function ImageComponent() {
return (
<picture>
<source type="image/avif" srcSet={require("./path/to/image.avif")} />
<source type="image/webp" srcSet={require("./path/to/image.webp")} />
<source type="image/jpeg" srcSet={require("./path/to/image.jpeg")} />
<img src={require("./path/to/image.jpeg")} alt="description" />
</picture>
);
}
export default ImageComponent;
// picture요소는 위에서부터 아래로 내려가며 조건에 맞는 source요소를 선택
// 만약 웹 브라우저가 AVIF 지원하면 해당 이미지를 사용하고, 그렇지 않다면 WEBP, 그렇지 않다면 JPEG를 사용한다
댓글남기기