음 · CHAPTER 02

큐브와 27트릿

앞 장에서 우리는 트릿(trit)이라는 가장 작은 조각을 손에 쥐었습니다. -1, 0, +1을 담는 세 상태의 단위, 그리고 거기에 구분자 U를 더한 네 부호 T·O·A·U. 나는 그 장을 닫으며 "이 부호들이 모여 무엇이 되는가"라는 질문을 일부러 남겨 두었습니다. 한 알의 트릿은 그 자체로는 아무것도 아닙니다. 글자 하나가 아직 단어가 아니듯이. 이 장에서 나는 그 트릿들이 어떻게 하나의 완결된 단위로 묶이는지, 그리고 그 묶음이 어떻게 크라우니의 메모리 구조 전체를 결정하는지를 정확한 스펙으로 보여 드리려 합니다. 단위의 이름은 큐브(Cube)입니다.

1. 큐브 — 기본 메모리 단위

크라우니의 메모리 구조는 큐브라 불리는 기본 단위에서 출발합니다. '큐브'는 정육면체를 뜻하지만, 여기서의 함의는 기하학적 형태가 아니라 구조적 완결성입니다. 가로 3, 세로 3, 높이 3으로 쌓은 27칸, 그 27칸이 비로소 의미 있는 정보를 담는 최소 집합이 됩니다.

1.1 정의

1 큐브 = 27 트릿 = 3³

이 수는 우연이 아닙니다. 3진 체계의 기본 단위가 트릿이라면, 27은 그 트릿들이 의미 있는 데이터와 메타데이터를 함께 담을 수 있는 최소 단위입니다. 기존 컴퓨터에서 1바이트(8비트 = 256값)가 메모리 주소의 기본 단위인 것과 같이, 크라우니에서는 큐브가 그 역할을 맡습니다.

실제 메모리 할당에서 큐브는 7바이트 + 1패딩 = 8바이트로 정렬됩니다. 이는 현대 CPU의 캐시 라인 효율을 고려한 선택이며, 27트릿 자체의 논리 폭(2비트 × 27 = 54비트)과는 구분됩니다.

1.2 메모리 레이아웃

트릿은 2비트로 인코딩됩니다(상태 3개 ≤ 2² = 4). 따라서 한 바이트(8비트)에는 최대 4개의 트릿이 들어갑니다. 27트릿은 T1(LST, Least Significant Trit) = index 0에서 시작해 T27(MST, Most Significant Trit) = index 26까지 순차 배치되며, 표준 레이아웃은 다음과 같습니다.

byte[0]: T1(1:0)  T2(3:2)  T3(5:4)  T4(7:6)
byte[1]: T5   T6   T7   T8
byte[2]: T9   T10  T11  T12
byte[3]: T13  T14  T15  T16
byte[4]: T17  T18  T19  T20
byte[5]: T21  T22  T23  T24
byte[6]: T25  T26  T27  (미사용)
byte[7]: 패딩

byte[6]의 마지막 2비트는 미사용으로 남고, byte[7] 전체가 정렬 패딩입니다. 27트릿이 24트릿(byte[0]~byte[5])과 메타 3트릿(byte[6])으로 자연스럽게 갈리는 이 구조는, 다음 절에서 보일 데이터/메타 분리와 정확히 맞물립니다.

1.3 메타데이터 — 마지막 3개 트릿

큐브의 마지막 세 트릿 T25·T26·T27은 일반 데이터를 담지 않고 역할 태그로 기능합니다. 레고 상자에 붙은 "이 안에 자동차 부품이 들었습니다"라는 딱지처럼, 큐브 스스로 자신이 무엇인지를 선언하는 자리입니다.

T27 — 큐브 역할 태그(Role Tag). 이 큐브가 무엇인지 구분합니다.

값의미내용
T(+1)데이터T1~T24가 균형3진 정수값(또는 문자열·셀참조)을 담는다
O(0)명령(opcode)T1~T6이 ISA729 6-트릿 인코딩을 담는다
A(-1)체이닝이전 큐브의 데이터를 확장한다 — 연속 큐브가 하나의 논리값을 표현

T26 — 값 타입 태그(Type Tag). T27이 T(데이터)일 때만 해석됩니다.

값타입비고
T(+1)숫자(정수)균형3진 인코딩
O(0)문자열UTF-8 또는 3진 압축 인코딩
A(-1)셀 참조규칙 기반 에이전트의 셀 저장소를 가리킴

