프로그래밍을 위한 리눅스 키매핑하기
Tags: linux, keymapping, xmodmap, keyd
Published: 2022-09-18 15:03:37

## 요약

- Xmodmap으로 X 서버 수준에서 매핑하기
- Keyd를 통해서 저수준에서 매핑하기
- 필자가 사용하는 키매핑

## 들어가기 전에

생각의 넓이는 언어 능력만큼 넓다는 말이 있다. 쉽게 말하면 아는 만큼 보인다는 것이고 다른 말로는 원하는 게 너무 많으면 괴롭다는 소리다 :)

Vim과 같은 모달 에디터를 사용하다 보면 다시는 평범한 에디터로 돌아갈 수 없다. 종국에는 텍스트 작성을 위한 더 좋은 방법이 없을까를 고민하게 된다. 여러 키매핑을 더하다보면 init.vim ( init.lua ) 파일이 덕지덕지 늘어나게 된다.

하지만 필자는 거기서 만족하지 않았다. 60퍼센트 키보드를 사랑하는 필자는 손을 움직이지 않고, 오로지 키보드의 알파벳 만으로 모든 타이핑을 해결하고 싶었다. 처음에는 Windows의 AutoHotkey와 비슷한 Autokey를 사용하려고 했다. 그러나 Autokey는 너무 고수준 이었기 때문에 원하는 퍼포먼스가 나오지 않았다. Xmodmap은 훌륭했지만, XKB keysym을 활용하지 않는 IME에서는 문제가 있었다. 그리하여 결국에는 Keyd로 정착하게 되었다. 

지금부터는 각각의 툴의 장단점 그리고 내가 사용하는 키매핑을 소개하려고 한다. 

## Xmodmap 키매핑

**장점**
- XKB의 레거시이기 때문에 모든 리눅스 시스템에 설치되어 있다. ( 최소한 X를 사용하는 리눅스에는 )
- 손쉽게 토글이 가능하다.

**단점**
- IME랑 호환되지 않는다. 쉽게 말해 한글을 쓸 때는 키매핑이 작동하질 않는다. ( 정확히는 Alphabet인 LevelTwo keysym들에 대해서 작동하지 않는다 )
- 비슷한 사례로, 많지는 않지만, XKB Keysym을 존중하지 않는 프로그램들에서는 작동하지 않는다. ( 한 때 크로미움이 그랬다 )

Xmodmap은 모든 리눅스에 깔려 있다고 봐도 된다. 새로운 시스템을 설치 했을 때 배포판에 상관없이 바로 키매핑을 할 수 있다는 점은 큰 장점이다. 아마 한글 IME가 설치되기도 전에는 단점도 큰 의미가 없을지도 모른다. 

하지만 영문과 한글을 복합적으로 사용하게 된다면 키매핑에 익숙해진 머슬 메모리가 상당히 성가셔진다. 열심히 한글을 치고 무의식적으로 사용하게 된 키매핑 때문에 잠시 멍 때리는 일이 잦아지다 보면 새로운 키매핑 툴의 필요성을 절실하게 느끼게 된다. 

### 그나저나 왜 IME는 keysym을 존중하지 않는가

다음은 나의 추측을 적은 것이다. 당연하게도 직접 그 구현 내용을 보지 않는다면 정확한 이유는 알지 못한다. 다만 그 이유를 생각해 보면 그 필요성은 분명해 보인다. 

XKB 시스템은 libinput에서 처리된 키 입력을 keysym으로 전환한다. 사실 XKB의 설정 파일을 살펴보면 어떤 keycode를 어떤 keysym으로 전환할 것인가를 정의하는 문법으로 되어있다. 이러한 Keysym이 다시 유저들이 사용하는 application에 전달되는 것이다.

대부분의 경우에는 주어진 Keysym을 그대로 사용해도 충분하다. 하지만 그래서는 안 되는 경우가 있다. 대표적으로 IME가 그럴 것이다. 예시를 들어 보자면, IME는 'ㅂ' 입력을 위해서 어떤 'q'라는 keysym과 'q' 위치에 있는 물리 키보드 인풋중에서 무엇을 확인해야 할 지를 안다. 바로 물리 키보드 인풋, 혹은 keycode를 확인해야 한다. 가장 단순하게 한글에서의 두벌식과 세벌식은 그 레이아웃이 전혀 다르다. 한글 캐릭터가 keysym에 매핑되는 것은 그다지 합리적이지 않다. ( 최소한 그런 이유가 아닐까 생각한다 )

