Skip to content

Instantly share code, notes, and snippets.

@joonhwan
Forked from dmsul/vim_crash_course.md
Last active May 13, 2026 11:12
Show Gist options
  • Select an option

  • Save joonhwan/a8d0a5a58fe773758e7adaa176621cd4 to your computer and use it in GitHub Desktop.

Select an option

Save joonhwan/a8d0a5a58fe773758e7adaa176621cd4 to your computer and use it in GitHub Desktop.
Vim Crash Course

참고: 옵션, 플래그, 명령어 변형 등에 대한 구체적인 예시는 모든 경우를 포괄하지 않습니다.

노멀 모드 (NORMAL MODE)

Vim은 모든 키의 동작 방식을 바꾸는 2가지 주요 "모드"를 가지고 있습니다. Vim의 기본 모드는 노멀 모드이며, 주로 커서 이동과 현재 파일 내 탐색에 사용됩니다.

일부 중요한 (또는 긴) 명령어는 ":"로 시작하며, 입력하는 텍스트는 화면 좌측 하단에 표시됩니다.

:q[uit] - Vim (의 현재 창)을 종료합니다. (여기서 "창"은 Vim 내부의 창을 의미하며, 동시에 여러 개의 OS 레벨 Vim 창을 열어둔 경우가 아닙니다.) :q! - 강제 종료 (마지막 저장 이후 현재 버퍼가 변경된 경우) :e[dit] {filename} - 파일 {filename}을 새 버퍼로 읽어들입니다. Vim은 MS Word처럼 파일을 "열지" 않습니다. 대신 파일 내용을 RAM으로 읽어들이고, RAM 안의 "버퍼"를 편집합니다. 다른 프로그램이 원래 열었던 파일에 접근하거나 변경할 수 있습니다 (Vim은 이를 감지하고 경고를 표시합니다). :w[rite] {filename} - 현재 버퍼를 {filename}에 씁니다. 파일명을 전달하지 않은 경우 (예: :w) 버퍼에 이미 연결된 파일명 (:e {filename}에서 사용된 그 파일명)이 사용됩니다. 간단한 :w는 MS Word의 "저장"과 같고, :w {new_filename}은 "다른 이름으로 저장하되 현재 버퍼는 유지"와 같습니다. :save {filename} - 다른 이름으로 저장 (그리고 현재 버퍼를 {filename}으로 변경) :w! - 강제 쓰기 (예: 다른 프로그램에 의해 원본 파일이 변경되어 이번 쓰기가 그 변경을 덮어쓰게 되더라도)

이 명령어들은 결합할 수 있습니다, 예를 들어 :wq - 버퍼를 쓰고 종료 :wq! - 강제 쓰기 후 종료

기본 이동 명령어로 커서를 움직이기...

j - 아래로 k - 위로 h - 왼쪽으로 l - 오른쪽으로

0 - 줄의 맨 처음으로 이동 ^ - 줄의 첫 번째 문자 (공백이나 탭이 아닌)로 이동 (줄이 공백이 아닌 문자로 시작하는 경우 "0"과 동일) $ - 줄의 끝으로 이동 참고: ^$는 정규 표현식에서 각각 문자열의 시작과 끝을 나타내는 단축 기호입니다

% - 커서가 괄호 (또는 유사한 기호) 안에 있으면 여는 괄호로 이동. 커서가 괄호 위에 있으면 짝이 되는 괄호로 이동. 괄호 사이에 있지 않으면 아무 일도 하지 않음. (짝이 맞지 않는 괄호에서는 이상한 동작을 할 수 있음.)

