여기서는 Vim에 대해 이야기해 보자.

Vim 익히기

Vim을 본격적으로 사용하기 시작한 것은 가상 머신에서 코드를 작성해야만 했던 회사였다. 내 로컬의 IDE와 가상 머신 내의 코드를 연동해야 하는데 이게 상당히 불편하고 귀찮아서 이리저리 알아보다가, 에이 이렇게 설정이 어려우면 그냥 Vim을 익혀보자는 생각에 사용하기 시작했다.

아직도 기억에 남는 일이 있는데, Vim의 이동키 hjkl에 너무 익숙해지기 힘들다고 사수에게 하소연한 적이 있다. 사수가 듣더니 아무렇지도 않은 표정으로 이렇게 이야기하는 것이었다.

그럼 그냥 화살표키로 이동하면 되죠.

굳이 외워지지 않는 단축키를 억지로 쓸 필요가 있냐는 말이었는데 참 기억에 남는 말이다. 사실 Vim을 익히기 어려운 이유 중 가장 큰 것으로, 단축키를 꼭 써야만 한다는 생각이 머리속을 지배해서 그런 것 같다. 그냥 안써도 되고, 익숙한 대로 아는 것부터 조금씩 써 나가면 되는 것이 아닌가 싶다. 필요성이 느껴진다면 그때 검색해서 익혀도 되고. 사실 필요성이 느껴지지 않는 학습은 크게 기억에 남지 않는 것 같다.

Vim을 익히는 데는 시간이 조금 필요한데, 이게 사실 요즘 세상에 훨씬 좋은 편집기도 많아서 굳이 이걸 익힌다고 어떤 코딩이나 문서 작성의 속도가 매우 빨라진다거나 하지는 않는 것 같다. 하지만 현존하는 IDE의 대부분이 Vim단축키 모드를 지원하고 있고, 특히나 서버에 기본적으로 Vim이 전부 깔려 있으므로 익숙해지면 여러 곳에서 일관된 사용성으로 무언가를 작성할 수 있다. 또한 마우스를 사용하지 않게 되므로 미세한 컨텍스트 스위칭이 일어나지 않는다고 해야 할지, 집중력이 유지된다는 장점도 있다. 특히나 키보드로 단축키를 계속 입력하면 자신도 모르는 리듬감이 생겨서 뭔가 재밌기도 하다.

여기서는 나름 생각했을 때 빠르게 Vim을 익힐 수 있는 방법에 대해 이야기해 보자.

Vim의 기본

Vim은 여러 모드를 가진다. Vim에서의 문서 작성이라는 것은 결국 크게 보면 모드를 전환해가며 무언가를 작성하는 것이다. 그래서 모드를 얼마나 잘 전환하는가, 그리고 확인하지 않아도 지금 내가 무슨 모드에 있는가를 빠르게 캐치하는 것이 중요하다.

모드는 크게 노멀 모드입력 모드(Insert), 그리고 비주얼 모드로 나뉜다.

Vim의 노멀 모드는 텍스트가 입력되지 않고 그 키에 해당하는 액션이 일어난다. 입력 모드는 단축키가 아니라 텍스트가 입력된다. 그러니까 텍스트 입력을 위해서, 노멀 모드에서 뭔가를 최대한 진행한 후 입력 모드로 들어가면 된다.

Vim의 유명한 단축키는 모두 노멀 모드에서 사용할 수 있다. 그리고 노멀 모드에서는 텍스트의 수정이나 편집을 진행할 수 있다. 그러니까, 입력 모드에서만 텍스트를 편집할 수 있는 것이 아니다. 따라서 모드 전환을 빈번하게 하지 않더라도 최대한 노멀 모드에서 많은 수정을 진행하는 것이, 모드 전환이 덜 일어나므로 여러 면에서 매우 유리하다. 거기에 Vim의 플러그인들이 대부분 노멀 모드에서의 추가 기능을 지원하고 있으므로 플러그인을 설치하면 할수록 노멀 모드에서 할 수 있는 일이 더 많아진다.

실전 예제: 텍스트의 간단한 편집

어쨌든 Vim에 익숙하지 않을 때 겪는 가장 난감한 경우는 노멀 모드와 입력 모드의 전환이 매우 잦게 발생하는 순간이다. 예를 들어 바로 아래의 경우가 바로 그렇다.

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacaaaaaaaaaaaaaaaaabaaaaaadaaa

여기서 문자 b를 지우는 방법을 생각해 보자.