그렇기 때문에 Xmodmap을 통해서 LevelTwo( 보통 알파벳에 해당하는 캐릭터들) keycode들은 작동하지 않는다. 하지만 LevelOne 키들의 매핑은 문제없이 작동한다. 가령 CapsLock이나 Esc 같은 것들이 그렇다. 한글 입력과는 무관하기 때문이다. 

## keyd 키매핑

[저장소](https://github.com/rvaiya/keyd)

**장점**
- 매우 저수준의 키매핑
- 매우 직관적이고 쉬운 키매핑 문법
- 어떠한 bottleneck이 없는 퍼포먼스

**단점**
- 보통은 직접 설치하거나 컴파일 해야 함

keyd, 혹은 key daemon은 매우 고성능, 저수준의 키매핑 툴이다. 매핑 문법도 너무나 간단해서 믿기지 않을 정도다. 굳이 단점을 하나 꼽자면 일반적인 저장소에는 포함되어 있지 않은 툴이라는 점이다. 하지만 리눅스를 쓴다면 직접 클론해서 컴파일 하는 정도야 어려운 일은 아니라고 생각한다.

Keyd는 keycode를 다른 keycode로 바꿔준다. 즉 애초부터 그러한 물리적 키가 눌린 것으로 처리하게 해준다. 그러므로 X 프로그램은 물론이고 다른 어플리케이션들 에서도 일관된 키매핑 행동을 보여주게 된다.

## 다른 대안들

사실 키매핑 툴이 위의 2가지만 있는 것은 아니다. 다만 Keyd는 누구나 사용할 수 있을 정도로 문법이 단순하기 때문에 강권하는 바이다. 다만 주목할 만한 대안 툴들도 있다는 점은 알린다. 

- Kmonad: Haskell 기반의 키매핑 툴, 문법이 Lisp-like 언어라서 진입장벽이 좀 있다. 
- Interception tools : 키매핑의 끝판왕. 무한한 가능성이 있는 툴로서 키보드 뿐만 아니라 모든 물리 인풋에 대해서 완벽한 매핑이 가능하다. 단점이 있다면 c++ 를 사용해서 직접 매개 프로그램을 작성해야 하는 데다가, linux.h의 event 등, 필요한 사전 지식이 필요 하다는 점.

## 드디어, 프로그래밍을 위한 키매핑

필자의 키매핑 컨피그 파일은 [여기](https://gist.github.com/Simhyeon/58b008a9a5d8e8b34d78d774db1f745b)에서 확인할 수 있다.

기본적으로 필자는 모든 특수 기호나 숫자를 손을 전혀 움직이지 않은 채로 작성할 수 있는 것을 목표로 키매핑을 만들었다. 대략적으로는 다음 그림과 같이 생겼다.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y5j0i2kpsse0zlzleyeo.png)

Alt키는 모디파이어로서 키매핑을 사용할 모드로 전환하는 버튼이다. 즉 J에 매핑된 왼쪽 방향키는 실제로 Alt+J를 누를 때 작동한다. 

### 손쉬운 네비게이션

우리의 손은 항상 jkl; 에 위치해 있다. 커서를 움직이기 위해서 방향키로 손을 움직이는 것은 매우 큰 운동이다. hjkl에 매핑 하는 것도 나쁘지는 않다. 모든 프로그램을 Vim처럼 쓸 수 있게 된다. 하지만 굳이 손의 위치를 한 칸 움직일 필요도 없다. 그래서 필자는 jikl을 방향키로 매핑했다. 마치 키보드 중간에 방향키가 박혀 있는 것처럼 커서를 이동할 수 있다. 

```
 i  |  ↑ 
jkl | ←↓→
```

커서 이동 다음으로 자주 발생하는 이벤트는 바로 텍스트 수정이다. 백스페이스와 딜리트는 너무 멀다. 백스페이스와 딜리트 키를 각각 U 와 O에 매핑하면 텍스트 수정이 산들바람 처럼 쉬워진다. 

```
uio | B↑D 
jkl | ←↓→
// B 는 Backspace
// D 는 Delete이다. 
```

방향키 이동은 쉬워졌다. 하지만 코딩을 하다보면 때때로, 아니 사실 상당히 자주 텍스트이 처음이나 끝으로 이동해야 하는 경우가 많아진다. 그리고 또 역시나 Home키와 End키는 너무나 멀다. H에 Home키를 ;에 End키를 할당하면 편리하게 그리고 또, 좀 더 기억하기 쉽게 커서 이동을 할 수 있다. 

```
 uio  |  B↑D 
hjkl; | H←↓→E
// H 는 Home이다.
// E 는 End이다. 
```

마지막으로 스크롤링을 하다보면 방향키만으로는 스킴하기에 아쉬움이 있다. 그러다보면 페이지업과 페이지다운의 필요성을 느끼게 된다. 기본 네비게이션 조합과 가까우면서 활용 빈도가 높지 않기 때문에 좀 멀지만 N과 M에 할당했다.

```
 uio  |  B↑D 
hjkl; | H←↓→E
nm    | ud
// u 는 pageUp이다.
// d 는 pageDown이다.
```

### 합리적인 특수 기호 매핑

특수 기호를 입력하기 위해서 숫자키를 사용해야 하는 일은 항상 성가시다. 어떤 키가 어디에 있었는가를 기억하는 것 부터, 그 숫자가 어디에 위치해 있는가를 기억하기 위한 머슬 메모리를 숙련하는 데에도 시간이 오래 걸린다. 필자는 그 위치를 기억하기 쉬운 장소에 할당하려 했다. 다음은 그 매핑의 간략한 이유들이다. 

- q 와 \ : 역슬래시는 일종의 Escape이기 때문에, 느슨하게나마 연결성이 있는 Quit의 q에 할당했다.
- e 와 = : 큰 고민없이 첫 글자에 맞추어 e
- w 와 - : 마이너스 키는 =키와 페어링하기 위해서 그 옆인 w
- p 와 + : 플러스의 첫 글자 p
- a 와 & : 앰퍼샌드의 첫 글자 a 
- s 와 * : 애스터리스크의 두번째 글자 s
- d 와 $ : 달러의 첫 글자 d
- f 와 % : 퍼센트이지만 P는 이미 할당됐다. 그나마 가까운 f
- z 와 ! : z와 !는 같은 행이므로
- x 와 @ : 동일 이유
- c 와 \# : 동일 이유
- , 와 _ : 특별히 연관성은 없지만 언더스코어이기 때문에 스트로크를 아래에서 한다는 것이 직관적이다

나머지 특수기호들은 보통 남은 칸들에 그 사용 빈도수에 따라서 적당히 할당했다.

### 덜 움직이는 숫자 입력

자주는 아니지만 종종 숫자를 입력할 때가 있다. 하지만 특수 기호를 외우지 못하는 만큼 숫자 입력도 하기 어렵다. 완벽한 해결책은 없지만 최소한 좀 더 쉽게 숫자를 입력하고 싶었다. 

- i 와 o 는 1 과 0으로 매핑되어 있다면, 왜냐하면 닮았기 때문이다. :)
- p[]l;',./ 는 789456123이 매핑되어 있다. 일종의 키패드 시뮬레이션이라고 보면 될 것이다. 