w - 한 단어 앞으로 (알파벳/숫자 또는 _; 또는 그렇지 않은 연속된 문자들) e - 현재 단어의 끝으로 (현재 단어 끝에 있으면 다음 단어의 끝으로) b - 단어의 시작으로 (현재 단어 시작에 있으면 이전 단어로) } - 한 단락 앞으로 이동. { - 한 단락 뒤로 이동.

gg - 파일의 시작으로 이동 [#]gg - [#]번 줄로 이동 (예: 20gg는 20번 줄로 이동) G - 파일의 끝으로 이동 [#]| - 현재 줄의 [#]번째 컬럼으로 이동, 예: 10|은 10번 컬럼으로 이동.

f<char> - "찾기"/줄에서 다음 <char> 인스턴스로 커서를 이동 F<char> - f이지만 뒤로 검색 t - "to"/f와 같지만, 해당 문자 바로 앞에 커서를 위치시킴 T - t이지만 뒤로 검색 ;(,) - 가장 최근의 f 또는 t에서 <char>의 다음 (이전) 인스턴스로 이동

/<RegEx><Enter> - <RegEx>의 다음 인스턴스로 이동 (전체 정규 표현식 매칭 사용) ? - /와 같지만 역방향 검색 n(N) - 최근 검색의 다음 (이전) 인스턴스 * - 커서 아래 단어에 대해 / 검색 수행 참고: 이는 기본 검색 기능입니다. /gen<Enter>는 "gen" 문자열의 다음 인스턴스로 이동하고, n은 그 다음 인스턴스로 이동합니다. 파일 끝에 도달하면 처음으로 돌아갑니다. ?/ 대신 사용하면 역방향 검색일 뿐입니다.

c-u - 커서를 한 페이지 위로 이동 c-d - 커서를 한 페이지 아래로 이동 참고: Vim 매핑에서 c-uCtrl+u를 의미합니다

c-e - 커서는 그대로 두고 앞으로 스크롤 c-y - 커서는 그대로 두고 뒤로 스크롤

c-f - 반 페이지 앞으로 c-b - 반 페이지 뒤로

H - 화면에서 가장 위쪽 줄로 (Home) M - 화면 중간 줄로 L - 화면에서 가장 아래쪽 줄로

참고: 대부분의 이동 명령어 앞에 숫자를 붙여서 그 횟수만큼 실행할 수 있습니다. 4j - 커서를 4번 아래로 이동 10w - 10 "단어" 앞으로 이동

비주얼 "모드" (VISUAL "MODE")

v[m] - 비주얼 (하이라이트) 모드로 진입하여 문자들을 선택합니다. 일반적인 이동 명령어를 사용해 커서가 움직임에 따라 선택 영역에 추가합니다. V[m] - 비주얼 모드이지만, 문자가 아닌 전체 줄 단위로 선택합니다. c-v[m] - 비주얼 모드이지만, 가로가 아닌 세로 (컬럼 단위)로 선택합니다.

ggvG - 파일 전체 하이라이트, 즉 파일의 시작으로 이동 (gg), 비주얼 모드 진입 (v), 파일 끝으로 이동 (G).

선택이 완료되면 그 선택 영역에 편집 명령어 (아래 참조)를 사용할 수 있으며 (대부분) 기대한 대로 동작합니다.

인서트 모드 (INSERT MODE)

대부분의 명령어는 노멀 모드에서 실행됩니다. 실제로 텍스트를 추가하려면 (한 줄 아래로 이동하는 대신 "j"를 입력하려면) 인서트 모드로 진입해야 합니다. 이를 위한 여러 방법이 있습니다.

i - 현재 문자 앞에 인서트 모드 진입 a - 현재 문자 뒤 (After)에 인서트 모드 진입 <Esc> - 인서트 모드 종료 (노멀 모드로 돌아감). 참고: <Esc>는 약간 멀리 떨어져 있기 때문에, 인서트 모드를 종료하기 위해 더 편리한 키 바인딩을 매핑하는 것이 일반적입니다. 예를 들어 vimrc에 inoremap jk <Esc>를 추가하면 <Esc> 대신 빠르게 jk를 사용할 수 있습니다.

I - 현재 줄의 텍스트 시작 부분에서 인서트 모드 진입 (^i와 동일) A - 현재 줄의 끝 다음 (After)에 인서트 모드 진입 ($a와 동일) o - 현재 줄 다음에 새 줄을 추가하고 인서트 모드 진입 (A<Enter>와 동일) O - 현재 줄 앞에 새 줄을 추가하고 인서트 모드 진입

c[m] - 여기서부터 [m]까지의 텍스트 변경. "Change"는 텍스트를 삭제하고 즉시 인서트 모드로 진입합니다. cc - 이 줄 전체 변경. C - 여기서부터 줄 끝까지 변경.

r - 현재 문자를 다음에 입력하는 문자로 교체 (한 문자만 허용) R - <Esc>까지 문자를 교체 (Word의 교체/덮어쓰기 모드와 같음)

노멀 모드에서의 편집 명령어

이 명령어들은 노멀 모드에 있는 동안 텍스트를 변경할 수 있게 해줍니다. 많은 명령어들은 편집을 실행할 범위를 지정하기 위해 이동 명령어 (여기서 [m]으로 표시)가 뒤따라야 합니다. 많은 (하지만 전부는 아닌) 명령어에 대한 몇 가지 공통 규칙: 더블 탭: 커서가 있는 전체 줄에 대해 명령어 실행 shift + 명령어: 커서에서 현재 줄의 끝까지 명령어 실행

더 일반적으로, 편집 명령어와 이동의 조합성은 Vim을 특히 강력하게 만드는 요소입니다. 5개의 편집 명령어와 5개의 이동 명령어를 알고 있다면, 실제로는 25개의 구체적이고 외우기 쉬운 명령어를 아는 것입니다.

[#]d[m] - [m]에 대해 삭제 ([#]번 실행) dw - 여기 (커서 위치)에서 다음 단어의 시작까지 삭제 (커서 아래 문자 포함) d4w - 여기서부터 4번째 단어 앞까지 삭제 dtT - 이 줄의 다음 "T" 인스턴스 직전까지 ("to") 삭제 (포함하지 않음) df) - 이 줄의 다음 ")" 인스턴스까지 ("finds") 삭제

dd - 현재 줄 전체 삭제. 4dd - 이 줄과 다음 3줄 삭제 (총 4줄) D - 여기서부터 줄 끝까지 삭제

y[m] - yank (복사). d (delete)와 동일한 동작. yw - 여기서부터 다음 단어 시작까지 yank y$ - 여기서부터 줄 끝까지 yank 참고: D와 일관성을 위해 vimrc에 Y에 대한 매핑을 추가하는 것이 일반적입니다: nnoremap Y y$

p - 커서 위치 다음에 붙여넣기 (a와 비슷) P - 커서 위치 앞에 붙여넣기 (i와 비슷)

레지스터 (yank와 paste용)

"\<char>y - <char> 레지스터에 yank. 이를 통해 클립보드에 여러 항목을 가질 수 있습니다. Vim 클립보드는 OS 클립보드와 별개입니다. 둘 사이를 이동하려면 (Vim과 다른 프로그램 간 복사/붙여넣기) * 레지스터를 사용합니다:

y$ - 줄 끝까지 yank, 기본 레지스터에 저장 "a$ - "a" 레지스터에 yank "*yG - 파일 끝까지 yank, OS 레지스터에 저장 p - 기본 레지스터의 내용을 붙여넣기 (커서 뒤에, a와 비슷) P - 커서 앞에 붙여넣기 (i 명령어와 비슷) "*p - OS 레지스터의 내용을 붙여넣기 (즉, 이미 *에 yank했거나 다른 프로그램에서 Ctrl+C로 복사한 경우)

참고: 텍스트를 삭제하면 그 텍스트가 기본 레지스터에 들어가므로, yy 후 다른 줄로 이동해 dd를 하면 yy로 yank했던 내용을 잃게 됩니다. 이 동작을 재정의하는 플러그인이 있습니다 (아마 Tim Pope가 만든 것).

대소문자 변경

~ - 이 문자의 대소문자 토글 [#]~ - 다음 [#]개 문자의 대소문자 토글 g~[m] - 이동 [m]에 따라 대소문자 토글 gU[m] - 대문자로 gu[m] - 소문자로

들여쓰기

>[m] - 현재 줄을 이동 [m]을 통해 들여쓰기 >5j - 이 줄과 다음 5줄 들여쓰기 >G - 파일 끝까지 들여쓰기 >> - 이 줄 들여쓰기 (dd, yy 등과 같이) <[m] - 들여쓰기 해제 (들여쓰기와 같지만 반대 방향)

기타 유용한 명령어

J - 다음 줄을 가져와 이 줄의 끝에 붙임.

gq[m] - 여기서부터 [m]까지의 텍스트 포맷팅 (대개 너무 긴 줄을 더 짧은 줄로 끊음, 기본값 80자). gqq - 현재 줄 포맷팅

u - undo c-r - redo

. - 마지막 편집 반복 (insert, replace, indent 등 포함) 참고: 매우 유용함. A;;<Esc>j. - 줄 끝에서 인서트 모드 진입 (A), 세미콜론 두 개 입력 (;;), 인서트 모드 종료 (<Esc>), 한 줄 아래로 이동 (j), 이 새 줄의 끝에 세미콜론 두 개 추가 (.) >>... - 이 줄을 들여쓰고 (>>), 추가로 세 번 더 들여쓰기 (...)

치환 (Substitution)

:<range>s/<re>/<str>/<flags> - <range> 내 각 줄에서 <re>의 첫 번째 인스턴스를 <str>로 치환. <flags>는 기본 동작을 변경.

  • <range>:

    • 기본 범위는 현재 줄만
    • % - 전역 (전체 파일)
    • <a>,<b> - 줄/마커 등의 사이
      • . - 현재 줄
      • $ - 파일의 마지막 줄 (:.,$s는 "여기서부터 파일 끝까지")
    • 참고: 다른 <range> 옵션도 있지만, 가장 일반적인 것은 %입니다.
  • <flags>:

    • g - 줄의 모든 <re> 인스턴스 (첫 번째 인스턴스만이 아닌)
    • c - 확인 (다음 <re> 인스턴스를 하이라이트하고 "y"를 눌러 변경을 실행하도록 요청)
    • i - 대소문자 구분 안 함

특정 치환: 매칭된 정규 표현식 내에서 치환되어야 할 하위 정규 표현식을 표시하기 위해 \zs\ze를 사용합니다. 예시:

:%s/Year \zs2007\ze is over/2008/g

이는 "Year 2007 is over"의 모든 인스턴스를 "Year 2008 is over"로 변경하지만, 모든 "2007"을 "2008"로 변경하지는 않습니다.

고급 이동(과 유사한) 명령어

delete, yank 등과 함께 사용할 수 있는 "이동" 명령어들이 있으며, 특정 텍스트 객체를 타겟팅하는 데 사용될 수 있습니다. dw는 커서에서 다음 단어 시작까지 삭제하므로, 커서가 단어 시작에 있지 않은 한 현재 단어 전체가 삭제되지 않습니다. 따라서 bdw는 전체 단어와 뒤의 공백을 삭제합니다 (커서가 이미 단어 시작에 있지 않다면).

이를 우회하는 단축키가 이 이동과 유사한 객체 명령어들입니다.

daw - "a" "word" 삭제. 현재 단어와 뒤의 공백을 삭제. diw - "inner" "word" 삭제. 현재 단어는 삭제하지만 뒤의 공백은 삭제하지 않음. dap - 한 단락 삭제. Vim에게 "단락"은 빈 줄(들) 사이의 연속된 텍스트 줄들의 그룹입니다. yaw - 단어 yank. yiw - 내부 단어 yank. ya( - 괄호 안 내용 yank. 커서가 () 사이에 있으면, 그 괄호 사이의 모든 내용과 괄호 자체를 yank. 아니면 아무 일도 하지 않음. yi( - 내부 괄호 내용 yank. ya(와 비슷하지만, 괄호 제외. ya) - ya(와 동일 ya[ - 대괄호 []에 대한 ya(와 동일. ya" - 동일

da( - 괄호 안 내용 삭제. di( - 괄호 내부 삭제.

g~i( - 괄호 내부의 대소문자 토글.

ciw - 내부 단어 변경 ci[ - 내부 (안쪽) 대괄호 변경 (대괄호 안 텍스트 삭제 후 인서트 모드 진입).

기타 매우 유용한 기능

예측 자동완성 (인서트 모드에서)

c-p - 예측 자동완성 (단어) c-x c-l - 예측 자동완성 (줄)

이는 이미 입력한 내용 (단어 또는 줄)을 가져와서 열려 있는 다른 버퍼들의 텍스트를 사용해 다음에 올 내용을 예측합니다. 가능성이 하나뿐이면 자동으로 채워집니다. 여러 가능성이 있으면 선택지를 제공합니다.

Vim 자동완성은 꽤 괜찮지만, 더 나은 자동화된 예측 텍스트 솔루션이 있습니다 (구체적으로, YouCompleteMe 패키지). 다만, 대부분의 노트북에는 좀 부담스럽고 데스크탑 컴퓨터에서만 유용하다는 것을 발견했습니다.

줄 단위 전역 명령

:g/<RegEx>/<edit command> - RegEx와 매칭되는 모든 줄에서 편집 명령 수행 :g!/... 또는 :v/... - 동일하지만 매칭되지 않는 줄에 대해 예시: :g/DEL THIS/d는 "DEL THIS"를 포함하는 모든 줄을 삭제합니다 :g/ $/d는 공백으로 끝나는 모든 줄을 삭제합니다.

매크로

q를 누른 다음 어떤 글자, 일반성을 잃지 않고 (WLOG) a를 누르면 매크로 "a" 녹화 시작. 원하는 작업 수행. q를 눌러 녹화 중지. @a로 새 매크로 반복. [#]@aa[#]번 반복.

기타 어느 정도 유용한 기능

마크 (Marks)

소문자는 로컬, 대문자는 전역 (파일 간). 마크로 점프하는 것은 delete, yank 등을 위한 표준 이동 명령어입니다.

ma - 현재 커서 위치 (줄과 컬럼)에 마크 설정, 일반성을 잃지 않고 (WLOG) "a"라고 부름 'a - "a"의 줄로 점프 (줄의 첫 비어있지 않은 문자) `a - "a"의 위치로 점프 (줄과 컬럼) :marks - 현재 모든 마크 나열 :delmarks <args> - 특정 마크 삭제 :delmarks! - 버퍼의 모든 소문자 마크 삭제 ]', [' - 소문자 마크가 있는 다음 (이전) 줄로 점프 ]`, [` - 다음 (이전) 소문자 마크로 점프

특별한 마크 (시작할 때 가장 유용)

' - "점프"하기 전에 있던 줄. 예를 들어 57번 줄에 있다가 gg로 파일 시작으로 점프하면, ''를 누르면 다시 57번 줄로 돌아갑니다. . - 현재 버퍼의 마지막 편집 `` - 방금 점프해 왔던 위치 (줄과 컬럼)로 다시 점프 `[, `] - 마지막으로 변경되거나 yank된 텍스트의 시작/끝으로 점프

맞춤법 검사 (Spellcheck)

:set spell로 켜고, :set nospell로 끕니다.

z= - 올바른 철자의 단어 제안 ]s, [s - 다음/이전 잘못 표기된 단어로 이동 ("bad words만"의 경우 S 사용) zq - 커서 아래 단어를 'spellfile'의 첫 번째 이름에 좋은 단어로 추가 zw - 나쁜 단어로 표시 zu[q,w] - 표시 취소

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment