목차
로그 파일은 압축하면 훌쩍 주는데 사진은 꿈쩍도 안 한다. 그 차이가 어디서 오는지를 이 시리즈에서 푼다.
줄어든 건 내용이 아니라 적는 법이다
압축을 처음 만나면 이런 그림을 떠올리기 쉽다. 데이터를 꾹 눌러서 작게 만든다. 스펀지를 손으로 쥐는 것처럼.
그런데 컴퓨터에 든 건 스펀지가 아니라 0과 1이 늘어선 칸뿐이다. 칸은 눌러도 안 줄어든다. 압축 프로그램이 실제로 하는 일은 하나다.
같은 내용을 더 짧게 적는 방법을 찾아낸다.
내용은 하나도 안 버렸는데 적힌 길이만 짧아진다. 그래서 다시 원래 길이로 펼칠 수 있다. 이 되돌리기가 되는 압축을 무손실이라고 부른다.
핵심은 여기다. 짧게 적을 여지가 없는 데이터는 압축해도 안 줄어든다. 압축이 못난 게 아니라 줄일 낭비가 애초에 없는 것이다.
강의를 받아 적는 노트
이 시리즈는 처음부터 끝까지 강의를 받아 적는 노트를 따라간다.
교수는 말이 빠르고 손은 느리다. 그래서 학생은 들리는 말을 그대로 옮겨 적지 않고 줄여 적는다. 줄이는 방법은 몇 가지로 정해져 있다.
- 같은 말이 이어지면
〃하나로 때운다 - 아까 적은 문장이 또 나오면 “위 3줄, 12자”라고만 적는다
- 강의 내내 나오는 낱말은 기호 하나로 정해 둔다
- 중요하지 않은 건 아예 안 적는다
노트는 짧아졌는데 강의 내용은 그대로다. 줄어든 것은 강의가 아니라 받아 적는 방식이다. 이 그림 하나로 시리즈 전체가 굴러간다.
〃와 “위 3줄, 12자” → 반복을 가리키는 압축- 자주 나오는 낱말에 기호 하나 → 짧은 이름을 붙이는 압축
- 안 중요한 건 안 적는다 → 되돌릴 수 없는 손실 압축
- 이미 줄여 적은 노트는 더 못 줄인다 → 압축의 한계
줄어드는 이유는 둘뿐이다
노트를 줄일 수 있었던 건 강의에 줄일 구석이 있었기 때문이다. 데이터도 똑같고, 그 구석은 딱 두 종류다.
띠의 칸 수는 셋 다 같다. 무늬가 있는 만큼만 줄어들고, 무늬가 없는 셋째 줄은 트랙을 그대로 채운다.
하나는 반복이다. 같은 조각이 여러 번 나온다. HTML의 <div class="card">, 로그의 날짜 형식, JSON의 필드 이름이 그렇다. 두 번째부터는 “아까 그거”라고만 적으면 된다.
다른 하나는 치우침이다. 나오는 것들의 빈도가 고르지 않다. 영어 텍스트에서 e와 공백은 아주 자주 나오고 z와 q는 거의 안 나온다. 그러면 자주 나오는 쪽에 짧은 이름을 주는 게 이득이다.
그리고 셋째는 없다. 반복도 없고 치우침도 없는 데이터는 줄어들지 않는다. 잘 만든 난수가 그렇고, 이미 압축된 파일이 그렇고, 암호화된 데이터가 그렇다. 이 셋이 압축에 꿈쩍 않는 이유는 전부 같다.
여기서 노트 비유가 한 번 깨진다
비유를 계속 끌고 가기 전에 안 맞는 자리를 밝혀 둔다. 노트는 사람이 나중에 알아보기만 하면 된다. 글씨가 좀 뭉개져도, 조사가 빠져도 읽는 사람이 알아서 메운다.
압축은 그럴 수 없다. 푸는 쪽은 사람이 아니라 프로그램이고, 원본과 한 비트도 다르면 안 된다. 〃를 보고 “위와 같은 말”이라고 알아채는 게 아니라, 〃가 정확히 몇 글자를 대신하는지가 규칙으로 못 박혀 있어야 한다.
그래서 압축 형식은 대부분 사람이 봐서는 알아볼 수 없게 생겼다. 사람이 읽을 여지를 남기지 않는 대신 기계가 한 치의 오차 없이 되돌릴 수 있게 만든 것이다.
이 선이 갈라지는 곳이 있다. “중요하지 않은 건 안 적는다”는 노트의 넷째 요령인데, 이건 되돌릴 수가 없다. 시리즈 뒤쪽의 손실 압축 편이 그 대목이다.
인코딩과는 다른 층이다
압축과 인코딩은 둘 다 “데이터를 바이트에 담는 일”이라 층이 겹쳐 보인다. 갈라 두면 나머지가 쉬워진다.
| 하는 일 | 안 하는 일 | |
|---|---|---|
| 인코딩 | 뜻을 바이트로 옮기는 약속을 정한다 | 크기를 줄이려 하지 않는다 |
| 압축 | 이미 바이트가 된 것을 더 짧게 다시 적는다 | 뜻이 무엇인지 알 필요가 없다 |
압축기는 그 바이트가 한글인지 사진인지 실행 파일인지 몰라도 된다. 반복과 치우침만 보면 되기 때문이다. 그래서 같은 압축 프로그램이 텍스트에도 실행 파일에도 통한다.
반대 방향의 예가 Base64다. 그건 크기를 줄이기는커녕 33% 늘리는데도 쓴다. 목적이 크기가 아니라 “글자만 지나가는 통로를 통과시키는 것”이라서다. 인코딩은 통과를 위해 늘리기도 하고, 압축은 오직 줄이려 한다.
줄인 만큼 어딘가에서 값을 치른다
압축은 공짜가 아니다. 바이트를 줄이는 대신 CPU 시간을 쓴다.
- 압축할 때: 반복을 찾고 빈도를 세느라 계산이 든다
- 풀 때: 짧게 적은 것을 원래 길이로 펼치느라 다시 계산이 든다
그래서 압축은 줄어든 바이트가 늘어난 계산보다 값질 때만 이득이다. 느린 회선으로 큰 파일을 보낸다면 압축이 압도적으로 남는 장사고, 같은 기계 안에서 순식간에 오가는 작은 데이터라면 오히려 손해다.
여기에 하나가 더 붙는다. 압축된 데이터는 중간을 못 읽는다. 노트에 “위 3줄, 12자”라고 적혀 있으면 그 줄만 봐서는 뜻을 모르고 위를 읽어야 안다. 압축 파일도 대개 앞에서부터 풀어야 뒤가 나온다. 파일 한가운데만 살짝 고치는 일이 압축된 상태에서 어려운 이유가 이거다.
실무에서: 이미 사방에서 돌고 있다
압축은 배워서 새로 켜는 기능이 아니라 이미 켜져 있는 것을 아는 일에 가깝다. 지금 만지는 시스템에도 최소한 이만큼은 돌고 있다.
- HTTP 응답 - 브라우저가 “압축된 것도 받을 수 있다”고 알리면 서버가 줄여서 보낸다. 요청과 응답의 헤더가 이 협상을 한다
- 이미지와 동영상 - JPEG, PNG, MP4는 전부 압축 형식이다. “압축을 건다”가 아니라 포맷 자체가 압축이다
- 로그와 백업 - 오래된 로그는 압축해서 보관한다. 로그만큼 반복이 심한 데이터도 드물다
- 데이터베이스와 저장소 - 블록 단위로 압축해 디스크를 아끼는 옵션이 대부분 있다
그래서 실무의 질문은 “압축을 쓸까요”가 아니다. **“이 자리에서 압축이 이득인가”**다. 이미 압축된 JPEG을 다시 압축하면 CPU만 태우고 크기는 그대로다. 이 판단을 제대로 하려면 무엇이 줄고 무엇이 안 주는지를 알아야 하고, 그게 이 시리즈가 하려는 일이다.
정리
- 압축은 데이터를 누르는 게 아니라 같은 내용을 더 짧게 적는 방법을 찾는 것이다.
- 줄어드는 이유는 둘뿐이다. 반복이 있거나 치우침이 있거나.
- 둘 다 없으면 안 줄어든다. 난수, 이미 압축된 파일, 암호문이 꿈쩍 않는 이유가 전부 이것이다.
- 인코딩과 층이 다르다. 인코딩은 뜻을 바이트로 옮기고, 압축은 그 바이트를 짧게 다시 적는다.
- 공짜가 아니다. 바이트와 CPU 시간을 맞바꾸는 거래이고, 중간을 못 읽는다는 대가도 붙는다.
다음 글은 두 이유 중 첫째로 들어간다. 같은 말이 또 나올 때 두 번 적지 않는 법부터 본다.