Dvorak에서 두벌식이 깨지는 이유: 리눅스 입력 스택을 패치한 기록

무엇이 바뀌었나: 영문은 Dvorak으로 치면서 한글 두벌식도 같은 손가락 기억으로 칠 수 있게, 한글 입력 스택의 두 라이브러리(libhangul, fcitx5-hangul)에 소스 패치를 만들어 사용자 영역(~/.local)에만 설치했다. 시스템 패키지는 건드리지 않아 pacman 업데이트에도 깨지지 않는다.

왜 이게 특별한가: "영문 Dvorak + 한글 두벌식" 조합은 Windows와 macOS 모두 공식 지원이 없다. 각 OS에서 서드파티 입력기로 우회해 써 왔지만 미묘한 문제가 계속 남는 조합이다. 리눅스에서는 입력 스택의 모든 계층이 오픈소스라, 우리가 한 것처럼 변환 규칙 자체를 고치는 근본 해결이 가능하다.

남은 것: 한/영 토글 키 방식이 두 갈래로 문서화돼 있어 통일이 필요하고, upstream 버전이 올라가면 패치 재빌드가 필요하다.

이 기사의 패치·스크립트·설정 원본은 공개 저장소 github.com/nacyot/libhangul-dvorak에 올려 두었다. OS별 지원 현황은 AI 리서치와 웹 검색으로 교차 확인했다. 대상 환경은 Omarchy(Arch Linux + Hyprland + Wayland)이며, DBus 함정과 부팅 알림 문제는 서로 다른 리눅스 머신에서 각각 확인했다.

1. 왜 이 문제가 특별한가: OS별 지원 현황

"영문은 Dvorak, 한글은 두벌식"이라는 조합은 마이너해 보이지만, 이 조합을 쓰는 사람에게는 매일 부딪히는 문제다. 그런데 어느 운영체제도 이걸 정식으로 지원하지 않는다.

OS영문 Dvorak한글 두벌식두벌식 + Dvorak 공식 지원현실적인 우회
Windows지원지원없음날개셋 입력기 + 레이아웃 DLL 교체
macOS지원지원 (2-Set/3-Set, QWERTY 위치 기준)없음구름 입력기의 Dvorak 결합 설정
Linux지원 (XKB)지원 (libhangul)없음 (기본 매핑이 QWERTY 가정)오픈소스 스택을 직접 수정 (본 작업)

Windows. Microsoft 한글 IME에는 두벌식/세벌식 같은 한글 자판 옵션만 있고, 한글 모드의 로마자 배열을 Dvorak으로 바꾸는 옵션은 없다. Windows의 IME는 대개 남의 키보드 레이아웃 DLL을 "위임"받아 키를 해석하는 구조라, 커뮤니티에는 레지스트리의 Layout File 값을 kbddv.dll(Dvorak 레이아웃 DLL)로 바꾸는 우회가 오래전부터 알려져 있다. 중국어 Pinyin IME와 일본어 IME에 같은 기법을 쓰는 사례가 Microsoft Q&A와 Super User에 문서화돼 있다(Super User 사례, Microsoft Q&A 사례). 사용자 본인도 세벌식 입력기인 날개셋의 고급 설정으로 DLL을 Dvorak으로 바꿔 쓰고 있지만, 미묘한 문제가 남아 있다고 보고했다. 이 방식은 시스템 전체 레이아웃을 바꾸는 거라 로그인 화면처럼 설정이 미치지 않는 영역이 생기고, Windows 한글 IME가 영문 입력까지 자체 처리하는 구조라 다른 영문 배열과의 결합이 원래 허술하다는 사용자 보고도 있다(Colemak 포럼).

macOS. 내장 한글 입력 소스(2-Set Korean, 3-Set Korean)는 QWERTY 키 위치를 기준으로 하고, Dvorak과 결합하는 옵션은 없다(Apple 한글 입력 가이드). 그래서 서드파티인 구름 입력기를 쓴다. 구름은 흥미롭게도 리눅스의 그 libhangul 기반으로 만들어졌고, "드보락이나 콜맥을 포함해 어떤 시스템 자판과도 결합해 사용할 수 있다"고 명시한다(구름 입력기 GitHub). 사용자 본인도 이 Dvorak 결합 설정으로 쓰고 있지만 역시 미묘한 문제가 남는다고 보고했다. macOS의 서드파티 입력기는 InputMethodKit이라는 프레임워크 위에서 돌아가는데, 이 계층의 제약 때문에 앱별로 조합 문자열 처리나 한영 전환이 다르게 동작하는 사례가 계속 보고된다. 로그인 화면과 데스크톱의 자판 배열이 따로 노는 macOS의 오랜 버그도 있다(관련 이슈).