내가 처음 vim을 사용했을 때는, 이럴 때 b근처로 가서 i를 누르고 백스페이스를 눌러 지워야 했다. 커서를 옮기는 데 시간도 많이 걸린다. GUI에서 편집할 때를 생각해 보면 그냥 해당 부분을 마우스로 찍어서 지우면 되는데, 마우스와 상호작용이 일어나지 않는 Vim에서는 이게 매우 번거롭고 불편하다. 거기다 i를 눌러 입력 모드로 전환되면 입력 커서가 어디에 생기는지도 몰라서, 화살표키로 커서 위치를 조정하고 백스페이스를 눌러 지웠었던 것 같다.

이럴 때 단축키 x를 써 볼수 있다. x는 현재 커서가 위치한 곳의 글자를 삭제하고 텍스트를 모두 한 칸씩 당긴다. 따라서 hl로, 혹은 화살표 키로 커서를 이동한 후 b위로 올리고 나서 x를 눌러 지울 수 있다.

x: 커서가 위치한 한 글자를 지운다.

누군가는 커서 이동이 너무 오래 걸리는 것이 아니냐고 생각할 수 있다. 커서 이동은 한 칸씩 일어나는데, 문자 50개를 지나야 한다면 커서 이동키를 50번 눌러야 b위에 커서를 올릴 수 있는데, 언제 50번을 누르고 있나? 여기서 숫자와 단축키를 조합하는 Vim의 기능을 이용해볼 수 있다. 커서 이동 키 hjkl은 언어로 치면 접두사를 줄 수 있는데, 숫자를 접두사로 주면 그 숫자만큼 액션을 반복할 수 있다. 따라서 5l을 누른다면 오른쪽으로 5칸 이동하게 된다. 아니아니… 그러면 5l을 몇 번을 눌러야 하나? 그럴 때는 대충 눈치봐서 30l같은걸 쓰는게 맞다. 어느 정도 가까워질때까지 적당히 숫자를 바꿔가며 커서를 이동시켜 보자.

숫자: 뒤에 따라오는 액션을 숫자만큼 반복한다.

그래도 숫자가 얼마나 되는지 일일히 세어 볼 수도 없고, 이거 너무 불편할 것 아니냐? 라고 말할 수 있다. 어떻게 한 번에 문자 b까지 이동하는 방법은 없을까? 이번에는 단축키 t를 써 보자. t는 “~까지"의 역할을 하는 vim의 단축키이다. 따라서 tb라고 입력할 경우, 커서는 한 번에 b위치 전까지 이동하게 될 것이다.

t(till): ~까지 커서를 이동한다.

커서는 b앞의 a까지 이동하는데, 그러면 아예 b 위로 올리는 방법은? t대신 f를 써서 fb라고 입력하면 커서는 b위에 올라가게 될 것이다.

f: 커서를 가장 가까운 특정 문자 위에 올린다.

커서를 어떻게든 b위에 올렸으니 이번에는 글자를 고쳐 보자. i를 누르면 글자 바로 앞에 입력 커서가 뜬다. 그래서 이럴 때 i를 누르면 화살표 키로 커서를 오른쪽으로 한 칸 이동시켜야 한다. 왜냐 하면 백스페이스는 지울 글자 다음에 커서를 위치시켜야 하기 때문이다. 그러므로 a를 통해 입력 커서를 글자 오른쪽에 위치시켜 보자.

a: 커서 오른쪽에 입력 커서를 만든다.

그러면 백스페이스를 눌러 커서를 지울 수 있는데, 입력 모드로 변경하지 않고 글자만을 바꿔보자. 단축키 r은 현재 커서의 글자를 다음에 따라오는 글자로 변경할 수 있다.

r: 현재 커서가 위치한 글자를 다른 글자로 바꾼다.

이런 케이스에서 커서를 이동하는 방법, 그리고 입력 모드로 돌입하는 것, 그리고 입력 모드로 전환하지 않고도 텍스트를 원하는 대로 수정할 수 있는 것을 확인했다. 이런 식으로 Vim에 대한 단축키를 조금씩 익혀나간다면 점점 Vim에 익숙해지게 되고 속도가 제법 나면서 더 빠르게 Vim을 익히게 된다…

Vim의 단축키 도표

vim-cheatsheet

여러가지 그림을 봤는데 이 그림이 제일 좋아 보인다. 그 이유로는,

  1. 커서를 이동하는 법이 제일 직관적으로 표현되어 있고,
  2. 모드를 전환하는 방법이 종류별로 나뉘어 있으며,
  3. [operator][count][motion]이 표현되어 있다.

이 세 가지가 vim의 핵심이라고 생각하는데 여기에 다 써있기 때문이다. 다른 부분이야 필요할 때 찾아서 익히면 되니까.

