3벌식 알고리즘

세 벌 분리, 2벌식과의 차이, 3-2015·공병우 세벌식 개요

3벌식은 한글 자모를 세 벌(초성 벌·중성 벌·종성 벌)로 나누어 서로 다른 글쇠에 배치하는 방식이다. 2벌식과 달리 같은 키초성이 될 때와 종성이 될 때 물리적으로 다른 키이므로, 상태에 따른 키 해석이 필요 없고, 키 → 자모(벌별) 매핑만 하면 된다.


0. 2벌식 vs 3벌식 키 처리 비교

flowchart TD
    subgraph 2벌식["2벌식: 같은 키, 다른 해석"]
        KEY1[자음 키 'r']
        KEY1 --> STATE1{현재 상태?}
        STATE1 --> |초성 없음| CHO1[초성 ㄱ으로]
        STATE1 --> |초+중 있음| JONG1[종성 ㄱ으로]
    end
    
    subgraph 3벌식["3벌식: 다른 키, 같은 해석"]
        KEY2A[초성 키 → 항상 초성 ㄱ]
        KEY2B[종성 키 → 항상 종성 ㄱ]
    end

핵심 차이:

  • 2벌식: “이 키가 초성인가 종성인가?”를 상태로 판단
  • 3벌식: “이 키는 어떤 인가?”로 판단 (상태 불필요)

1. 키 → 유니코드 매핑 (3벌식)

1.1 유니코드 한글 블록

3벌식도 2벌식과 동일한 유니코드 블록을 사용한다:

블록범위용도
Hangul JamoU+1100–U+11FF조합용 자모 (초성·중성·종성 구분)
Hangul Compatibility JamoU+3130–U+318F호환용 자모 (독립 표기)
Hangul SyllablesU+AC00–U+D7AF완성형 음절

1.2 공병우 세벌식 키 → 유니코드 매핑 (예시)

초성 벌 (오른손 영역):

영문 키한글Jamo (초성)Compatibility
yU+1100U+3131
Y (Shift+y)U+1101U+3132
uU+1102U+3134
iU+1103U+3137
I (Shift+i)U+1104U+3138
oU+1105U+3139
pU+1106U+3141
hU+1107U+3142
H (Shift+h)U+1108U+3143
jU+1109U+3145
J (Shift+j)U+110AU+3146
kU+110BU+3147
lU+110CU+3148
L (Shift+l)U+110DU+3149
;U+110EU+314A
U+110FU+314B
nU+1110U+314C
mU+1111U+314D
,U+1112U+314E

중성 벌 (가운데 영역):

영문 키한글Jamo (중성)Compatibility
fU+1161U+314F
6U+1162U+3150
tU+1163U+3151
7U+1164U+3152
rU+1165U+3153
cU+1166U+3154
eU+1167U+3155
8U+1168U+3156
dU+1169U+3157
4U+116DU+315B
sU+116EU+315C
5U+1172U+3160
wU+1173U+3161
gU+1175U+3163

종성 벌 (왼손 영역):

영문 키한글Jamo (종성)Compatibility
xU+11A8U+3131
X (Shift+x)U+11A9U+3132
vU+11ABU+3134
/U+11AEU+3137
zU+11AFU+3139
aU+11B7U+3141
!U+11B8U+3142
qU+11BAU+3145
Q (Shift+q)U+11BBU+3146
1U+11BCU+3147
@U+11BDU+3148
#U+11BEU+314A
$U+11BFU+314B
3U+11C0U+314C
2U+11C1U+314D
%U+11C2U+314E

참고: 위 매핑은 공병우 세벌식 390 레이아웃 예시이다. 3-90, 3-91, 3-2015 등 세벌식 배열마다 키 위치가 다르다.

1.3 2벌식과 3벌식의 유니코드 차이

항목2벌식3벌식
초성 ㄱ 입력’r’ 키 → U+1100 (상태에 따라)초성 벌 ‘y’ 키 → U+1100 (항상)
종성 ㄱ 입력’r’ 키 → U+11A8 (상태에 따라)종성 벌 ‘x’ 키 → U+11A8 (항상)
유니코드 코드포인트동일동일
키→자모 결정 방식상태(L/LV/LVT)에 따라키 위치(벌)에 따라