### 기타

필자가 자주 사용하는 키매핑 2가지가 있는데. Y에 매핑된 ESC와 B에 매핑된 F6키다. Esc는 쓸 일이 많다, 특히나 필자는 SQL을 종종 작성하므로 CapsLock을 쓸 일이 있고 다른 Vim 유저들이 사용하는 것처럼 CapsLock을 Esc키와 스왑하지 않는다. 이를 위해서 네비게이션에 가까운 Y에 Esc를 매핑해서 쓰고 있다. 

F6는 웹 브라우징을 할 때 필요하다. 필자는 기본적으로 마우스 없는 환경을 지향하는데 그러다보면 주소를 입력하는 일이 매우 거추장스러워 지기 때문에 F6를 B에 매핑하여 사용하고 있다. 

### 결론

키매핑을 하는 것은 처음에는 답답한 일일 수 있다. 지금까지의 머슬 메모리 덕분에 새롭게 매핑된 키를 찾는 것이 더 느릴 지도 모른다. 하지만 다양한 키매핑에 익숙해지다보면 다시는 순수한 키보드 레이아웃을 만지지 못하게 된다고 분명히 말할 수 있다. 꼭 필자의 키매핑을 그대로 사용할 필요는 없다. 자신만의 키매핑을 찾아가는 것도 재미있는 경험이다. 그렇기에 한 번 쯤 키매핑을 시도해 보길 바란다.