T25 — 크기 태그(Size Tag). 역시 T27이 T(데이터)일 때 적용됩니다.

값크기의미
T(+1)확장이 값은 다음 큐브로 이어진다
O(0)보통정확히 1개 큐브에 수용된다 (가장 일반적)
A(-1)소형1개 큐브의 일부만 사용한다 (메모리 절약 마크)

세 태그가 T·O·A 세 값으로 똑같이 갈린다는 점에 주목하기 바랍니다. 부호 체계의 대칭성이 메타데이터 설계에까지 일관되게 투영되어 있습니다.

1.4 역할 판별 알고리즘

런타임이 큐브 하나를 해석할 때의 순서는 명확합니다. 언제나 T27을 먼저 읽습니다.

  1. T27 = T → 데이터 큐브. T26으로 타입을, T25로 크기를 확인한 뒤 T1~T24(메타 참여분 포함 시 T1~T26)를 균형3진 정수로 디코딩한다.
  2. T27 = O → 명령 큐브. T1~T6을 6-트릿 slotcode로 읽어 opcode를 산출한다.
  3. T27 = A → 체이닝 큐브. 직전 큐브의 데이터를 확장한다.

의사코드로 옮기면 분기는 세 갈래로 끝납니다.

if (cube.t[26] == T)      value  = balanced_ternary_to_i64(cube.t[0..25]);
else if (cube.t[26] == O) execute(decode_opcode(cube.t[0..5]));
else /* A */              extend_previous(cube);

명령 큐브의 경우 T1~T6을 다시 세 쌍으로 끊어 command = (T1,T2), group = (T3,T4), sector = (T5,T6)로 읽고 opcode = sector × 81 + group × 9 + command를 계산합니다. 이 공식은 3절에서 다시 정밀하게 다룹니다.

2. 균형3진 인코딩 — 데이터의 표현

데이터 큐브에서 실제 정수값을 담는 트릿은 T1~T26의 26트릿입니다. T27만이 순수한 역할 태그이고, 나머지는 수치 표현에 동원될 수 있습니다. 이로써 표현 가능한 정수 범위는 다음과 같습니다.

최대값 = (3²⁶ − 1) / 2 = ±141,214,768,240

약 54비트에 해당하는 폭이며, 64비트 정수형 int64에 충분히 수용됩니다. 이 자릿수는 그대로 외워 두어도 좋습니다 — 큐브 한 칸이 담을 수 있는 정수의 절대 한계이기 때문입니다.

2.1 변환 알고리즘

십진 정수를 균형3진으로 옮기는 과정은 표준 3진 변환과 한 군데에서 갈라집니다. 핵심은 나머지가 2일 때 −1로 바꾸고 몫을 1 올리는 것입니다.

encode_balanced_ternary(int64 val, trit out[26]):
  for i = 0..25:
    r = val % 3
    if (r == 2) { r = -1; val += 1; }   // A로 인코딩, 올림
    out[i] = r                          // T(+1), O(0), A(-1)
    val /= 3

이 보정 덕분에 균형3진은 중복 표현이 없고, 음수와 양수가 완전 대칭입니다. 0을 기준으로 수직선을 접으면 양쪽이 포개진다는 뜻이며, 이 대칭성이 뒤이어 메모리 정렬과 타입 체계에까지 일관되게 흐릅니다.

2.2 2-트릿 → 정수 매핑

두 트릿(2-trit)을 한 묶음으로 보면 0~8의 정수 아홉 값으로 사상됩니다. 순서는 반드시 A→O→T(−1→0→+1)입니다.

쌍트릿값정수
AA(−1, −1)0
AO(−1, 0)1
AT(−1, +1)2
OA( 0, −1)3
OO( 0, 0)4
OT( 0, +1)5
TA(+1, −1)6
TO(+1, 0)7
TT(+1, +1)8

이 아홉 매핑이 다음 절 ISA729의 sector/group/command 인코딩에 그대로 재사용됩니다. 같은 표가 데이터에도 명령에도 쓰인다는 점 — 바로 이것이 크라우니가 데이터와 명령을 같은 살로 짠다는 증거입니다.

3. ISA729와 6-트릿 Opcode 인코딩

명령어 집합 ISA729는 729개 슬롯을 가집니다. 729 = 3⁶ = 9 × 9 × 9, 3진 체계에서 자연스럽게 솟아오르는 수입니다.