정리하면: 두 상용 OS 모두 이 조합을 "설정 한 번에 영구적으로" 해결할 방법이 없다. 서드파티 우회는 존재하지만 OS가 업데이트되거나 앱을 바꾸면 미묘하게 새는 문제와 함께 살아야 한다. 그리고 macOS의 최선책이 리눅스의 오픈소스 라이브러리(libhangul)를 포팅한 입력기라는 사실이 이 문제의 본질을 보여준다. 정공법은 그 라이브러리를 직접 고치는 것이고, 그게 가능한 OS가 리눅스다.

리눅스에서도 기본값은 똑같이 깨진다. 차이는 고칠 수 있느냐다. 2007년 Arch Linux 포럼에 올라온 같은 문제의 보고가 증거다. Dvorak으로 바꾼 사용자가 "안녕하세요"를 치려 하면 ㄷ새해댜쇼딜이 찍힌다는 내용인데, 해결책도 우리와 같은 방향(IME 테이블 편집)이었다(Arch Linux 포럼).

2. 두벌식 + Dvorak 사용자의 고충

두벌식은 "자모를 어느 손가락으로 치는가"의 체계다. ㅇ는 오른쪽 검지, ㅏ는 오른쪽 중지, ㄴ은 왼쪽 검지. 이 체계는 전부 QWERTY 자판의 물리적 키 위치를 기준으로 만들어졌다. 리눅스 한글 조합 라이브러리 libhangul의 두벌식 테이블도 그 가정을 그대로 따른다. ASCII 키 심볼을 한글 자모로 바꾸는 단순 조회표인데, 'd'(0x64)를 ㅇ으로 매핑한다. QWERTY에서 d가 ㅇ 자리이기 때문이다.

위: 두벌식의 기본 가정 — QWERTY 위치에 붙은 자모 | 아래: 같은 물리 키의 Dvorak 라벨
키에 마우스를 올려 보세요. 같은 물리 위치가 두 자판에서 어떻게 달라지는지 보여준다.
그림 1. 두벌식 자모는 물리 위치에 붙어 있고, Dvorak은 그 위치의 문자를 바꾼다. 이 충돌이 모든 문제의 출발점이다.

Dvorak 사용자에게 이 가정은 세 가지 고통으로 돌아온다.

고충 1. 한글 자모가 뒤섞인다. Dvorak 사용자의 손가락은 이미 재배치돼 있다. "안녕"을 치고 싶으면 두벌식 기준으로 QWERTY 위치 d k s s u d를 눌러야 하는데, Dvorak 라벨로는 같은 물리 위치가 e t o o g e다. 키보드 이벤트를 받는 쪽은 이 키들을 Dvorak 심볼 etooge로 전달하고, libhangul은 그 심볼을 QWERTY 위치로 착각해서 해석한다. 결과는 엉뚱한 자모다. 작업 노트에 기록된 실측으로, "안녕"을 치려 하면 ㄷ새핻이 나왔다. 위 Arch 포럼의 실측(안녕하세요ㄷ새해댜쇼딜)도 같은 현상이다. 한글을 치려면 두 자판 체계를 머릿속에서 실시간으로 환산해야 하니, 손가락 기억으로 타이핑하는 사람에게는 사실상 한글 입력 불가다.

치고 싶었던 것
실제로 찍힌 자모 (패치 전)
그림 2. 단어를 골라 재생하거나, 입력창에 직접 쳐 보거나, 키보드를 직접 눌러 보자. 손가락이 의도한 자모와 실제로 찍히는 자모가 왜 어긋나는지 키 단위로 따라갈 수 있다.

고충 2. 한글 모드에서 단축키가 죽거나 이동한다. 처음에는 "한글 모드일 때만 시스템 자판을 QWERTY로 바꾸는" 스크립트를 시도했다. 한글은 나오게 됐지만, 그 순간 단축키도 QWERTY 위치로 바뀐다. Dvorak 사용자는 Ctrl+C를 QWERTY의 I 자리에서, Ctrl+V를 . 자리에서 누른다. 한글로 글을 쓰다가 복사·붙여넣기를 할 때마다 손가락이 헛나간다. 자판 전체를 토글하는 우회는 한 문제를 고치고 다른 문제를 만든다.

