2026.10.29 목
Aqueous: 이미 압축된 파일을 더 작게 보관하기
오늘의 픽: Aqueous
Aqueous 는 JPEG, PNG, ZIP 처럼 이미 압축된 파일의 압축을 풀어 더 작게 다시 압축하고, 아카이브를 풀 때 원본과 모든 비트가 같은 파일로 복원하는 프로덕트다.
오늘의 픽으로 선정한 이유는 사진처럼 이미 압축돼 더 줄지 않던 파일도 원본을 잃지 않고 더 작게 보관할 수 있게 하기 때문이다.
- 출처
- Show HN
- 만든 방식
- Rust, WebAssembly
무엇이 문제인가
사진, 스크린샷, 문서 파일은 대부분 저장할 때 이미 압축된다. JPEG 은 손실 압축 뒤 마지막 단계에서 허프만 부호화자주 나오는 값에 짧은 비트열을, 드문 값에 긴 비트열을 할당해 데이터를 줄이는 부호화 방식이다.로, PNG 와 ZIP 은 DEFLATE반복되는 문자열을 앞에 나온 같은 문자열의 위치와 길이로 바꾸고, 그 결과를 허프만 부호화로 다시 줄이는 압축 방식이다.로 압축된다. 압축된 데이터에는 반복되는 패턴이 적어서, 이런 파일을 다시 압축해도 크게 줄지 않는다.
7-Zip 의 7z 형식 문서에 따르면 7z 는 LZMA2 같은 범용 압축 방식에, 실행 파일과 WAV 파일을 위한 변환 필터를 더해 압축한다. 이 문서의 필터 목록에는 JPEG 이나 PNG 처럼 이미 압축된 파일을 위한 필터가 없다. 제작자는 README 에서 Aqueous 를 tar 와 zstdMeta 가 공개한 범용 압축 방식이자 프로그램이다. 압축과 해제가 빠르다.의 조합, 압축 프로그램 zpaq 와 비교했고, 7z 와는 비교하지 않았다. 7z 는 이런 파일의 압축된 바이트를 그대로 다시 압축하므로, 이미 압축된 부분은 크게 줄이지 못한다.
어떻게 해결했나
Aqueous 는 2026년 10월 28일 Hacker News 에 Show HN개발자 커뮤니티 Hacker News 에서 자신이 만든 프로덕트를 소개하는 글. 제목이 "Show HN:"으로 시작한다. 글로 올라왔다. Aqueous 의 압축 프로그램 aqr 은 파일의 형식을 판별해 파일 안의 압축을 먼저 푼다. 푼 내용물은 형식에 맞춘 압축 모델앞에 나온 데이터로 다음 값을 예측하는 압축기의 구성 요소다. 예측이 정확할수록 그 값은 적은 비트로 저장된다.로 다시 압축한다. README 에 따르면 aqr 은 JPEG, PNG, MP3, PDF, SQLite, ZIP, gzip 등 20여 개 형식을 이렇게 처리한다.
같은 데이터라도 압축기와 설정에 따라 압축된 바이트가 달라진다. 그래서 내용물만 저장하면 원본 파일을 똑같이 만들 수 없다. aqr 은 원래 압축기가 내린 선택(DEFLATE 라면 반복 문자열을 앞의 어느 위치로 가리킬지, 블록을 어디서 나눌지)을 예측하고, 예측이 빗나간 부분만 따로 기록한다. 압축을 풀 때는 이 기록으로 원래 압축 과정을 재현해, 원본과 모든 비트가 같은 파일을 만든다.
아카이브에는 파일마다 복원 절차를 담은 작은 프로그램과, 그 절차에 필요한 WebAssembly브라우저와 여러 런타임에서 같은 방식으로 실행되는 바이너리 형식이다. WebAssembly 모듈을 실행하는 프로그램은 그 모듈의 접근 권한을 제한할 수 있다. 모듈이 함께 들어간다. README 에 따르면 aqr 은 실행 파일에 내장된 모듈을 네이티브 코드로 실행하고, 내장되지 않은 모듈은 샌드박스프로그램이 파일, 네트워크 같은 시스템 자원에 접근하지 못하게 제한한 실행 환경이다.에서 실행한다.
무엇이 다른가
첫째, 압축하는 대상이 다르다. 7z 는 파일의 바이트를 그대로 압축한다. Aqueous 는 파일 안의 압축을 풀고, 그 내용물을 형식별 모델로 압축한다. 압축을 푼 이미지나 텍스트에는 압축된 바이트보다 반복되는 패턴이 많아 더 작게 압축할 수 있다. 다만 원래 압축기의 선택을 잘 예측할 수 있는 파일에만 효과가 있다. 예측이 많이 빗나가면 기록이 커져 이득이 사라진다. 저장소의 aqr-flate 문서에 따르면 aqr 은 DEFLATE 스트림의 경우 zlib 같은 알려진 압축기를 모방해 선택을 예측한다. 예측이 빗나간 부분의 기록이 클 것으로 추정되면, 그 스트림은 풀지 않고 그대로 저장한다.
둘째, 압축 해제 프로그램이 알아야 하는 것이 다르다. 7z 를 풀려면 프로그램이 LZMA2 같은 방식을 미리 구현하고 있어야 한다. Aqueous 는 복원에 필요한 모듈을 아카이브에 넣는다. README 에 따르면 그 덕분에 압축 해제 프로그램은 안에 든 파일 형식을 몰라도 된다. 트레이드오프는 모듈의 크기가 아카이브마다 더해진다는 점이다. 파일이 적은 아카이브는 거의 줄지 않거나 원본보다 커질 수 있다.
제작자는 README 에서 2026년 10월 27일의 측정 결과를 밝혔다. 제작자는 Apple M4 에서 10 GB 벤치마크 데이터(파일 79,431개)를 압축했다. 이 벤치마크는 zpaq 를 만든 Matt Mahoney 가 공개했다. aqr 은 2.63 GB, zpaq 7.15 는 3.70 GB 였다. tar 로 묶은 뒤 zstd -3 으로 압축한 결과는 4.68 GB 였다. 압축에는 aqr 이 136초, zstd 가 33초 걸렸다. aqr 의 시간에는 모든 파일을 복원해 확인하는 과정이 포함된다.
어떻게 만들었나
- 커밋 539개는 2026년 10월 5일부터 10월 29일까지 작성됐다. 그중 31개에 Claude 와 함께 작성했다는 Co-authored-by 트레일러가 있다.
- 제작자는 README 에서 LLM 코딩 에이전트를 많이 사용했다고 밝혔다. README 에 따르면 아이디어와 목표는 제작자가 결정했고, 구현과 실험은 AI 가 진행했다.
- 소스 코드는 Rust 99,033줄, 테스트 코드는 11,298줄이다. 형식별 재압축기는 Rust 패키지 24개로 나뉘어 있다.
실행해 보니
저장소를 클론해 aqr 을 빌드하고, 파일 60개(6.56 MB)를 압축하고 풀었다. 이 사이트의 스크린샷 JPEG 22개, PNG 14개, Debian 문서의 gzip 20개, SQLite 2개, ZIP 1개, PDF 1개다. PNG 14개 가운데 10개는 그 JPEG 스크린샷을 PNG 로 다시 저장한 것이고, 4개는 실행한 컴퓨터의 node_modules 와 /usr/share 폴더에 있던 것이다.
- 빌드. README 대로
cargo build -r -p aqr를 실행하자flate-zoo/Cargo.toml을 읽지 못한다는 에러로 멈췄다. flate-zoo 는 git 서브모듈인데, README 의 빌드 방법에는 서브모듈을 받는 단계가 없다.git submodule update --init을 실행한 뒤에는 4코어 컴퓨터에서 빌드에 7분 40초가 걸렸다. 실행 파일은 166 MB 였다. - 압축. 6.56 MB 가 0.98초 만에 4.63 MB(원본 크기의 70.6%)가 됐다. 같은 파일을 tar 로 묶어 압축하자 zstd -3 은 85.5%, xz -9 는 81.8% 였다. xz 는 7z 가 기본으로 사용하는 LZMA2 로 압축한다.
- 형식별. 형식마다 아카이브를 따로 만들자 PNG 는 70.8%(zstd -3 97.9%), JPEG 은 70.4%(zstd -3 77.3%)가 됐다. SQLite 는 13.1% 로 zstd -3(7.5%)보다 컸다.
- 복원.
aqr -d로 푼 파일 60개의 SHA-256데이터에서 256비트 값을 계산하는 해시 함수다. 값이 같은 파일은 내용이 같다고 본다. 이 원본과 모두 같았다. 모든 모듈을 WebAssembly 로 실행하는--wasm으로 풀어도 같았다. 압축 해제 시간은 기본 실행이 0.25초,--wasm이 1.47초였다. - gzip. 기본 수준에서는 Debian 문서의 gzip 20개 가운데 18개를 풀지 않고 그대로 저장했다. 시험한 파일 60개와 별도로 GNU gzip 과 Python 의 zlib 으로 gzip 6개를 직접 만들었다. aqr 은 직접 만든 gzip 6개도 모두 그대로 저장했다. 출력에는 그 이유가 나오지 않았다.
-l high로 압축하자 aqr 은 6개 가운데 소스 코드를 담은 2개를 풀어서 다시 압축했다. - 작은 아카이브. JPEG 하나(131.8 KB)만 압축하자 이미지 데이터는 66.1% 가 됐지만, 모듈과 헤더 41.5 KB 가 더해져 아카이브는 128.6 KB 였다. ZIP 하나(200.6 KB)는 245.2 KB 로 커졌다.
/tmp/run/out/corpus.aqr: 60 files, 6.56 MB -> 4.63 MB (70.6%) in 0.98 s, 6.7 MB/s
/tmp/run/one/2026-10-11-2.jpg: jpeg, jpeg-recons@2, 131.8 KB -> 87.2 KB (66.1%)
archive overhead (header, modules, metadata): 41.5 KB
/tmp/run/out/one.aqr: 1 file, 131.8 KB -> 128.6 KB (97.6%) in 0.03 s, 3.8 MB/s
확인하지 못한 것
- MP3, FLAC, PDF 의 재압축. aqr 은 시험한 PDF 의 형식을 인식하지 못하고 그대로 저장했다. 여러 PDF 와 음악 파일로 압축률을 확인하자.
- 10 GB 벤치마크. 제작자의 결과를 재현하려면 10 GB 데이터를 받아 압축해야 한다. 압축 시간과 복원할 때의 메모리 사용량을 확인하자.
- 샌드박스. README 에 따르면 aqr 에 내장되지 않은 모듈은 권한이 제한된 별도 프로세스에서 실행된다. 그런 모듈을 넣은 아카이브로 모듈의 권한이 실제로 제한되는지 확인하자.
판정
작동한다. 압축한 파일을 모두 원본과 비트 단위로 같게 복원했다. 다만 복원 모듈이 아카이브마다 들어가, 파일이 적은 아카이브는 거의 줄지 않거나 오히려 커졌다. 이미 압축된 사진과 스크린샷이 많은 폴더를 백업하면서, zstd 보다 압축 시간이 길어도 용량을 줄이고 싶은 경우에 써 볼 만하다.
시작하기
git submodule update --initcargo build -r -p aqr
- 필요한 것
- Rust 와 cargo
- 비용
- 퍼블릭 도메인(퍼블릭 도메인을 인정하지 않는 나라에서는 MIT-0), 무료.
README 의 빌드 방법에는 서브모듈을 받는 단계가 없어, 클론한 뒤 git submodule update --init 을 먼저 실행해야 한다. 아카이브 형식의 명세는 아직 초안이다.
실행해서 확인한 절차다.
진행
- 3일예정
- 7일예정
- 15일예정
- 30일예정
- 90일예정
- 180일예정
- 365일예정