3벌식 알고리즘
세 벌 분리, 2벌식과의 차이, 3-2015·공병우 세벌식 개요
3벌식은 한글 자모를 세 벌(초성 벌·중성 벌·종성 벌)로 나누어 서로 다른 글쇠에 배치하는 방식이다. 2벌식과 달리 같은 키가 초성이 될 때와 종성이 될 때 물리적으로 다른 키이므로, 상태에 따른 키 해석이 필요 없고, 키 → 자모(벌별) 매핑만 하면 된다.
0. 2벌식 vs 3벌식 키 처리 비교
Section titled “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. 2벌식과의 차이
Section titled “1. 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) 를 키 위치(벌) 에 따라 호출하면 된다.
2. 공병우 세벌식 (개요)
Section titled “2. 공병우 세벌식 (개요)”가장 널리 알려진 공병우 세벌식은 수동 타자기에서 활자 엉킴을 피하기 위해 설계된 배열이다.
- 초성: 오른쪽 자리
- 중성(모음): 왼쪽 가운데
- 종성(받침): 맨 왼쪽
타자기에서는 초성·중성·종성을 서로 다른 벌의 글쇠로 눌러 한 음절을 만든다. 컴퓨터 3벌식 IME도 키보드 배열만 3벌로 나누고, 키 → L / V / T 매핑 테이블을 벌별로 두면 된다.
3. 3-2015 자판 (개요)
Section titled “3. 3-2015 자판 (개요)”3-2015 자판은 E/R/D/F/C/V 위치의 글쇠가 자동으로 중성인지 종성인지 판단하도록 설계된 최신 세벌식 배열이다. Shift 없이도 입력할 수 있도록, 키 위치만으로 벌이 결정된다. 구체적인 키→L/V/T 매핑은 세벌.org 3-2015 등 공개 자료를 참고한다.
4. 상태 전이 (2벌식과 동일)
Section titled “4. 상태 전이 (2벌식과 동일)”3벌식도 한 음절은 초성 → 중성 → (종성) 순서로만 쌓인다. 따라서 상태 전이는 2벌식과 동일하다.
- 초성만 → 중성 키 입력 시 (L,V) 로 전이.
- 초성+중성 → 종성 키 입력 시 (L,V,T) 로 전이(받침 가능할 때). 모음 키 입력 시 commit + 새 (L,V)(겹모음이 아니면).
- 초성+중성+종성 → 모음 키 입력 시 commit + 종성→초성 변환으로 새 L, 새 V. 자음 키 입력 시 commit + 새 초성 또는 겹받침(3벌식에서도 겹받침은 규칙이 있음).
차이점: 3벌식에서는 자음 키가 “초성 키”인지 “종성 키”인지 키 위치로 구분되므로, 현재 상태가 “초성+중성”인데 자음 키가 눌렸다고 해서 “이걸 종성으로 쓸까? 아니면 commit하고 초성으로 쓸까?”를 키가 종성 벌인지 초성 벌인지로만 판단하면 된다. 2벌식처럼 “같은 키를 종성으로 해석할지 초성으로 해석할지” 상태로 나누지 않아도 된다.
5. 겹모음·겹받침 (3벌식)
Section titled “5. 겹모음·겹받침 (3벌식)”- 겹모음: 2벌식과 동일하게 중성 벌에서 두 키 시퀀스로 겹모음(ㅘ, ㅙ, …)을 입력한다. (V 인덱스 조합 규칙은 한글 조합 규칙과 동일.)
- 겹받침: 종성 벌에서 두 키 시퀀스로 겹받침(ㄳ, ㄵ, …)을 입력한다. 3벌식에서는 종성 키가 분리되어 있으므로, “첫 종성 키 + 두 번째 종성 키” → 겹받침 T 로 매핑하면 된다.
6. 3벌식 구현 (JavaScript)
Section titled “6. 3벌식 구현 (JavaScript)”6.1 키 매핑 (공병우 세벌식 예시)
Section titled “6.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, // ㅂ (종성) // ...};6.2 process 함수 차이
Section titled “6.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]; }}6.3 입력 순서 유연성
Section titled “6.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 각
결과: 순서와 무관하게 “각” 조합 완성
7. libhangul 사용
Section titled “7. 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 참고.