최종 유니코드 출력은 동일하지만, 어떤 키어떤 자모에 매핑되는지가 다르다.


2. 2벌식과의 차이

항목2벌식3벌식
벌 구분자음 벌·모음 벌 두 벌초성 벌·중성 벌·종성 벌 세 벌
같은 키자음 키 하나가 초성이 될 수도 종성이 될 수도 있음초성 키·종성 키가 분리되어 있음
상태 의존현재 상태(초성만 / 초성+중성 / 초성+중성+종성)에 따라 같은 자음 키를 초성 또는 종성으로 해석키 위치만으로 초성/중성/종성 구분. 상태에 따라 키 해석을 바꿀 필요 없음
조합 알고리즘L,V,T 상태 머신 + 키→(L,V,T)상태에 따라 초성/종성 구분L,V,T 상태 머신 + 키→(L,V,T)벌(키 위치) 로 초성/중성/종성 구분
완성형 공식동일: S = 0xAC00 + (L×588) + (V×28) + T동일

즉, 완성형 계산L,V,T 상태 전이(초성→중성→종성 순서)는 2벌식과 같고, 키 입력을 (L,V,T)로 바꾸는 방식만 다르다. 3벌식에서는 **키가 이미 “초성 키” “중성 키” “종성 키”**로 구분되어 들어오므로, keyToChoseong(key) / keyToJungseong(key) / keyToJongseong(key)키 위치(벌) 에 따라 호출하면 된다.


3. 공병우 세벌식 (개요)

가장 널리 알려진 공병우 세벌식은 수동 타자기에서 활자 엉킴을 피하기 위해 설계된 배열이다.

  • 초성: 오른쪽 자리
  • 중성(모음): 왼쪽 가운데
  • 종성(받침): 맨 왼쪽

타자기에서는 초성·중성·종성서로 다른 벌의 글쇠로 눌러 한 음절을 만든다. 컴퓨터 3벌식 IME도 키보드 배열만 3벌로 나누고, 키 → L / V / T 매핑 테이블을 벌별로 두면 된다.


4. 3-2015 자판 (개요)

3-2015 자판은 E/R/D/F/C/V 위치의 글쇠가 자동으로 중성인지 종성인지 판단하도록 설계된 최신 세벌식 배열이다. Shift 없이도 입력할 수 있도록, 키 위치만으로 벌이 결정된다. 구체적인 키→L/V/T 매핑은 세벌.org 3-2015 등 공개 자료를 참고한다.


5. 상태 전이 (2벌식과 동일)

3벌식도 한 음절초성 → 중성 → (종성) 순서로만 쌓인다. 따라서 상태 전이는 2벌식과 동일하다.

  • 초성만 → 중성 키 입력 시 (L,V) 로 전이.
  • 초성+중성 → 종성 키 입력 시 (L,V,T) 로 전이(받침 가능할 때). 모음 키 입력 시 commit + 새 (L,V)(겹모음이 아니면).
  • 초성+중성+종성 → 모음 키 입력 시 commit + 종성→초성 변환으로 새 L, 새 V. 자음 키 입력 시 commit + 새 초성 또는 겹받침(3벌식에서도 겹받침은 규칙이 있음).

차이점: 3벌식에서는 자음 키가 “초성 키”인지 “종성 키”인지 키 위치로 구분되므로, 현재 상태가 “초성+중성”인데 자음 키가 눌렸다고 해서 “이걸 종성으로 쓸까? 아니면 commit하고 초성으로 쓸까?”를 키가 종성 벌인지 초성 벌인지로만 판단하면 된다. 2벌식처럼 “같은 키를 종성으로 해석할지 초성으로 해석할지” 상태로 나누지 않아도 된다.


6. 겹모음·겹받침 (3벌식)

  • 겹모음: 2벌식과 동일하게 중성 벌에서 두 키 시퀀스로 겹모음(ㅘ, ㅙ, …)을 입력한다. (V 인덱스 조합 규칙은 한글 조합 규칙과 동일.)
  • 겹받침: 종성 벌에서 두 키 시퀀스로 겹받침(ㄳ, ㄵ, …)을 입력한다. 3벌식에서는 종성 키가 분리되어 있으므로, “첫 종성 키 + 두 번째 종성 키” → 겹받침 T 로 매핑하면 된다.

