데이터와 압축
컴퓨터 안의 모든 것은 0과 1다. 그 0과 1로 글자·사진을 나타내고, 작게 줄이고, 남이 못 읽게 잠그는 방법을 정리한다.
비트, 바이트, 16진수
- 비트는 0 또는 1 하나다. 비트 8개가 바이트이고, 바이트 하나는 0~255의 256가지를 나타낸다.
- 2진수는 자리마다 1, 2, 4, 8…을 뜻한다.
1011= 8 + 0 + 2 + 1 = 11이다. - 16진수는 4비트를 글자 하나(0~9, A~F)로 적는다. 바이트 하나가 두 글자가 되어 읽기 쉽다. 색 코드
#FF8800은 빨강 255, 초록 136, 파랑 0이다. - KB와 KiB: 1KB = 1,000바이트, 1KiB = 1,024바이트. 저장장치 회사는 1,000 단위, 운영체제는 1,024 단위로 세는 경우가 많아, 1TB 디스크가 약 931GB로 보인다.
- 음수: 2의 보수: 부호 있는 정수는 맨 앞 비트가 1이면 음수로 읽는다. −x는 x의 비트를 모두 뒤집고 1을 더해 만든다. 8비트면 −128~127을 담고,
11111111이 −1이다. 이렇게 두면 덧셈 회로 하나로 양수·음수를 함께 더할 수 있다. 대신 127에 1을 더하면10000000, 곧 −128이 되는 오버플로가 조용히 일어난다. - 실수: 소수는 IEEE 754 부동소수점으로 적는데, 0.1 같은 수는 2진수로 끝나지 않아 근삿값만 담긴다.
0.1 + 0.2가 0.3과 다르게 나오는 이유는 계산 과학 노트의 부동소수점 절에 있다. - 바이트 순서: 여러 바이트로 된 수를 메모리에 어느 쪽부터 놓을지(엔디언)는 CPU마다 정해져 있다. 파일이나 네트워크로 바이트를 주고받을 때 어긋나면 숫자가 엉뚱하게 읽힌다. 자세한 것은 컴퓨터 구조 노트의 명령어 집합 절에 있다.
이 사이트의 헥스 편집기로 파일을 바이트 단위로 직접 볼 수 있다.
글자도 숫자다: 텍스트 인코딩
글자마다 번호를 정한 표가 문자 집합(유니코드)이고, 그 번호를 바이트로 적는 방법이 인코딩다. 지금은 대부분 UTF-8을 쓴다. 영문은 1바이트, 한글은 보통 3바이트다. 다른 인코딩(예: EUC-KR)으로 저장된 파일을 UTF-8로 읽으면 글자가 깨진다. 이 사이트의 인코딩 도구로 바꿔 볼 수 있다.
인코딩이 같아도 글자가 달라 보일 수 있다. 유니코드에는 "각"을 글자 하나로 적는 방법과 초성 ㄱ·중성 ㅏ·종성 ㄱ 세 자모를 이어 적는 방법이 모두 있고, 둘은 같은 글자로 친다. 앞쪽으로 모으는 것이 NFC, 자모로 푸는 것이 NFD다(유니코드 표준 부속서 UAX #15). 파일 이름을 NFD로 저장하는 시스템에서 만든 파일을 다른 시스템으로 옮기면 "한글"이 "ㅎㅏㄴㄱㅡㄹ"처럼 자모가 풀려 보이거나, 눈에는 같은 두 이름이 서로 다른 문자열로 비교된다. 글자를 비교·검색·저장하기 전에 한 형식(보통 NFC)으로 맞춘다. UTF-8 인코딩 규칙, 글자 수 세기, 한글 조합 공식, 시간대까지는 문자와 시간 노트에 있다.
압축: 무손실과 손실
무손실 — 되돌리면 원래와 똑같다 (ZIP, PNG)
- 데이터에 반복과 치우침이 있을수록 줄어든다. 얼마나 예측하기 어려운지를 재는 값이 엔트로피다. 완전히 무작위인 데이터는 엔트로피가 최대라 줄일 수 없다. 이미 압축된 파일을 다시 압축해도 작아지지 않는 이유다.
- 허프만 부호화: 자주 나오는 글자에는 짧은 비트, 드문 글자에는 긴 비트를 준다(모스 부호와 비슷한 생각).
- LZ 계열: 앞에서 나온 내용이 다시 나오면 “몇 칸 앞에서 몇 글자 복사”로 바꿔 적는다.
손실 — 사람이 잘 못 느끼는 부분을 버린다 (JPEG, MP3, 동영상)
- 크로마 서브샘플링: 눈은 밝기 변화에 민감하고 색 변화에는 둔하다. 그래서 색 정보는 해상도를 낮춰 저장한다.
- DCT: JPEG은 이미지를 8×8 블록으로 나누고, 각 블록을 “완만한 변화부터 촘촘한 무늬까지” 성분으로 바꾼다. 눈에 덜 띄는 촘촘한 성분을 거칠게 줄여 저장한다. 품질을 낮추면 블록 경계가 보이는 이유다.
- 손실 압축은 저장할 때마다 조금씩 더 망가진다. 편집 중간본은 무손실로 저장한다.
이 사이트의 스테가노그래피(이미지 DCT)는 바로 이 DCT 성분에 데이터를 숨기고, 이미지 LSB는 픽셀 값의 가장 낮은 비트에 숨긴다. GIF·WebP의 구간을 잘라 다시 압축해 보려면 움직이는 이미지 편집기를 쓴다.
암호와 해시
| 종류 | 원리 | 쓰임 |
|---|---|---|
| 대칭 암호 | 잠그는 열쇠와 여는 열쇠가 같다. 빠르다 | 파일·디스크 암호화, 연결이 맺어진 뒤의 HTTPS 통신 |
| 비대칭(공개키) 암호 | 공개키로 잠근 것은 짝이 되는 개인키로만 열린다. 느리다 | 처음 만난 상대와 열쇠 정하기, 전자 서명 |
| 해시 | 어떤 데이터든 고정 길이의 “지문”으로 바꾼다. 되돌릴 수 없고, 한 글자만 바뀌어도 완전히 달라진다 | 파일 무결성 확인, 비밀번호 저장, git 커밋 ID |
HTTPS는 둘을 섞는다. 공개키 암호로 대칭 열쇠를 안전하게 나눈 뒤, 실제 내용은 빠른 대칭 암호로 주고받는다.
QR 코드는 일부가 가려져도 읽힌다
QR 코드는 검은·흰 칸을 비트로 읽는다. 세 모서리의 큰 사각형은 위치와 방향을 찾는 표시다. 데이터와 함께 오류 정정 부호(리드-솔로몬)를 덧붙여, 등급에 따라 대략 7~30%가 가려지거나 더러워져도 원래 내용을 복원한다. 가운데에 로고를 얹은 QR이 읽히는 이유다.
흔한 오해
- “압축은 여러 번 하면 더 작아진다” — 한 번 압축하면 반복이 사라져 더 줄지 않는다.
- “해시는 암호화다” — 해시는 되돌릴 수 없는 지문이다. 암호화는 열쇠로 되돌릴 수 있다.
- “Base64로 바꾸면 암호화된다” — Base64는 3바이트를 6비트씩 네 글자로 옮겨 적는 인코딩일 뿐이다. 열쇠가 없어 누구나 되돌리고, 크기는 약 3분의 1 늘어난다. 표준인 RFC 4648도 보안 절에서 기밀성을 주지 않는다고 적는다. 텍스트 형식에 바이너리를 실을 때의 함정은 시스템 설계 › 데이터 모델과 인코딩에 있다.
- “PNG가 JPEG보다 항상 좋다” — 사진은 JPEG·WebP가 훨씬 작다. PNG는 글자·도형·투명 배경에 알맞다.
- Joel Spolsky, 유니코드 최소 지식 — 인코딩이 깨지는 이유를 다룬 고전 글
- Unraveling the JPEG — JPEG 압축 단계를 직접 만져 보는 대화형 글
- Thonky QR Code Tutorial — QR 코드를 손으로 만드는 단계별 설명
- UAX #15 Unicode Normalization Forms — NFC·NFD와 한글 음절의 분해·조합
- RFC 4648 — Base64·Base32·Base16 인코딩과 "암호화가 아니다"라는 보안 절
- Two's complement (Wikipedia) — 2의 보수로 음수를 나타내는 법과 오버플로
- Bartosz Ciechanowski — 직접 만져 보는 대화형 원리 설명
- Making Software: Bits, bytes and binary — Dan Hollick, 유료 전자책
- Making Software: Entropy and compression — Dan Hollick, 유료 전자책
- Making Software: Image compression — Dan Hollick, 유료 전자책
- Making Software: Cryptography — Dan Hollick, 유료 전자책
- Making Software: QR and barcodes — Dan Hollick, 유료 전자책
- Dan Hollick (X) — Making Software 저자