같은 GIF인데 용량은 더 작게, 화질은 그대로
'GIF 용량 줄이기'라고 하면 보통 화질을 깎거나 색 수를 줄여서 작게 만든다고 생각하잖아요. 그런데 이번에 소개할 이야기는 화질을 단 한 픽셀도 건드리지 않으면서 파일 크기만 줄이는 방법이에요. 디코딩하면 원본과 완전히 똑같은 그림이 나오는데, 파일 용량은 더 작은, 그야말로 무손실(lossless) 재압축이죠. 어떻게 이런 게 가능할까요? 핵심은 'GIF의 압축 방식엔 사실 놀고 있는 여유 공간이 꽤 있다'는 데 있어요.
GIF는 어떻게 압축될까: LZW 이야기
GIF는 LZW(Lempel-Ziv-Welch)라는 압축 방식을 써요. 이게 뭐냐면, 데이터를 쭉 읽어나가면서 '아까 나왔던 패턴'을 사전(dictionary)에 등록해두고, 다음에 같은 패턴이 또 나오면 통째로 쓰는 대신 사전 번호 하나로 짧게 표현하는 방법이에요. 쉽게 비유하면, 긴 문장에 '아까 그 표현 있잖아, 12번' 하고 번호표를 붙여서 줄여 쓰는 거예요. 같은 패턴이 자주 반복될수록 번호표로 확 줄일 수 있으니 효과가 좋죠.
그런데 여기엔 함정이 하나 있어요. 이 사전은 무한정 커지지 못해요. GIF는 번호표를 최대 12비트, 즉 4096개까지만 만들 수 있거든요. 사전이 꽉 차면 두 가지 선택지가 생겨요. (1) 지금 사전을 그대로 계속 쓰거나, (2) '초기화 신호(clear code)'를 보내서 사전을 싹 비우고 처음부터 다시 패턴을 모으거나. 그런데 이걸 언제 비우는 게 최적인지는 그림에 따라 달라요. 그림 앞부분이랑 뒷부분의 패턴 성격이 다르면, 중간에 한 번 비워주는 게 더 작을 수도 있거든요.
문제는 우리가 흔히 쓰는 인코더(압축 프로그램)들이 '그때그때 눈앞에서 가장 좋아 보이는 선택'을 하는 탐욕적(greedy) 방식이라는 거예요. 당장은 좋아 보여도 전체적으로 보면 최선이 아닐 수 있죠. 사실 LZW에서 진짜 최적의 압축을 찾는 건 수학적으로 꽤 어려운 문제예요.
무차별 탐색: 컴퓨터한테 다 해보게 시키기
그래서 이 글의 저자는 좀 무식하지만 확실한 방법을 택했어요. 바로 무차별 탐색(exhaustive search)이에요. '사전을 언제 비울지', '어떤 식으로 인코딩할지' 가능한 선택지들을 컴퓨터가 일일이 다 시도해보면서, 그중 결과물이 가장 작게 나오는 조합을 찾아내는 거죠. 시간은 오래 걸려요. 사람이 머리로 똑똑하게 줄이는 게 아니라 컴퓨터의 계산 무식함으로 밀어붙이는 거니까요. 하지만 그 대가로 거의 한계치에 가까운 작은 GIF를 얻을 수 있어요. 픽셀은 단 하나도 안 바뀌었는데 말이죠.
사실 이건 압축 세계의 오래된 전략이에요
이 '엄청난 계산을 들여서 무손실로 더 작게 만들기' 패턴은 GIF에만 있는 게 아니에요. 가장 유명한 형제가 구글이 만든 Zopfli예요. PNG나 gzip이 쓰는 DEFLATE 압축을 무차별에 가깝게 파고들어서 보통보다 몇 퍼센트 더 작게 짜내주거든요. PNG 전용인 zopflipng, pngout, 여러 최적화를 묶은 ECT(Efficient Compression Tool) 같은 도구들도 다 같은 철학이에요. GIF 쪽에선 gifsicle의 강력한 최적화 옵션(-O3)이나 flexigif 같은 도구가 비슷한 일을 하는데, 이번 글의 무차별 탐색은 그보다 더 극단까지 밀어붙인 셈이죠.
이런 도구들의 공통점은 명확해요. '압축할 땐 시간을 펑펑 쓰고, 그 대신 매번 전송할 때 절약한다'는 거예요. 한 번 압축해두면 그 파일은 수백만 번 다운로드될 수 있잖아요. 그러니 빌드 시점에 CPU를 좀 갈아 넣어서 파일을 작게 만들어두면, 그 이후로 두고두고 대역폭을 아끼는 거예요. 수지가 맞는 장사죠.
한국 개발자에게 주는 시사점
웹 성능 최적화하시는 분들은 이 발상을 꼭 챙겨두세요. 우리가 서비스에 올리는 정적 자산(이미지, 폰트, JS 번들 등)은 한 번 만들고 수없이 전송되거든요. 그래서 빌드 파이프라인에 무손실 최적화 단계를 끼워 넣는 것만으로 사용자 로딩 속도와 트래픽 비용을 동시에 잡을 수 있어요. 화질 저하 없이 공짜로 얻는 이득이라 안 할 이유가 없죠. 다만 솔직하게 덧붙이면, GIF 자체는 요즘 좀 한물간 포맷이에요. 움직이는 짧은 영상은 WebP나 AVIF, 아니면 그냥 비디오(mp4)나 APNG로 바꾸는 게 용량 면에서 훨씬 유리한 경우가 많거든요. 그래도 '내 자산을 무손실로 더 짜낼 여지가 있다'는 감각과, Zopfli 같은 도구의 존재는 알아두면 분명 써먹을 날이 와요.
핵심 한 줄: '압축 포맷엔 생각보다 놀고 있는 여유가 있고, 빌드 시점의 계산력으로 그 여유를 무손실로 쥐어짜낼 수 있다'는 거예요. 여러분 프로젝트의 정적 자산들, 마지막으로 최적화 도구 한번 돌려본 게 언제였나요?
🔗 출처: Hacker News