7. 3벌식 구현 (JavaScript)

7.1 키 매핑 (공병우 세벌식 예시)

// 초성 벌 (오른손)
const KEY_TO_CHOSEONG_3SET = {
  'y': 0,  // ㄱ
  'u': 2,  // ㄴ
  'i': 3,  // ㄷ
  'o': 5,  // ㄹ
  'p': 6,  // ㅁ
  'h': 7,  // ㅂ
  'j': 9,  // ㅅ
  'k': 11, // ㅇ
  'l': 12, // ㅈ
  ';': 14, // ㅊ
  // ...
};

// 중성 벌 (가운데)
const KEY_TO_JUNGSEONG_3SET = {
  'f': 0,  // ㅏ
  'r': 4,  // ㅓ
  'd': 8,  // ㅗ
  's': 13, // ㅜ
  'e': 18, // ㅡ
  'w': 20, // ㅣ
  // ...
};

// 종성 벌 (왼손)
const KEY_TO_JONGSEONG_3SET = {
  'q': 1,  // ㄱ (종성)
  'a': 4,  // ㄴ (종성)
  'z': 7,  // ㄷ (종성)
  '1': 8,  // ㄹ (종성)
  '2': 16, // ㅁ (종성)
  '3': 17, // ㅂ (종성)
  // ...
};

7.2 process 함수 차이

// 2벌식: 상태에 따라 같은 키를 다르게 해석
function process2Set(key) {
  if (key in KEY_TO_CONSONANT) {
    const choseong = KEY_TO_CONSONANT[key];
    
    if (this.state === 'LV') {
      // 같은 키지만 종성으로 해석
      const jongseong = CHOSEONG_TO_JONGSEONG[choseong];
      if (jongseong) this.T = jongseong;
    } else {
      // 초성으로 해석
      this.L = choseong;
    }
  }
}

// 3벌식: 키 위치(벌)가 이미 역할을 결정
function process3Set(key) {
  if (key in KEY_TO_CHOSEONG_3SET) {
    // 초성 벌 키는 항상 초성
    this.L = KEY_TO_CHOSEONG_3SET[key];
  }
  else if (key in KEY_TO_JUNGSEONG_3SET) {
    // 중성 벌 키는 항상 중성
    this.V = KEY_TO_JUNGSEONG_3SET[key];
  }
  else if (key in KEY_TO_JONGSEONG_3SET) {
    // 종성 벌 키는 항상 종성
    this.T = KEY_TO_JONGSEONG_3SET[key];
  }
}

7.3 입력 순서 유연성

3벌식에서는 순서가 틀려도 키가 벌로 구분되어 있어 복구 가능:

sequenceDiagram
    participant U as 사용자
    participant IME as 3벌식 IME

    U->>IME: 중성 키 ㅏ
    Note over IME: V=0 설정
    
    U->>IME: 초성 키 ㄱ
    Note over IME: L=0 설정, LV 상태
    
    U->>IME: 종성 키 ㄱ
    Note over IME: T=1 설정, LVT 상태
    
    Note over IME: preedit 각

결과: 순서와 무관하게 “각” 조합 완성


8. libhangul 사용

libhangul은 2벌·3벌 모두 지원한다.

// 2벌식
HangulInputContext* hic2 = hangul_ic_new("2");

// 3벌식 (공병우 390)
HangulInputContext* hic3 = hangul_ic_new("3f");

// 3벌식 (3-2015)
HangulInputContext* hic3_2015 = hangul_ic_new("3-2015");

키보드 정의 파일에서 벌별 키→자모 매핑이 다르게 로드된다. libhangul API 참고.


9. 요약

  • 3벌식: 초성·중성·종성이 **서로 다른 키(벌)**에 배치. 키 위치로 벌 구분 → 상태 없이 key→L/V/T 매핑 가능.
  • 조합 순서·완성형 공식·겹모음·겹받침·종성→초성 규칙은 2벌식과 동일. 키→(L,V,T) 변환 방식만 벌별 테이블로 다름.
  • 2벌식: 2벌식 알고리즘. 3벌식: 본 문서와 한글 조합 원리, 한글 조합 규칙.