“이 이미지를 압축한다“는 말은 버튼 하나를 쓰고 있는 서로 다른 네 가지 작업입니다. 그중 어느 것이 화질을 깎아 먹는지 알고 나면 설정이 훨씬 덜 알쏭달쏭해집니다.
1단계: 디코딩
압축된 파일을 다시 픽셀 격자로 되돌립니다. 브라우저는 이 일을 네이티브 코드로 하고, 플랫폼이 제공한다면 하드웨어 가속도 씁니다. JPEG과 PNG, WebP, AVIF를 다루고, 애플 플랫폼에서는 HEIC까지 다룹니다. 운영체제가 그 디코더를 이미 갖고 있기 때문입니다.
디코딩은 파일에 대해서는 무손실입니다. 파일이 기술하는 픽셀을 그대로 얻습니다. 손실은 이미 일어난 뒤입니다. 그 파일을 만들어 낸 무언가가 인코딩하던 순간에 말입니다.
2단계: 방향 보정
휴대폰 카메라는 센서가 놓인 그대로의 방향과, 그것을 어떻게 회전해야 하는지 알려 주는 EXIF 태그를 따로 저장합니다. 그 태그를 무시하는 소프트웨어는 옆으로 누운 사진을 내놓습니다. 태그를 적용한다는 것은 다른 무엇이 손대기 전에 실제 픽셀 격자를 회전시킨다는 뜻입니다. 그러고 나면 태그는 더 이상 필요하지 않은데, 다시 인코딩할 때 메타데이터가 사라지는 이유 중 하나가 이것입니다.
3단계: 리샘플링
원래 해상도로는 목표 용량을 맞출 수 없으면 이미지를 줄입니다. 체감 화질이 소리 없이 지켜지거나 버려지는 지점이 바로 여기입니다. 값싼 박스 필터는 이웃 픽셀을 평균 내며 전체를 부드럽게 뭉갭니다. Lanczos 필터는 더 넓은 범위에 가중치를 매겨 경계선을 또렷하게 지킵니다.
리샘플링은 분명히 파괴적입니다. 버려진 픽셀은 돌아오지 않습니다. 그러나 작은 목표 용량에 이르는 방법 중에서는 오히려 가장 덜 파괴적인 경우가 많습니다. 그대로 두었다면 인코더가 예산을 다 쓰고도 제대로 담아내지 못했을 세부를 미리 덜어내기 때문입니다.
4단계: 인코딩
손실이 일어나는 부분입니다. JPEG은 밝기와 색으로 나눈 표현으로 바꾸고, 색 해상도를 일부 버리고 (눈은 거의 알아채지 못합니다), 이미지를 8×8 블록으로 쪼개고, 각 블록을 주파수 성분으로 변환한 뒤 양자화합니다. 고주파 세부를 반올림해 버리는 것입니다. 품질 값이란 그 반올림이 얼마나 거친지를 가리킵니다. 그 뒤의 과정은 모두 무손실 엔트로피 부호화이며, 최적화한 허프만 표나 프로그레시브 스캔이 화질을 깎지 않고도 바이트를 아껴 주는 이유가 여기에 있습니다.
WebAssembly가 끼어드는 지점
브라우저에 내장된 인코더는 속을 볼 수 없는 상자입니다. 품질 숫자 하나를 요청할 수 있을 뿐 그 이상은 없습니다. 최적화한 엔트로피 표도, 베이스라인과 프로그레시브 중에 고르는 것도, 리샘플링 필터를 정하는 것도 안 되고, 어떤 설정이 몇 바이트를 낼지 해 보기 전에는 알 방법도 없습니다.
WebAssembly로 컴파일한 코덱은 그 모두를 돌려줍니다. 대신 그것을 내려받는 바이트를 치릅니다. ToolZool은 디코딩을 브라우저에 맡기는 대신 파이프라인 전체를 그 방식으로 돌립니다. 디코딩과 방향 보정, 리샘플링, 인코딩이 모두 WebAssembly로 컴파일한 Rust이고, 백그라운드 워커에서 실행됩니다. 이유는 셋이며 모두 실용적인 것입니다.
- 탐색에는 여러 번의 인코딩이 필요합니다. 정확한 용량에 이르려면 같은 이미지를 다섯 번이나 여섯 번 인코딩해야 합니다. 그 일을 값싸고 반복 가능하게 만드는 것이 인코더를 직접 가지는 일입니다.
- 디코더는 거절할 줄 알아야 합니다. 60,000 × 60,000 픽셀이라고 선언하는 파일은 메모리를 잡기 전에 거절해야 하고, 잘려 나간 파일은 반쪽짜리 이미지를 돌려주는 대신 실패해야 합니다. 브라우저 디코더는 그 지점에서 스스로 판단합니다. 저희 것은 한계를 명시하고 그것을 지킵니다.
- 같은 입력은 같은 출력을 내야 합니다. 브라우저 디코더는 색을 다루는 방식과 망가진 파일을 대하는 태도가 저마다 다릅니다. 양쪽 끝을 모두 가진 파이프라인은 어느 기기에서나 같은 바이트를 내놓고, 그래야 여러분이 결과를 확인할 수 있습니다.
대가는 정직하게 말해 두겠습니다. 그 엔진은 내려받아야 하는 파일입니다. 여러분이 파일을 고른 뒤에야 가져오므로, 이런 페이지를 읽는 데는 그 비용이 들지 않습니다.
코덱보다 탐색이 더 중요한 이유
목표 파일 용량이 정해져 있을 때, 좋은 인코더와 아주 뛰어난 인코더의 차이는 몇 퍼센트입니다. 품질 슬라이더를 짐작하는 것과 알맞은 값을 탐색하는 것의 차이는 훨씬 큽니다. 허용치의 60%에 멈춘 짐작은 여러분 몫이던 화질의 3분의 1을 버린 것이기 때문입니다. 정확한 용량으로 압축하기의 발상이 통째로 이것이고, 50 KB 제한 맞추기는 가장 빡빡한 쪽 끝에서 이 탐색이 무엇을 벌어 주는지 보여 줍니다.

