하나의 워드가 세 개의 세계를 관통한다


세 개의 세계

컴퓨터 과학에는 세 개의 세계가 있다.

네트워크의 세계. 데이터는 바이트 스트림으로 흐른다. TCP 소켓에서 바이트가 들어오고, 바이트가 나간다. 네트워크 엔지니어의 언어는 패킷, 헤더, 페이로드다.

스토리지의 세계. 데이터는 파일 포맷으로 저장된다. 디스크에 쓰고, 디스크에서 읽는다. 스토리지 엔지니어의 언어는 블록, 오프셋, 정렬이다.

AI의 세계. 데이터는 토큰 시퀀스로 처리된다. LLM은 토큰을 입력받고, 토큰을 출력한다. AI 엔지니어의 언어는 임베딩, 어텐션, 컨텍스트다.

이 세 세계는 서로 다른 언어를 쓴다. 그래서 세계와 세계 사이에는 항상 번역이 필요하다.


번역의 비용

현재 AI 시스템에서 데이터가 이동하는 경로를 따라가보자.

지식이 파일에 저장되어 있다. JSON이나 텍스트로.

이것을 AI에게 전달하려면:

  1. 파일을 열어서 텍스트를 읽는다.
  2. 텍스트를 파싱한다. JSON이면 구조를 해석하고, 필드를 추출한다.
  3. 추출된 텍스트를 토크나이저에 넣는다.
  4. 토크나이저가 텍스트를 토큰 ID 시퀀스로 변환한다.
  5. 토큰 시퀀스가 LLM에 입력된다.

AI가 답변을 생성하면:

  1. LLM이 토큰 시퀀스를 출력한다.
  2. 토큰을 텍스트로 디코딩한다.
  3. 텍스트를 구조화된 포맷으로 직렬화한다.
  4. 직렬화된 데이터를 파일에 쓴다.

단순히 “읽고 쓰는” 작업에 9단계가 필요하다.

매 단계마다 시간이 든다. 매 단계마다 메모리가 든다. 매 단계마다 정보가 손실될 수 있다.

특히 3번과 4번의 토크나이징 과정은 악명 높다. 자연어의 단어 경계와 토크나이저의 토큰 경계가 일치하지 않아서, “이순신"이 “이순"과 “신"으로 쪼개지거나, 하나의 의미 단위가 여러 토큰에 걸쳐 분산된다.

이것이 세 세계가 서로 다른 언어를 쓰는 대가다.


만약 하나의 단위가 세 세계를 관통한다면

이 언어의 1워드는 16비트(2바이트)다.

이 16비트 워드 하나가 동시에 세 가지다.

바이트 스트림의 단위. 네트워크에서 16비트 워드가 연속으로 흘러온다. Big Endian. 2바이트씩 정렬. 추가 파싱 불필요. 도착한 순서대로 읽으면 된다.

파일 포맷의 단위. 네트워크에서 흘러온 스트림을 그대로 디스크에 쓰면 그것이 파일이다. 디스크에서 읽은 바이트를 그대로 네트워크에 보내면 그것이 스트림이다. 직렬화도, 역직렬화도 필요 없다.

LLM 토큰의 단위. 16비트 = 65,536종. 현대 LLM의 어휘 크기(vocabulary size)는 대체로 5만~10만. GPT 계열은 약 50,000, 한국어 특화 모델은 100,000 전후. 65,536은 이 범위의 정중앙에 놓인다. 하나의 16비트 워드가 하나의 LLM 토큰이 된다.

세 세계가 같은 단위를 쓴다. 번역이 사라진다.


변환 0, 손실 0, 오버헤드 0

이것이 실제로 의미하는 것을 구체적으로 보자.

기존 방식: 9단계

[파일] → 읽기 → 파싱 → 텍스트 추출 → 토크나이징 → [LLM]
[LLM] → 디코딩 → 직렬화 → 쓰기 → [파일]

바이너리 스트림 방식: 1단계

[파일/스트림] → [LLM]
[LLM] → [파일/스트림]

파일을 읽으면 그것이 곧 토큰 시퀀스다. LLM이 출력한 토큰 시퀀스를 그대로 쓰면 그것이 곧 파일이다. 네트워크에서 들어온 스트림을 그대로 LLM에 넣으면 된다.

변환 0. 파싱 0. 토크나이징 0. 손실 0. 오버헤드 0.


왜 8비트가 아닌가

8비트는 256종이다.

256개의 심볼로 세계를 표현하기에는 너무 적다. 알파벳, 숫자, 기본 문장부호를 배정하면 이미 절반이 찬다.