3.1 슬롯 구조와 인코딩 공식

729 슬롯은 9 섹터(sector) × 9 그룹(group) × 9 커맨드(command)로 조직됩니다.

opcode  = sector * 81 + group * 9 + command
sector  = opcode / 81
group   = (opcode % 81) / 9
command = opcode % 9          (sector, group, command ∈ [0, 8])

명령 큐브의 T1~T6 위치는 이 세 좌표를 2-트릿씩 담습니다.

T1, T2 → 2-트릿 = command (0~8)
T3, T4 → 2-트릿 = group   (0~8)
T5, T6 → 2-트릿 = sector  (0~8)
T7~T26 → O 패딩,  T27 = O (명령 역할)

3.2 섹터별 기능 영역

9개 섹터는 각각 하나의 기능 영역을 맡습니다. 6-트릿 접두는 (sector, group, command) = (s, 0, 0)일 때의 선두 패턴입니다.

섹터opcode 범위접두기능 영역
00–80AA____스택·흐름 제어·함수·코루틴·디버그
181–161AO____산술·비트·통계·벡터·행렬·노이즈
2162–242AT____비교·논리·3진 연산
3243–323OA____제어 흐름 (JMP·CALL·RET)
4324–404OO____입출력·표현
5405–485OT____컬렉션·배열·맵
6486–566TA____타입·메모리
7567–647TO____에러·수학 확장·네트워크
8648–728TT____셀·CTP·트릿·테스트·ISA 반성

3.3 인코딩 예시

몇 가지 대표 opcode를 6-트릿으로 풀어 보면 공식이 빈틈없이 닫히는 것을 확인할 수 있습니다.

  • NOP(0) = sector 0, group 0, command 0 → AAAAAA
  • ADD(81) = sector 1, group 0, command 0 → AOAAAA
  • EQ(162) = sector 2, group 0, command 0 → ATAAAA
  • PRINT(324) = sector 4, group 0, command 0 → OAAAAA
  • CELL_NEW(696) = sector 8(TA), group 5(OT), command 3(OA) → OAOTTA

마지막 예의 검산: 8 × 81 + 5 × 9 + 3 = 648 + 45 + 3 = 696. 좌표 셋이 곧바로 트릿 패턴이 되고, 트릿 패턴이 곧바로 정수 opcode가 됩니다.

3.4 구현 상태 (2026-05-27 측정)

  • VM 구현 완성도: 729/729 슬롯 — 100%(fallthrough 포함).
  • 한선씨 키워드 매핑: 432개 (한글 명령어 → opcode).
  • 표준 외 확장: 106개 — 하드웨어(HDL) 49 + 이미지·오디오 코덱 56 + 시스템 1.

여기서 한 가지 구분을 분명히 해 둡니다. 슬롯 총량은 9×9×9 = 729로 고정이며, VM은 fallthrough를 포함해 729/729를 모두 구현합니다. 한편 "의미 있는 명령"의 이론적 상한은 별도로 489로 추정되는데, 이는 구현 슬롯 수가 아니라 설계 여백의 추정치입니다. 책의 다른 장에서 489라는 수를 만나거든 이 둘을 혼동하지 마시기 바랍니다.

이 1:1 정합은 크라우니 헌법 9조(2026-05-21 선언)의 핵심 문구 — "한선씨 RPN = ISA729 1:1" — 의 달성 상태를 그대로 가리킵니다. 한국어 RPN으로 적은 더해가 ISA729의 ADD와, 빈틈 없이 한 칸씩 맞물린다는 선언입니다. 이 상승의 사다리 — Rust/Swift → 한선씨 고수준 → 한선씨 RPN → 기계어 — 는 뒤의 한선씨 장에서 본격적으로 오르게 됩니다.

4. 큐브와 프로그램 구조

개별 큐브가 메모리에 배열되는 방식은 프로그램 실행 구조를 직접 결정합니다.

4.1 단순 명령 시퀀스

가장 기본적인 구조는 명령 큐브의 단순 나열입니다.

[명령1][명령2][명령3] … [명령N]

각 명령 큐브는 독립적으로 해석되고, 프로그램 카운터(PC)는 한 번에 한 큐브씩 전진합니다.

4.2 데이터와 명령의 혼재

