파일 크기만 고려한다면 AVIF 품질 설정을 고르는 일은 쉽다. 어려운 부분은 눈에 보이는 화질 저하를 어디까지 허용할지 결정하는 것이다. 품질값 40이 지각 품질 점수 40을 뜻하는 것은 아니며, 모든 이미지에서 같은 결과가 나온다는 보장도 없다. 인코더 설정이 같아도 원본 이미지에 따라 결과가 크게 달라질 수 있다.
SSIMULACRA2는 압축된 이미지를 디코딩한 결과와 참조 이미지를 비교해 이러한 판단을 돕는다. 하지만 모든 이미지에 대해 품질값을 빠짐없이 탐색하면 단순해야 할 변환 파이프라인이 인코딩 작업량이 많은 과정으로 바뀔 수 있다. 모든 파일을 완벽하게 최적화하기보다 웹에서 쓰기에 충분한 화질을 얻는 것이 목표라면 더 간단한 방법이 있다. 대표 샘플로 AVIF 품질값 하나를 보정하고, 결과를 눈으로 확인한 다음 나머지 이미지에도 같은 값을 적용하는 것이다.
AVIF 품질값과 SSIMULACRA2 점수는 서로 다르다
AVIF 인코더에 전달하는 quality 옵션은 압축 방식을 지정하는 설정이다. 반면 SSIMULACRA2는 인코딩 결과를 측정한 값이다. 두 값의 척도는 서로 바꿔 쓸 수 없다. AVIF quality: 40이라고 해서 SSIMULACRA2 점수가 40이나 60, 또는 다른 특정 값으로 정해지는 것은 아니다.
인코딩 결과를 측정하려면 이미지를 디코딩한 후 참조 이미지와 비교한다.
ssimulacra2 reference.png encoded-decoded.png
SSIMULACRA2 점수가 높을수록 지각적 유사도가 높다. 공식 문서에서는 50 안팎을 중간 수준의 품질, 70 안팎을 높은 품질로 설명한다. 임계값 60은 실용적인 목표가 될 수 있지만, 모든 이미지에 적용되는 보편적인 허용 품질 기준이 아니라 운영상 선택한 기준이다. 대표적인 결과물은 반드시 실제 표시 크기에서 눈으로 확인해야 한다.
이미지별 최적화를 끝까지 수행하면 비용이 커지는 이유
엄격한 최적화 방식에서는 이미지 하나를 여러 품질값으로 반복 인코딩하고, 각 결과를 SSIMULACRA2로 평가한 뒤 허용 기준을 충족하는 것 중 파일 크기가 가장 작은 결과를 남긴다. 압축하기 쉬운 이미지는 낮은 품질값으로도 기준을 통과하고 어려운 이미지는 더 높은 품질값이 필요하므로, 이런 방식이 압축 효율을 더 높이는 경우가 많다.
단점은 인코딩 횟수다. 이미지가 N개이고 허용 가능한 설정을 찾을 때까지 이미지당 K개의 후보를 인코딩한다면, 인코딩 횟수는 대략 N × K가 된다. 여기에 디코딩과 점수 계산도 추가된다. 실제로는 높은 연산 강도로 AVIF를 인코딩하는 과정이 비용의 대부분을 차지할 수 있다. SSIMULACRA2 지표를 계산하는 작업 자체가 반드시 비싼 것은 아니다.
폴더마다 품질값 하나를 선택하면 탐색 작업은 줄지만, 여전히 그룹별 샘플링과 측정, 별도의 설정 관리가 필요하다. 이미지 제공 요구사항이 일관되고 일부 예외를 허용할 수 있는 이미지 모음이라면 이런 추가 복잡성이 그만한 가치가 없을 수도 있다.
| 전략 | 보정 작업 | 주요 절충점 |
|---|---|---|
| 이미지별 적응형 품질 조정 | 이미지마다 여러 후보를 인코딩 | 세밀한 제어가 가능하지만 보정 비용이 가장 높음 |
| 그룹별 적응형 품질 조정 | 그룹별 샘플에 대해 여러 후보를 인코딩 | 작업량은 줄지만 설정이 늘고 결과가 그룹에 따라 달라짐 |
| 단일 고정 품질값 | 제한된 보정 샘플에서만 후보를 인코딩 | 운영은 단순하지만 일부 이미지는 과도하게, 일부는 충분하지 않게 압축됨 |
중요한 차이: 평균 점수와 통과율
품질값을 선택하기 전에 무엇을 '충분히 좋은 품질'로 볼지 정의해야 한다. 얼핏 비슷한 다음 두 목표는 서로 매우 다른 인코더 설정으로 이어진다.
- 평균 점수 목표: 샘플의 평균 SSIMULACRA2 점수가 약 60이 되도록 한다.
- 통과율 목표: 이미지의 약 90%가 SSIMULACRA2 ≥ 60을 기록하도록 하고, 나머지는 60 미만이어도 허용한다.
두 목표는 같지 않다. 평균을 계산하면 쉬운 이미지의 높은 점수가 어려운 이미지의 낮은 점수를 상쇄할 수 있다. 예를 들어 이미지의 절반이 75점, 나머지 절반이 55점이면 평균은 65지만 임계값 60을 충족하는 이미지는 절반뿐이다.
대부분의 이미지가 보기에 무난하면 되고 소수의 실패는 감수할 수 있는 일반적인 웹 이미지 처리에서는 통과율 목표가 더 유용한 경우가 많다. 다음 값을 측정한다.
pass_rate = count(scores >= 60) / count(all_scores)
통과하지 못한 점수의 분포도 기록하고, 눈에 띄게 나쁜 이미지를 살펴봐야 한다. 9%가 59점을 받은 샘플과 9%가 30점을 받은 샘플은 통과율이 같아도 실질적인 차이가 크다.
실제 보정 작업에서 확인한 점
탐색적으로 진행한 AVIF 보정에서 적응형 절차는 이미지 그룹마다 서로 다른 품질값을 선택했으며, 값은 대략 30대 중반에서 40대 중반에 걸쳐 있었다. 예상 가능한 결과였다. 어떤 그룹에는 낮은 품질값에서 이미 SSIMULACRA2 임계값을 넘는 이미지가 있었지만, 까다로운 샘플 몇 개는 훨씬 높은 인코더 품질값을 필요로 했다.
그러나 이 적응형 규칙은 실제 제공 요구사항보다 엄격했다. 각 그룹에서 테스트한 이미지가 거의 모두 임계값을 통과하도록 하고, 예외는 극히 제한적으로만 허용하려 했다. 이렇게 하면 까다로운 이미지를 보호할 수 있지만, 유독 예외적인 샘플 하나 때문에 그룹 전체의 품질값이 올라갈 수도 있다.
측정값을 다른 목표, 즉 이미지 열 장 중 대략 아홉 장이 SSIMULACRA2 60점 이상이어야 한다는 기준으로 다시 살펴보니, AVIF 품질값을 39~40 정도로 고정하는 것이 현실적인 절충안으로 보였다. 이 비교에서 39는 더 작은 출력 파일을 우선했고, 40은 임계값 근처의 이미지에 조금 더 여유를 줬다. 이 값들은 보정 데이터와 후속 분석에서 도출한 것이며, 고정 품질값으로 전체 이미지를 변환하거나 전체 이미지 모음에 대해 독립적으로 검증하는 작업은 수행하지 않았다. 39와 40의 정확한 파일 크기 차이도 확인되지 않았다.
여기서 얻을 교훈은 AVIF 품질값 39나 40이 어디서나 통한다는 것이 아니다. 허용할 품질 분포를 명확히 정하고 그 기준에 맞는다면 고정값을 사용하는 것이 합리적일 수 있다는 점이다. 인코더, 이미지 구성, 색상 처리 파이프라인 또는 지각 품질 임계값이 다르면 답도 달라질 수 있다.
AVIF 품질값을 한 번 보정해 정하는 방법
- 허용할 실패율을 정한다. 예를 들어 이미지의 약 90%가 SSIMULACRA2 ≥ 60을 달성하도록 요구할 수 있다. 이 목표를 유연하게 적용할지, 출시 전에 반드시 충족해야 하는 엄격한 조건으로 삼을지도 결정한다.
- 실제 이미지 집합을 제대로 대표하는 샘플을 만든다. 다양한 크기와 원본 형식, 그라데이션, 날카로운 경계, 질감, 세부 묘사가 적은 이미지를 포함한다. 실제 작업 대상에서 무작위로 뽑되 특정 유형이 빠질 우려가 있다면 층화 샘플링을 사용한다. 압축된 이미지의 픽셀당 바이트 수만을 기준으로 파일을 고르는 것은 범위를 넓히는 데 유용한 휴리스틱일 뿐, 지각적 대표성을 보장하지는 않는다.
- 인코더 품질값을 좁은 범위에서 시험한다. 전체 품질 범위를 탐색하는 대신, 눈으로 보기에 허용할 만한 설정 주변의 몇 가지 후보부터 비교한다. 예를 들어 동일한 이미지에 38, 39, 40, 42를 적용해 본다.
- 인코딩 파이프라인의 조건을 동일하게 유지한다. 해상도, 방향, 색상 변환, 인코더 구현,
effort, 크로마 서브샘플링, 비트 깊이, 전처리를 고정한다. 워터마크를 넣는다면 참조 이미지에도 같은 워터마크와 변환을 적용한 상태에서 압축 결과와 비교해야 한다. - 점수와 크기를 함께 기록한다. 후보마다 60점 이상을 받은 이미지의 비율, 임계값 미만 점수의 분포, 동일한 샘플을 인코딩했을 때의 총 바이트 수를 계산한다. 품질값만 보고 대역폭 절감량을 추정해서는 안 된다.
- 통과하지 못한 이미지를 살펴본다. 얼굴, 글자, 가는 선, 그라데이션 등 실제 용도에서 중요한 세부 요소를 확인한다. 확대 비교만 하지 말고 실제 표시 크기에서도 확인한다.
- 기준을 만족하는 가장 낮은 품질값을 고른 뒤 검증한다. 품질값을 선택할 때 사용하지 않은 별도의 무작위 홀드아웃 샘플로 시험한다. 90% 목표를 놓치면 손실이 크다면 안전 여유를 두고 표본 불확실성도 신중히 고려한다. 드문 실패를 허용할 수 있다면 더 공격적인 값도 합리적일 수 있다.
한 번 보정했다고 해서 이후의 변화를 무시해도 되는 것은 아니다. 원본 이미지 구성, 이미지 크기, 인코더 버전, 제공 과정의 변환 작업 또는 화질 요구사항이 바뀌면 작은 샘플로 다시 검사해야 한다.
Sharp와 SSIMULACRA2로 비교하는 간단한 예제
다음의 단순화된 예제는 Sharp의 AVIF 인코더를 사용해 같은 입력에서 두 후보를 생성한다. 보정 방법을 설명하기 위한 코드이며, 모든 프로젝트에 이 인코더 옵션이나 품질값을 권장한다는 뜻은 아니다. sharp를 설치한 다음 ES 모듈로 실행한다.
import sharp from 'sharp';
const source = 'sample.png';
const encoding = {
effort: 9,
chromaSubsampling: '4:4:4',
bitdepth: 8,
tune: 'iq',
lossless: false
};
// Use the same orientation and color conversion in both paths.
await sharp(source)
.rotate()
.toColourspace('srgb')
.png()
.toFile('reference.png');
for (const quality of [39, 40]) {
const encoded = `candidate-q${quality}.avif`;
await sharp(source)
.rotate()
.toColourspace('srgb')
.avif({ ...encoding, quality })
.toFile(encoded);
await sharp(encoded)
.png()
.toFile(`candidate-q${quality}.png`);
}
그런 다음 디코딩한 후보를 준비된 참조 이미지와 비교한다.
ssimulacra2 reference.png candidate-q39.png
ssimulacra2 reference.png candidate-q40.png
실제 테스트에서는 샘플 이미지 전체에 대해 이 과정을 자동화하고 후보마다 점수와 파일 크기를 수집해야 한다. 운영 파이프라인에서 크기 조정, 자르기, 오버레이 또는 그 밖의 변환을 수행한다면 비교용 참조 이미지에도 같은 작업을 적용한다. 그렇지 않으면 SSIMULACRA2가 압축 손실뿐 아니라 변환으로 생긴 차이까지 일부 측정하게 된다.
전체에 사용할 품질값을 고르면 운영 환경에서는 일반적인 단일 패스 AVIF 변환만 수행하면 된다. 이미지나 폴더마다 품질값을 탐색할 필요가 사라진다. 반복적인 시험 인코딩은 없어지지만, 출력 이미지마다 한 번씩 인코딩해야 하는 비용까지 없어지는 것은 아니다.
AVIF 품질값 하나로 처리하면 안 되는 경우
고정 품질값은 절충안이지 모든 상황에 통하는 최적해가 아니다. 개별 이미지에 대한 최소 품질을 계약상 보장해야 하거나 시각적 품질 실패를 허용할 수 없거나 원본 이미지의 특성이 크게 다를 때는 적응형 인코딩이 여전히 유용하다. 바이트 하나하나를 줄이는 이점이 추가 연산과 구현 복잡성을 정당화하는 경우에도 마찬가지다.
특히 이미지 유형이 섞여 있다면 주의해야 한다. 사진, 단순한 그래픽, 작은 글자, 이미 압축된 원본이 같은 방식으로 반응하리라는 보장은 없다. 특정 유형에서 반복적으로 허용 기준을 충족하지 못한다면, 모든 이미지에 단일 품질값을 쓰거나 이미지마다 완전히 최적화하는 두 극단 대신 형식이나 콘텐츠별로 몇 가지 프로필을 두는 편이 더 효율적일 수 있다.
또한 인코딩 속도와 보정 속도를 구분해야 한다. 품질값 하나를 사용하면 반복 실험은 피할 수 있지만, 모든 이미지를 매우 높은 effort로 인코딩하면 여전히 많은 연산이 필요할 수 있다. 낮은 effort의 인코더 프로필도 유효한 최적화 방법이지만 다시 보정해야 한다. 인코더 옵션에 따라 품질값과 점수 사이의 관계가 달라질 수 있기 때문이다.
실무에서 적용할 원칙
SSIMULACRA2는 모든 이미지의 운영 파이프라인에서 반드시 실행해야 하는 단계라기보다 품질값을 보정하는 도구로 사용하면 된다. 이미지가 실제로 표시되는 방식을 반영해 품질 목표를 정하고, 대표 샘플을 비슷한 몇 가지 설정으로 인코딩한 뒤 지각 품질 점수와 바이트 수를 함께 비교한다. 통과하지 못한 이미지를 눈으로 확인하고 허용 범위를 만족하는 가장 낮은 값을 고정한다.
한 탐색적 보정에서는 AVIF 품질값 39~40 정도가 적절한 절충점으로 보였다. 이는 특정 임계값과 허용 범위에 따른 판단이지, 어디에나 적용되는 사전 설정이나 전체 이미지 모음에서 검증된 벤치마크가 아니다. 널리 적용할 수 있는 교훈은 더 간단하다. 시간과 연산 자원이 제한되어 있다면, 충분히 검증한 고정 품질값을 사용하는 편이 이미지마다 끝없이 최적화하는 것보다 실용적인 경우가 많다.