결론. 실물 Bluetooth 키보드도 PC의 IME 모드를 모릅니다. 한/영 키를 보낼 뿐 모드가 실제로 바뀌었는지는 끝까지 알지 못합니다. 그래도 문제가 되지 않는 이유는 키캡에 영문과 한글 각인이 동시에 새겨져 있어서, 각인이 어느 모드인지를 주장하지 않기 때문입니다. 폰 화면에는 키당 각인 한 벌만 들어가므로 앱은 하나를 골라야 하고, 하나를 고르는 순간 각인은 지도에서 주장으로 바뀝니다. 그리고 그 주장은 앱이 확인할 방법이 없는 추정에 기대고 있습니다.
이 글은 입력이 아니라 각인에 대한 것입니다. 입력창에서 보내는 문장은 전환까지 포함한 계획으로 컴파일되어 나가며, 그 경로는 Bluetooth HID와 한글 입력 노트가 다룹니다. 여기서 다루는 것은 화면 키보드입니다. 화면 키보드는 사용자가 키를 누르기 전에 키캡마다 무엇을 그릴지 정해야 합니다.
키캡에 각인 두 벌이 있으면 아무것도 주장하지 않는다
한글 실물 키보드의 인쇄를 보면 Q 키에 Q와 ㅂ이 함께 있고 shift 각인까지 같이 있습니다. 이 각인은 지도입니다. 이 키는 이 중 하나다라고만 말합니다. PC가 어느 모드에 있든 이 문장은 참이며, 애초에 모드를 주장한 적이 없기 때문입니다.
그래서 실물 키보드에서는 모드 어긋남이 경험으로 남지 않습니다. 사용자는 치다가 한글이 나와야 할 자리에 영문이 나오면 한/영 키를 누르고 다시 칩니다. 키보드에는 틀린 것이 없었으므로 고칠 것도 없습니다. 애초에 신뢰의 대상은 키보드가 아니라 화면이었습니다.
맹점 자체는 앱만의 것이 아닙니다. 실물 키보드도 이 앱도 host의 IME 모드를 읽지 못합니다. 실물 키보드는 모드를 표시하지 않으므로 알 필요가 없을 뿐입니다. 키보드가 모드를 표시하기 시작하는 순간 같은 맹점이 눈에 보이게 됩니다.
폰 화면에는 키당 각인 한 벌만 들어간다
앱의 글자 키는 네 벌의 각인 후보를 가지고 있습니다. 기본·shift·한글·한글 shift, 즉 q·Q·ㅂ·ㅃ입니다. 폰 화면에는 이것을 다 그릴 자리가 없습니다. 키캡 하나는 손가락이 덮는 터치 대상이고, 각인은 한 줄로 그려지며, 각인 크기는 키보드 전체가 공유하는 하나의 기준에서 나옵니다. 그래서 한 키에 두 벌을 밀어 넣으면 나머지 키의 각인까지 함께 작아집니다.
그래서 앱은 한 벌만 그립니다. 한글 모드에서는 한글, 영문 모드에서는 영문입니다. 정보가 없어서가 아닙니다. 앱은 네 벌을 모두 쥐고 모드나 Shift가 바뀔 때 각인 크기가 흔들리지 않도록 그 네 벌을 전부 써서 크기를 정한 다음, 그중 하나만 표시합니다. 이유는 공간뿐입니다.
그리고 한 벌만 남은 각인은 더 이상 지도가 아닙니다. 키캡에 ㅂ 하나만 있으면 그것은 이 키를 누르면 ㅂ이 나온다는 뜻입니다. 이는 host의 현재 상태에 대한 주장이고, 그 주장은 앱이 가진 추정만큼만 정확합니다.
Bluetooth HID에는 그 주장을 확인할 경로가 없다
앱은 IME 상태를 추정으로 들고 있고 키캡 각인을 그 추정에서 그립니다. 실제 상태를 되돌려 주는 것은 아무것도 없습니다. host가 키보드에 알려주는 유일한 값은 LED 출력 바이트이고, 표준 boot keyboard LED는 Num Lock·Caps Lock·Scroll Lock·Compose·Kana입니다. 한글 비트는 없습니다. 한/영은 host 입력기의 속성이지, host가 상대하고 있다고 여기는 키보드 장치의 속성이 아니기 때문입니다.
앱에는 그런 비트를 노출하는 host가 있을 경우를 위한 자리가 마련돼 있습니다. 프로필이 어느 LED 비트가 한글을 뜻하는지 선언하면, 그 보고를 받을 때 해당 세션의 추정을 확인된 것으로 표시합니다. 다만 현재 제공하는 네 프로필 중 그 비트를 선언한 것은 없습니다. 선언할 표준 비트가 없기 때문입니다. 이 자리는 앞으로의 발견을 담을 곳이지 지금 동작하는 되먹임 고리가 아닙니다.
추정이 어긋나는 경로
아래 각각이 단독으로 충분하며, 어느 것도 발생하는 그 순간에는 오류로 보이지 않습니다.
| 원인 | 일어나는 일 |
|---|---|
| 전환 키가 host에 닿지 않음 | 앱은 전환 키를 보낼 때 추정을 갱신하지, host가 그것을 처리한 것을 확인하고 갱신하지 않습니다. 전환 한 번이 유실되면 그 이후 모든 각인이 뒤집힙니다. 가정이 아니라 실측입니다. Windows에서 전환 직후 첫 한글 자음이 유실되는 것이 관측됐고(빠른이 ㅏ른으로 도착), 그래서 지금은 전환 후 400 ms를 기다린 뒤 타이핑합니다. |
| 프로필이 host와 다름 | host마다 전환 키가 다릅니다. Windows에서만도 오른쪽 Alt와 LANG1이 함께 쓰이고 다른 플랫폼은 또 다른 키를 씁니다. 앱은 선택된 프로필의 첫 번째 후보를 보내며, 그 프로필에 후보가 없으면 LANG1로 대신합니다. host가 전환으로 읽지 않는 키를 보내면 각인만 바뀌고 host는 그대로입니다. |
| 세션 경계에서 한쪽만 초기화 | 재연결·앱 프로세스 재생성·프로필 변경으로 세션이 바뀌면 확인 표시가 버려지고, 키캡은 설정된 키보드 언어의 초기 배열로 돌아갑니다. host의 IME는 있던 상태 그대로이고, 앱에는 이제 맞춰 볼 확인된 추정도 없습니다. |
| 토글에는 절대 지정이 없음 | 지금부터 한글이라고 지시할 방법이 없고, host가 현재 가진 상태를 뒤집는 키만 있습니다. 두 쪽이 한 번 어긋나면 이후의 모든 토글은 그 어긋남을 해소하는 것이 아니라 그대로 유지합니다. |
그동안 사용자는 ㅂ이라고 적힌 키를 누르면서 q를 받고 있습니다.
Caps Lock은 해결됐는데 이것은 안 되는 이유
Caps Lock도 똑같은 모양의 문제를 가지고 있었고, 앱은 그것을 없앴습니다. host로 Caps Lock을 아예 보내지 않습니다. caps를 앱 상태로만 관리하고 보내는 키에 Shift를 실어 보내므로, host의 Caps Lock 상태와 무관하게 키캡에 보이는 대로 도착합니다. 이것도 실측에 대한 대응이었습니다. 키 release가 유실되면 host가 앱보다 Caps Lock을 여러 번 토글하게 되고, 그 결과 첫 글자만 대문자로 나오는 문장이 나왔습니다.
같은 수법을 한글에는 쓸 수 없습니다. 대소문자는 키 입력 자체의 속성이라 앱이 소유할 수 있습니다. 한글 조합은 그렇지 않습니다. 자모를 음절로 합치는 주체는 host의 입력기이고, 앱이 ㅂ을 만들 수 있는 유일한 방법은 한글 IME가 ㅂ으로 읽는 물리 키를 보내는 것뿐입니다. 우회로가 없습니다. 그 키가 ㅂ이 될지 q가 될지는 host에서, 앱이 소유할 수도 읽을 수도 없는 상태가 결정합니다.
그래서 앱은 대신 복구를 싸게 만든다
어긋남을 막을 수 없으므로, 설계 목표는 그것을 수수께끼가 아니라 2초짜리 정정으로 만드는 쪽으로 옮겨갑니다.
- 한/영 키를 길게 누르면 표시만 정렬합니다. 각인을 뒤집고, 아무것도 보내지 않으며, 정정된 상태를 그 세션의 확인된 값으로 표시합니다. 각인이 반대로 되어 있을 때의 직접적인 해결책입니다. host는 이미 원하는 모드에 있으므로 host가 아니라 앱을 고치는 것입니다. 짧게 누르는 것은 종전대로 키를 실제로 보내는 전환입니다.
- 보정 프로브. 앱이 프로브를 쳐 보내고 host에 무엇이 나왔는지 묻습니다.
abc를 보내며, 모드 전환을 하는 프로필에서는가나다도 함께 보냅니다. 기계적으로 확인할 경로가 없으므로 사용자의 대답이 추정을 확인된 것으로 만듭니다. - 신뢰는 세션을 넘기지 않습니다. 확인된 추정은 그 host 연결 하나에만 적용되고 재연결이나 프로세스 재생성에서 버려집니다. 이미 거짓이 되어 있을 수도 있는 다음 세션으로 신뢰를 이월하지 않습니다.
- 영문 전용 키보드에는 전환 키를 두지 않습니다. 키보드 언어가 한국어가 아니면(앱 설정값이며, 시스템 기본으로 두면 폰 자체의 언어입니다) 한/영 키가 Alt로 대체되고 각인은 영문으로 고정됩니다. 전환 키가 없는 키보드에는 어긋날 것도 없습니다.
알아둘 잔여 사항 하나. 입력창에서 보낸 글이 한글로 끝나면 앱은 그 전송을 host 확인이 필요한 것으로 표시합니다. 마지막 음절이 host의 조합 버퍼에 미확정으로 남고, 앱은 확정 키를 스스로 보내지 않습니다. 그것을 확정시키는 일은 host에서, 앱이 관측하지 않는 바깥에서 일어납니다.
한계
여기 있는 어떤 것도 앱을 더 잘 만들어서 해결되지 않습니다. 고리를 닫으려면 전송 규격이 정의하지 않은 되읽기 경로가 필요합니다. LED 보고에 한글 표시 비트가 표준으로 들어가거나, host가 자신의 IME 모드를 입력 장치에 알려주어야 합니다. 그때까지 키캡 각인은 앱의 최선의 추정을 큰 글씨로 그린 것이고, 길게 눌러 정렬하는 기능이 있는 이유는 최선의 추정이 측정은 아니기 때문입니다.