스택 기반 머신에서는 데이터 큐브와 명령 큐브가 메모리상 섞여 존재할 수 있습니다. 다만 한 가지 불변 규칙이 있습니다 — PC가 실행을 위해 도달한 큐브는 반드시 T27 = O여야 합니다. PC가 데이터 큐브(T27 = T)에 닿으면 그것은 체계 오류(system exception)입니다.

4.3 체이닝을 통한 큐브 확장

두 개 이상의 큐브가 하나의 값을 표현해야 할 때, 체이닝 큐브(T27 = A)가 개입합니다.

[큐브1: 데이터, T25=T(확장)] → [큐브2: T27=A(체이닝)] → … → [큐브N: T25=O(보통)]

문자열, 배열, 큰 정수처럼 한 큐브에 다 담기지 않는 값이 이렇게 표현됩니다. 마지막 큐브의 T25는 언제나 O(보통)이어야 하며, 이는 값의 종료를 뜻합니다. T25 = O가 곧 마침표인 셈입니다.

5. 한글 3진 압축

큐브의 27트릿 구조가 가장 우아하게 빛나는 자리 중 하나가 한글 압축입니다. 크라우니는 한글 문자열을 1큐브에 3글자씩 담을 수 있습니다.

5.1 인코딩 원리

한글 한 글자는 초성·중성·종성으로 분해됩니다. 각 요소가 갖는 경우의 수(초성 19, 중성 21, 종성 28)는 2-트릿(범위 0~8)으로는 부족하므로, 모두 3-트릿(범위 0~26)으로 인코딩합니다.

초성(19값) → trit[0:2]
중성(21값) → trit[3:5]
종성(28값) → trit[6:8]
1 한글 = 9 트릿 = 3-트릿 × 3

따라서:

3글자 = 27트릿 = 1큐브

5.2 압축률

UTF-8에서 한글 1자는 3바이트입니다. 3진 압축을 적용하면 트릿당 0.5바이트(2비트) 환산으로 다음과 같이 줄어듭니다.

UTF-8 : 3글자 × 3바이트            = 9.00 바이트
3진   : 3글자 × 9트릿 ÷ 4트릿/바이트 = 2.25 바이트
절약률: (9 − 2.25) / 9             = 25%

한글 1자가 정확히 9트릿, 큐브 하나가 정확히 27트릿이라는 사실이 맞아떨어지기에 가능한 절약입니다. 한글 기반 프로그램과 문서 처리에서 문자열 집약도를 높여 줍니다.

6. 결론 — 큐브가 증명하는 동형성

나는 이 장을 쓰며, 큐브가 단순한 메모리 단위가 아님을 거듭 확인했습니다. 27트릿의 고정 구조(fixed structure)를 통해 크라우니는 세 가지를 한꺼번에 얻습니다.

  1. 명령과 데이터를 동등하게 취급합니다. 같은 2-트릿 매핑표가 데이터 정수에도, opcode 좌표에도 그대로 쓰입니다 — 기호적 동형성(symbolic homomorphism)의 가장 작은 증거입니다.
  2. 역할 태그(T25·T26·T27)로 런타임 타입 정보를 큐브 안에 함께 인코딩합니다. 데이터가 스스로 자신을 설명합니다.
  3. 3진의 대칭성을 메모리 정렬과 타입 체계에 그대로 투영합니다. 양수와 음수가 0을 축으로 포개지듯, T·O·A가 모든 태그에서 똑같이 갈립니다.

트릿 → 큐브 → 프로그램. 앞 장에서 손에 쥔 한 알의 트릿이, 이 장에서 27칸의 완결된 단위가 되고, 그 단위가 줄지어 프로그램이라는 성을 이룹니다. 이 계층적 상승 — 작은 것의 구조가 큰 것의 구조에 그대로 되살아나는 동형성 — 이야말로 우리가 이 책 전체에서 추적할 단 하나의 줄기입니다. 그렇다면 이 큐브가 디스크 위에, 메모리 위에 실제로 어떤 바이트열로 적히는가. 다음 장 "TOAU 인코딩"에서 그 마지막 한 겹을 벗겨 보겠습니다.

내 맘 –

독자 게시판 — 함께 읽고 남기는 곳

불러오는 중…

크라우니 책방에 가입하고 무료로 읽기

첫 번째 책은 선물이에요. 가입하면 100맘을 드리니까, 두 번째 책부터 자유롭게 읽을 수 있어요. 친구를 추천하면 50맘도 생겨요.