8비트를 기본 단위로 쓰면, 대부분의 의미 있는 토큰이 2바이트 이상이 된다. 그러면 가변 길이 인코딩이 필요하고, 가변 길이는 파싱을 복잡하게 만든다.

바이트 스트림으로서는 적합하지만, 토큰 단위로서는 표현력이 부족하다.


왜 32비트가 아닌가

32비트는 약 43억 종이다.

표현력은 충분하다. 넘치고도 남는다. 그러나 문제는 효율이다.

이 포맷에서 가장 자주 등장하는 패킷은 Tiny Verb Edge로, 2워드다. 16비트 기준이면 4바이트. 32비트 기준이면 8바이트. 고빈도 패킷의 크기가 2배가 된다.

LLM의 관점에서도 문제가 있다. 토큰 하나가 32비트면, 같은 컨텍스트 윈도우에 절반의 토큰만 들어간다. 현재 LLM의 컨텍스트 길이가 제한된 자원인 상황에서, 토큰 하나가 전달하는 정보량 대비 차지하는 공간이 비효율적이다.

32비트 워드는 이 언어의 토큰으로서는 과하다.


왜 가변 길이가 아닌가

UTF-8은 가변 길이 인코딩이다. 1바이트에서 4바이트까지 문자에 따라 길이가 달라진다.

이것은 저장 효율에서는 이점이 있지만, 처리 효율에서는 치명적인 약점이 된다.

n번째 문자를 찾으려면 처음부터 세어야 한다. 랜덤 액세스가 불가능하다. SIMD 병렬 처리가 어렵다.

이 언어는 고정 폭 16비트 워드를 기본 단위로 쓴다. n번째 워드의 위치는 n × 2 바이트다. 항상. 랜덤 액세스가 O(1)이다. SIMD로 한 번에 여러 워드를 비교할 수 있다. GPU로 수십억 개를 병렬 스캔할 수 있다.

그러면서도, 패킷 레벨에서는 가변 길이를 허용한다. Tiny Verb Edge는 2워드, Event6 Edge는 최대 8워드. 워드 단위는 고정이지만, 패킷 단위는 유연하다.

고정 폭의 처리 효율과 가변 길이의 표현력. 16비트 워드는 이 둘을 동시에 달성한다.


유니코드가 증명한 길

유니코드는 인류가 만든 가장 성공적인 인코딩 표준이다.

UTF-16의 기본 단위는 16비트(2바이트)다. 기본 다국어 평면(BMP)의 65,536자를 1워드로 표현하고, 그 밖의 문자는 서로게이트 페어(2워드 = 4바이트)로 확장한다.

이 검증된 구조를 따르면 된다.

기본 의미소 65,536종을 1워드로 표현하고, 복합 패킷은 여러 워드로 확장한다.

유니코드가 “한 글자 = 2바이트"라는 기본 단위 위에서 전 세계의 모든 문자를 표현하듯, 이런 언어는 “한 워드 = 2바이트"라는 기본 단위 위에서 AI 추론의 모든 요소를 표현한다.


하위 호환과 상위 확장

16비트의 또 다른 강점은 정렬이다.

16은 8의 배수이고, 32의 약수이며, 64의 약수이고, 128의 약수다.

이것은 어떤 방향으로 확장해도 정렬이 깨지지 않는다는 뜻이다.

미래에 트랜스포머 아키텍처가 바뀌어서 토큰이 32비트가 되면? 16비트 워드 2개가 1토큰이 된다. 정렬 문제 없음.

64비트가 되면? 16비트 워드 4개가 1토큰이 된다. 여전히 정렬 문제 없음.

반대로, 8비트 임베디드 시스템에서 이 포맷을 처리하면? 16비트 워드를 상위 바이트, 하위 바이트로 나눠 읽으면 된다.

하위 호환은 절대 유지되어야 한다. 16비트 워드가 이것을 물리적으로 보장한다.

미래 지성체의 워드 크기를 예측할 수 없지만, 16비트의 배수 정렬이 어떤 크기와도 호환됨을 보장한다.


3중 구조

정리하자.

16비트 1워드는 동시에 세 가지다.

세계1워드의 역할
네트워크바이트 스트림의 단위
스토리지파일 포맷의 단위
AILLM 토큰의 단위

이 세 세계를 하나의 단위가 관통한다.

스트림을 그대로 저장하면 파일이다. 파일을 그대로 읽으면 토큰이다. 토큰을 그대로 보내면 스트림이다.

변환이 없다. 번역이 없다. 손실이 없다.

이것이 16비트인 이유다. 8비트도 아니고, 32비트도 아니고, 가변 길이도 아닌. 세 세계의 교차점에 정확히 놓인 숫자.