버로우즈–휠러 변환(BWT) 계산기
문자열을 한 칸씩 돌린 것을 모두 사전순으로 늘어놓고 마지막 열을 뽑아내는 과정을 표로 보여 줍니다. 길이는 그대로인데 같은 글자가 뭉치는 이유, 마지막 열만으로 원문이 복원되는 이유, Move-to-Front를 붙이면 무엇이 달라지는지까지 확인할 수 있습니다.
48글자까지. 회전을 전부 늘어놓아 보이는 것이 목적이라 짧게 넣는 편이 읽기 좋습니다.
변환 결과 (마지막 열)
BNN^AA|A
원문이 놓인 행 번호는 6번입니다. 되돌리려면 이 두 가지가 함께 있어야 합니다. 길이는 8글자 그대로이고, 줄어든 것은 「덩어리 수」뿐입니다.
회전을 사전순으로 늘어놓은 표
파랗게 칠한 줄이 원문입니다. 맨 오른쪽 열을 위에서부터 읽은 것이 변환 결과이고, 맨 왼쪽 글자를 위에서부터 읽으면 AAABNN^| — 마지막 열을 그냥 정렬한 것입니다. 모든 행이 같은 글자를 돌린 것이므로 열마다 글자 구성이 같기 때문입니다.
Move-to-Front를 붙이면
1 2 0 3 3 0 4 1
MTF는 방금 쓴 글자를 목록 맨 앞으로 옮깁니다. 그래서 같은 글자가 이어지면 0이 줄줄이 나오고, 여기에 런길이 부호화를 붙이면 크게 줄어듭니다. bzip2가 쓰는 순서가 정확히 이것입니다 — BWT → MTF → RLE → 허프만. BWT를 거친 쪽의 0 비율이 더 높은 것이 이 순서를 쓰는 이유입니다.
사용 방법
- 1문자열을 넣으면 모든 회전이 사전순으로 늘어섭니다.
- 2맨 오른쪽 열을 위에서부터 읽은 것이 변환 결과입니다.
- 3파랗게 칠한 줄이 원문이며, 그 행 번호가 역변환에 필요합니다.
- 4덩어리 수가 얼마나 줄었는지, 글자별 엔트로피는 그대로인지 표에서 봅니다.
- 5Move-to-Front를 붙였을 때 0의 비율이 얼마나 오르는지 견줍니다.
자주 묻는 질문
문자열을 한 칸씩 돌린 것을 모두 만들어 사전순으로 늘어놓고 마지막 열만 뽑아내는 재배열입니다. 길이도 글자 개수도 그대로이지만 같은 글자가 뭉쳐 나오게 되어, 뒤에 붙는 압축이 훨씬 잘 먹습니다. bzip2가 BWT → MTF → 런길이 부호화 → 허프만 순서로 이 변환을 앞단에 씁니다.
되지 않습니다. BWT 자체는 한 바이트도 줄이지 않으며 글자별 엔트로피도 정확히 그대로입니다. 「BWT로 압축했다」는 말은 틀렸고 「BWT로 압축이 잘 되게 만들었다」가 맞습니다. 바뀌는 것은 같은 글자가 이어지는 덩어리의 수뿐이고, 그 덕에 뒤에 붙는 단계가 잘 먹는 것입니다.
정렬 기준이 각 행의 「뒤에 오는 글자들」인데, 그 행의 마지막 글자는 그 글자들의 바로 앞 글자이기 때문입니다. 영어에서 "he" 앞에는 t가 자주 오므로 "he…"로 시작하는 행이 한 덩어리로 모이면 그 행들의 마지막 열에 t가 줄줄이 늘어섭니다. 문맥이 비슷한 자리의 앞 글자가 비슷하다는 성질을 정렬로 끌어모으는 셈입니다.
첫 열이 마지막 열을 정렬한 것이고, 같은 글자끼리는 두 열에서 순서가 같기 때문입니다. 마지막 열의 k번째 A와 첫 열의 k번째 A가 원문의 같은 자리를 가리킵니다. 두 열의 A들이 모두 「그 뒤에 오는 문자열의 사전순」으로 줄 서 있어서 그렇습니다. 이 대응(LF 매핑)을 따라가면 원문을 뒤에서부터 한 글자씩 되짚을 수 있습니다.
어느 행이 원문이었는지 알아야 역변환을 시작할 수 있기 때문입니다. 끝을 알리는 특수문자를 문자열 끝에 붙이는 방식을 쓰면 행 번호 없이도 되지만, 그러면 원문에 그 문자가 없어야 한다는 조건이 붙습니다. 실제 구현은 아무 데이터에나 쓸 수 있는 행 번호 쪽을 대개 씁니다.
방금 쓴 글자를 목록 맨 앞으로 옮기고, 각 글자를 「그때 목록에서의 자리」로 적는 변환입니다. 같은 글자가 이어지면 0이 줄줄이 나오므로 뒤에 런길이 부호화를 붙이면 크게 줄어듭니다. BWT를 거친 뒤에 붙이면 0의 비율이 눈에 띄게 오르는데, bzip2가 두 변환을 이 순서로 붙이는 이유가 그것입니다.
전송되지 않습니다. 모든 계산은 브라우저 안에서 이뤄지고, 입력값은 이 기기에만 남습니다.
알아두면 좋은 점
- 널리 실린 예제 "^BANANA|" → "BNN^AA|A"와 대조해 검증했습니다. 정렬된 회전 여덟 줄이 교과서 표와 글자 하나까지 같은 것, 원문이 6번 줄에 놓이는 것까지 고정했습니다. "banana" → "nnbaaa"도 함께 맞췄습니다.
- 왕복 검산은 무작위 문자열 600벌(알파벳 2~8종, 한글·공백·특수문자 포함, 길이 1~24)을 변환한 뒤 되돌려 원문과 대조해 했습니다. 회전이 모두 같아지는 주기 입력(abab, abcabcabc)과 한 글자짜리도 따로 넣었습니다.
- 첫 열이 마지막 열을 정렬한 것과 같다는 것, LF 매핑이 0부터 n−1까지의 순열이며 첫 열과 마지막 열의 같은 글자를 순서대로 잇는다는 것을 무작위 입력으로 확인했습니다.
- 변환 전후로 길이와 글자 개수가 그대로이고 글자별 엔트로피가 정확히 같다는 것을 테스트로 고정했습니다. BWT가 압축이 아니라는 것을 가장 또렷이 보여 주는 값입니다.
- 되풀이가 있는 글은 덩어리 수가 5분의 1 아래로 떨어지지만, 무작위 문자열은 평균 95% 이상 그대로라는 것도 재어 두었습니다. BWT는 되풀이를 찾아내는 변환이지 아무 데나 듣는 것이 아닙니다.
- 문자열 비교는 UTF-16 코드단위가 아니라 코드포인트 차례로 못 박았습니다. 자바스크립트의 기본 비교를 그대로 쓰면 서로게이트 쌍이 섞였을 때 변환과 역변환의 기준이 어긋납니다.
- 48글자까지 다룹니다. 회전을 전부 늘어놓아 보이는 것이 목적이라 그보다 길면 표가 읽히지 않습니다.
함께 보면 좋은 도구
마지막 검증: 2026년 9월 1일 · 결과는 참고용 추정치입니다.