motion

motion은 커서를 이동하는 단축키다. 이미지의 상하좌우 화살표에 쓰여 있는대로 이동한다. 단 다 외울 필요도 없다.

  1. 상하좌우 이동은 hjkl로,
  2. 좌우로 더 빨리 이동하려면 w, b로(단어 단위 이동)
  3. 상하로 더 많이 이동하고 싶으면 C-u, C-d로,
  4. 라인의 첫 글자와 끝으로 가려면 ^, $로,
  5. 파일의 첫 라인, 마지막 라인으로 이동하려면 G, gg

이것들만 외우면 우선 이동은 끝난다. 물론 다른 키들이 있긴 한데 의미적으로도 이것들이 외우기가 쉽다.

  1. hjklj키, 돌기가 나온 키가 아래 이동이라고 생각해두면 나머지를 외울 수 있다.
  2. 단어 단위로 이동하려면 w(word), 뒤로는 b(back)
  3. 위아래는 C-u(page up), C-d(page down)
  4. 첫, 마지막 글자는 정규식의 그것이며
  5. 파일 처음과 끝은 그냥 외우자…

예를 들어 0을 누르면 라인의 아예 처음 끝, 즉 커서 포지션이 0으로 가지만 대부분 ^만 사용해도 문제가 없다. C-b의 경우 1페이지 단위로 위로 이동하지만 의미가 조금 이상하게 느껴진다. b가 왜 up 1 page인지… 여튼 이렇게만 외워도 당장은 사용할 수 있다.

motion의 의미는 커서를 단순히 이동만 하는 것이 아니다. operator를 통해 커서에 어떤 속성을 부여했다면, 그 속성을 가진 채로 커서를 이동한다. 즉 dj의 경우 d를 통해 커서에 삭제 속성을 부여 후 j를 통해 커서를 아래로 내리는 것이다. 커서는 다음 줄로 내려가므로, 현재 라인과 다음 라인 두 줄이 지워진다. 삭제 속성이 부여된 채로 현재 라인에서 다음 라인으로 이동하니까. 그렇다면 dgg는?

count

이는 단축키가 아니라 단순히 숫자를 입력하면 된다. motion과 조합이 되는데, 즉 l은 오른쪽 한 칸 이동이지만 5l은 오른쪽으로 다섯 칸 이동한다. 즉, 5는 l을 꾸며주는 접두사라고 생각하자. 어쨌든 이렇기때문에 vim 유저는 :set nu를 통해 편집 화면 왼쪽에 라인 넘버를 띄워놓는데, 커서를 아래로 이동시키거나 지워야 하는 경우 현재 커서와의 라인 수를 계산해서 숫자와 함께 사용하게 된다.

operator

operator는 동작을 나타낸다. 여기서 알아야 할 것은 motion키는 동작을 나타내는 것이 아니다. 여기서 말하는 동작이란, 커서를 이동하는 것 이외의 문서 편집 전반에 대한 내용을 말한다. 사실 이렇게 말하면 매우 큰 범위같지만 그런 것도 아닌것이, 대표적으로 이 d(delete), y(yank) 두 가지만 알면 된다. c도 알면 좋은데 사실 당장은 안 써도 된다.

어쨌든 이 operator의 특징은 키를 입력하면 아무런 동작을 하지 않는다는 것이다. 따라오는 count, motion이 있어야 제대로 동작한다. 그럼 dd는 뭐냐고? 그건 그냥 한줄 편하게 지우라고 따로 매핑한 것이라 생각하자. 사실은 인터넷 어딘가에서 봤는데 dd, 혹은 yy는 원래 동작이 각각 d_y_이지만, 편의를 위해 이렇게 바뀐거라고…(사실인지는 모름)

조합

위 세 가지, operator, count, motion을 이해하면 이런 단축키는 누가 알려주지 않아도 바로 생각해볼 수 있다.

  • d5j: 아래로 여섯 줄을 지운다. 왜 5줄이 아니냐고? 커서가 위치한 라인 다음부터 숫자를 세기 때문이다.
  • dw: 커서가 위치한 곳에서부터 단어 하나를 지운다. count가 없으면 1이 생략된 것이다. 즉 l1l과 같다. 그래서 다시 쓰면 d1w가 된다.
  • yG: 커서가 위치한 곳부터 파일 끝까지 yank(클립보드에 복사)한다.

더 많은 조합이 필요하다면 이제 operator와 더 많은 motion 단축키를 외우면 된다. 사용하다보면 자연스럽게 외워질 거고, 빨리 외워야 한다면 외운 것을 바로바로 몇 번씩 써먹어보자.