그림 3. "한글 모드에서만 XKB를 QWERTY로 토글"하는 우회의 대가. 실선 테두리가 손가락 기억 속 자리, 색 채움이 그 모드에서 실제로 눌러야 할 자리다.

고충 3. 마침표와 쉼표가 알파벳으로 바뀐다. Dvorak은 문장부호 위치가 QWERTY와 크게 다르다. 마침표는 하단열 V 자리, 쉼표는 그 옆 W 자리에 있다. 한글로 문장을 쓰다가 모드 전환 없이 마침표를 찍고 싶은데, 두벌식 자판표에 Dvorak 하단열 키는 매핑이 없어서 그대로 v, w 같은 알파벳이 찍힌다. 문장 하나 끝날 때마다 한/영을 전환하거나, 틀린 글자를 지우고 다시 쳐야 한다.

그림 4. Patch A로 자모는 고쳤지만 문장부호는 샜다. 빨간 테두리 키(물리 . , ; ' - 위치)가 누수 지점이다. 날짜의 하이픈도 Patch B 없이는 [로 샌다. 완전 무패치 상태라면 이 키들도 ㅍ·ㅈ 같은 엉뚱한 자모로 찍혔다.

3. 리눅스 입력 스택 이해하기

이 작업을 이해하는 데 필요한 배경은 입력 스택의 계층 구조 하나다. 리눅스(정확히는 Wayland 환경)에서 키 하나가 글자가 되기까지의 경로:

물리 키 입력
  → XKB: 물리 키를 키 심볼로 번역 (여기서 Dvorak 적용)
  → fcitx5: 입력기 프레임워크 (한/영 모드 관리, 키 가로채기)
  → libhangul: 키 심볼을 자모로 매핑하고 글자로 조합
  → 애플리케이션

Windows와 macOS에서는 이 계층이 운영체제 안에 닫혀 있고 IME와 레이아웃이 강하게 묶여 있다. 리눅스에서는 각 계층이 별도 오픈소스 프로젝트라, 소스를 고쳐 다시 빌드하는 것이 기술적으로는 평범한 작업이다. 이 차이가 1장의 OS별 현황표에서 리눅스만 "근본 해결 가능"인 이유다.

4. 고쳐가는 과정: 시행착오 타임라인

한 번에 정답에 도달한 게 아니다. 우회 시도 세 번이 실패하고, 패치를 넣고도 실사용에서 부작용이 하나씩 발견돼 차례로 덧고쳤다. 노트에 날짜가 남은 것만 확정 날짜로 표기했다. 두 대의 리눅스 머신에서 병렬로 진행된 작업이라, 날짜 없는 단계의 정확한 순서는 상대적이다.

시기한 일결과와 부작용
패치 이전우회 1: fcitx5의 입력기별 Layout= 설정실패. Wayland에서는 키 배열이 compositor 소유라 입력기가 IM 단위로 덮어쓸 수 없음
패치 이전우회 2: 한글 모드에서만 XKB를 QWERTY로 토글하는 스크립트한글은 나옴. 부작용: 단축키까지 QWERTY 위치로 이동(고충 2) → 폐기
2026-06-28 (보조 머신)우회 3: fcitx5 "Allow Overriding System XKB Settings" 옵션실패. 옵션 설명에 "(Only support KDE5+ and GNOME)". Hyprland에서는 묵묵히 아무것도 안 함
2026-06-28 (보조 머신)한/영 토글 키 정리fcitx5 기본값에 왼쪽 Shift 토글이 숨어 있던 것을 발견해 제거, Alt+Space로 지정
6월 말Patch A: libhangul에 Dvorak 기반 두벌식 테이블 추가자모는 손가락대로 나옴. 부작용 발견: 마침표·쉼표 위치 키가 알파벳(v, w 등)으로 출력. 두벌식 테이블에 없는 키는 그대로 통과하기 때문
6월 말Patch B: fcitx5-hangul에 문장부호 passthrough(v/w/s/z. , ; /) 추가문장부호 대부분 해결. 남은 부작용: 홈 행의 ' 자리에 -가 찍힘. 최초 패치는 알파벳이 새던 하단열 키만 잡았고, 이 키는 문장부호(-)가 새는 별도 케이스였음
2026-06-30Patch B 보강: -/_'/" 두 줄 추가해결. QWERTY의 apostrophe 물리 키가 Dvorak에서는 -(shift는 _)를 내는 게 원인이었음
2026-07-01 이전Patch B 확장: 숫자열·브래킷 자리 8키 매핑([-, ]=, /[, =]와 shift형)한글 모드에서 하이픈·등호·브래킷 입력 가능. 문서화가 누락돼 있던 것을 2026-07-28에 실물 패치와 대조하며 확인
2026-06-28 (보조 머신)패치 후에도 한글이 간헐적으로 QWERTY 기준으로 깨지는 문제 추적원인: DBus 자동 활성화가 환경변수 없이 fcitx5를 직접 띄워 시스템(무패치) 라이브러리를 로드. 사용자 DBus 서비스 오버라이드로 해결
2026-07-01 (Asahi 머신)부팅마다 fcitx5 "Wayland Diagnose" 알림원인: GTK_IM_MODULE과 Wayland 입력기 프런트엔드 공존. 메인 머신은 GTK_IM_MODULE 제거, Asahi 머신은 알림만 숨김. 부수 발견: fcitx5 설정 파일의 리스트 직렬화 함정

실패한 우회 세 개에는 공통 원인이 있다. Wayland(Hyprland)에서는 키 해석을 입력기 차원에서 바꿀 수단이 없다는 것. 설정으로 우회할 길이 없으니, 키를 자모로 변환하는 라이브러리 자체를 Dvorak 인지로 고치는 수밖에 없었다.

Patch A: libhangul에 Dvorak 기반 두벌식 테이블

핵심 아이디어는 단순하다. XKB는 항상 Dvorak을 유지하고, Dvorak 키 심볼을 받았을 때 "이 키의 물리적 위치가 QWERTY라면 무슨 키인가"를 기준으로 자모를 매핑한다.

Dvorak 사용자가 누르는 키 → 그 키의 심볼 (Dvorak)
                          → 같은 물리 위치의 QWERTY 심볼
                          → 그 QWERTY 심볼의 두벌식 자모

libhangul 0.2.0에 새 테이블 hangul_keyboard_table_2_dvorak[128]을 추가했다. 여기서 결정 하나: 새 keyboard를 별도 등록하지 않고, 기존 hangul_keyboard_2(ID "2", 이름 "Dubeolsik")의 테이블 포인터를 새 테이블로 교체했다. fcitx5-hangul이 keyboard ID를 하드코딩으로 고르기 때문에, 별도 등록하면 fcitx5-hangul 설정 UI에서 선택할 방법이 없기 때문이다. 원본 QWERTY 테이블은 ID "2q"("Dubeolsik (QWERTY)")로 보존했다.

Patch B: fcitx5-hangul에 문장부호 passthrough

Patch A만으로는 고충 3이 남는다. Dvorak 라벨 v(QWERTY . 위치)는 두벌식 테이블에 매핑이 없어(0) v가 그대로 출력되는데, 사용자는 여기를 마침표 위치로 인지한다. libhangul 테이블은 자모 매핑만 표현할 수 있고 "다른 문자로 넘겨라"를 표현할 수 없어서, 이건 fcitx5-hangul 애드온에서 가로채야 한다. engine.cpp::keyEvent()에서 modifier 검사 이후, hangul_ic_process 호출 직전에 작은 변환표를 삽입했다. 현재 조합 중인 글자를 commit한 뒤 QWERTY 등가 문자를 직접 commit하고 원래 키는 소비한다. modifier 검사 이후에 두었기 때문에 Ctrl+V(붙여넣기) 같은 조합은 영향받지 않는다.

타임라인에서 보듯 이 passthrough 표는 여러 번에 걸쳐 완성됐다. 최초에는 하단열 알파벳(v/w/s/z)만 잡았고, 홈 행에서 문장부호가 새는 케이스(-/_'/" 자리)는 실사용 중 발견해 6월 30일에 추가했다. 이후 숫자열 끝과 브래킷 자리까지 확장됐다. Dvorak은 물리 QWERTY - = [ ] 키를 [ ] / =로 리라벨하므로, 그대로 두면 한글 모드에서 -=를 칠 방법이 아예 사라진다. 그래서 이 키들도 물리 QWERTY 등가로 변환한다([-, ]=, /[, =], shift형 포함). 결과적으로 문장부호는 표준 두벌식과 같은 물리 자리에서 전부 입력된다. 이런 류의 버그는 매핑표를 보고 찾는 게 아니라 쓰다가 걸려야 보이고, 이 마지막 확장은 문서화가 누락돼 있다가 2026-07-28에 실물 패치와 문서를 대조하는 과정에서 확인됐다.

5. 키보드로 보는 매핑

아래 그림은 패치 후 한글 모드에서 각 키가 무엇을 출력하는지를 보여준다. 기본은 한글 모드 출력을 크게 표시하고("Dvorak 라벨 크게"로 바꾸면 키 라벨 중심으로 볼 수 있다), 좌상단 작은 글자는 그 키의 물리적 위치(QWERTY)다. 초록 테두리 키가 패치로 출력이 바뀐 키다. `\처럼 아무 표시도 없는 키는 자기 문자가 그대로 입력된다.

그림 5. 패치 전/후를 바꿔 보자. 같은 키보드, 같은 키인데 한글 모드 출력이 어떻게 달라지는지가 이 작업의 전부다.
``11223344556677889900-[→ -=]→ =deletetabq'w,e.rptyyfugicorpl[/→ []=→ ]\\capsaasodefugihdjhktln;s→ ;'-→ 'returnshiftz;xqcjvkbxnbmm,w→ ,.v→ ./z→ /shiftfncontroloptioncommandcommandoption

그림 5의 정적 버전(스크립트 없이 볼 때 표시). 한글 모드에서의 키별 출력. 예: Dvorak e 키(물리 위치 QWERTY d)를 누류면 ㅇ이 입력된다.

shift 조합으로 쌍자음·복합 모음이 나오는 키도 물리 위치 기준으로 맞췄다. Dvorak에서 P(shift+p, QWERTY R 위치)은 ㄲ, Y(QWERTY T 위치)는 ㅆ, "(QWERTY Q 위치)는 ㅃ, <(QWERTY W 위치)는 ㅉ, >(QWERTY E 위치)는 ㄸ, L(QWERTY P 위치)은 ㅖ, R(QWERTY O 위치)은 ㅒ다.

워킹 예시: "안녕하세요"는 Dvorak 라벨(손가락 기억) 그대로 e t o o g e i t y l e f로 입력된다. 물리적으로는 QWERTY 사용자의 dkssudgktpdy와 완전히 같은 키열이다.

한글자모Dvorak 라벨로 누르는 키같은 물리 위치의 QWERTY
ㅇ+ㅏ+ㄴe t od k s
ㄴ+ㅕ+ㅇo g es u d
ㅎ+ㅏi tg k
ㅅ+ㅔy lt p
ㅇ+ㅛe fd y

6. 설치 구조와 운영 중 발견한 함정

네 번째 요구사항은 "시스템 패키지를 건드리지 않고 사용자 영역만으로 해결"이다. /usr/lib을 덮어쓰면 다음 pacman 업데이트 때 패치가 증발하기 때문이다. 그래서 두 패치 모두 ~/.local/ 아래로 설치하고, fcitx5가 패치된 라이브러리를 찾도록 환경변수 세 개를 설정한다. 이 변수들은 fcitx5의 기본 검색 경로를 대체하므로, 시스템 경로도 함께 나열해야 다른 애드온(wayland, xcb, classicui 등)이 정상 로드된다.

LD_LIBRARY_PATH=~/.local/lib:/usr/lib
FCITX_ADDON_DIRS=~/.local/lib/fcitx5:/usr/lib/fcitx5
FCITX_DATA_DIRS=~/.local/share:/usr/share

가장 오래 헤맨 함정: DBus 자동 활성화. 환경변수를 올바른 곳(environment.d, Hyprland autostart, 현재 세션)에 다 넣어도 한글이 간헐적으로 QWERTY 기준으로 깨졌다(보조 리눅스 머신, 2026-06-28 확인). 원인은 배포판의 DBus 서비스 파일이 Exec=/usr/bin/fcitx5(레거시 방식)라서, 앱이 입력기를 요청할 때 dbus-daemon이 세션 환경을 거치지 않고 fcitx5를 직접 띄운다는 것이었다. 이 경로로 뜬 데몬은 시스템 libhangul을 로드한다. 해결은 사용자 디렉터리(~/.local/share/dbus-1/services/, 시스템보다 우선)에 같은 이름의 서비스 파일을 두고 Exec에 환경변수를 절대경로로 박는 것이다. 검증은 pkill -9 fcitx5 후 환경변수 주입 없이 fcitx5-remote로 재활성화를 유도하고, /proc/$(pgrep -x fcitx5)/maps~/.local 경로의 libhangul이 잡히는지 본다.

후속 문제: "Wayland Diagnose" 부팅 알림(Asahi 머신, 2026-07-01). 로그인 때마다 "GTK_IM_MODULE을 빼라"는 fcitx5 자가진단 알림이 떴다. environment.d/fcitx.confGTK_IM_MODULE=fcitx와 fcitx5의 Wayland 프런트엔드가 공존한 게 원인이다. 메인 머신에서는 권고대로 GTK_IM_MODULE을 제거했다. GTK 앱은 Wayland text-input-v3로 같은 fcitx5 엔진을 쓰므로 동작이 동일하다. Asahi 머신에서는 셋업을 건드리는 리스크를 피해 알림만 notifications.confHiddenNotifications에 등록해 숨겼다. 이 과정에서 fcitx5 설정 파일의 함정도 확인했다. 리스트 값은 [섹션] 아래 0=/1= 번호 키 형식으로 써야 하는데, 잘못된 형식으로 쓰면 fcitx5가 빈 리스트로 파싱하고 리로드 때 파일을 덮어써서 편집 내용이 통째로 날아간다.

7. 패치 저장소와 적용 방법

패치 두 개와 설치·재빌드 스크립트, 설정 파일 묶음은 공개 저장소 github.com/nacyot/libhangul-dvorak에 올려 두었다. 대상 버전은 libhangul 0.2.0과 fcitx5-hangul 5.1.9(Arch Linux 기준)이고, 구조는 이렇다.

libhangul-dvorak/
├── patches/
│   ├── libhangul-dvorak-dubeolsik.patch    # Patch A: Dvorak 위치 두벌식 테이블
│   └── fcitx5-hangul-dvorak-punct.patch    # Patch B: 문장부호 passthrough
├── scripts/
│   ├── install.sh                          # 새 머신 부트스트랩 (idempotent)
│   ├── rebuild-libhangul-dvorak.sh         # upstream 소스에 패치 적용 후 사용자 영역에 빌드
│   ├── rebuild-fcitx5-hangul-dvorak.sh     # 〃
│   └── toggle-korean-input                 # 한↔영 토글 (XKB 변경 없이 입력기만 전환)
├── configs/                                # environment.d, fcitx5, Hyprland, DBus 서비스 설정
└── docs/                                   # Dvorak→자모 전체 매핑 표

적용 순서(Arch + Hyprland 기준, 자세한 설명은 저장소 README):

  1. 저장소를 clone하고 scripts/install.sh를 실행한다. 의존성 설치, upstream 소스 clone, 패치 적용, ~/.local 아래로의 빌드·설치까지 전부 수행한다. 스크립트 상단의 TAG= 변수로 대상 버전을 바꿀 수 있어, 새 upstream 버전에서는 이 값만 조정하면 된다.
  2. configs/ 안의 파일을 각자의 자리(~/.config/environment.d/, ~/.config/fcitx5/, ~/.config/hypr/)에 배치한다. 환경변수 세 개(LD_LIBRARY_PATH, FCITX_ADDON_DIRS, FCITX_DATA_DIRS)가 핵심이며, 6장에서 설명한 대로 시스템 경로를 함께 나열해야 한다. 6장의 DBus 함정을 막는 서비스 파일도 들어 있는데, 안의 __HOME__을 실제 홈 디렉터리 절대경로로 바꿔 ~/.local/share/dbus-1/services/에 두어야 한다.
  3. 재로그인. 이후 pacmanlibhangul·fcitx5-hangul을 업데이트하더라도 사용자 영역 설치분이 우선하므로 패치는 유지된다.

upstream 버전이 올라갔을 때의 재빌드는 rebuild-*.sh 두 개를 다시 실행하고 pkill -9 fcitx5로 입력기를 재시작하는 것으로 끝난다. install.sh는 idempotent하므로 재실행하더라도 안전하다.

8. 결과와 검증

고충 1~3 모두 해소됐다. 한글 자모는 손가락 기억대로 나오고, XKB를 건드리지 않으므로 한글 모드에서도 Ctrl 조합 단축키는 Dvorak 위치 그대로 동작하며(modifier 검사가 먼저라 키가 앱으로 그대로 전달된다), 마침표·쉼표·세미콜론·슬래시·따옴표는 모드 전환 없이 인지한 위치에서 찍힌다.

재발 시 첫 진단은 정해져 있다. 한글이 다시 QWERTY 기준으로 들어오면 거의 확실히 DBus가 패치 환경변수 없이 fcitx5를 띄운 것이다. grep libhangul /proc/$(pgrep fcitx5)/maps에서 /usr/lib/libhangul.so가 보이면 시스템 라이브러리를 잡은 것이고, DBus 서비스 오버라이드를 확인하면 된다.

9. 남은 것