Vi는 1976년 Bill Joy가 BSD Unix를 위해 작성한 텍스트 에디터다. 당시 터미널 환경에서 키보드만으로 효율적인 편집을 가능하게 한 혁신적인 도구였다. Vi의 핵심 아이디어인 **모달 편집(Modal Editing)**은 오늘날까지 살아 숨 쉰다.
Vim(Vi IMproved)은 1991년 Bram Moolenaar가 공개한 Vi의 대폭 확장 버전이다. 구문 강조, 플러그인 시스템, 다중 창, 매크로, 정규식 치환 등 수백 가지 기능이 추가되었다. Vim은 GNU/Linux 서버에 기본 탑재되어 전 세계 개발자와 시스템 관리자가 일상적으로 사용하는 표준 에디터가 되었다.
Neovim은 2014년에 시작된 Vim의 리팩토링 포크다. Lua 기반 설정, 내장 LSP(Language Server Protocol), 비동기 플러그인 API를 제공하며, VS Code 수준의 IDE 경험을 터미널에서 구현하는 것을 목표로 한다.
에디터
출시
특징
Vi
1976
모달 편집의 원조, 경량
Vim
1991
플러그인, 구문 강조, 매크로
Neovim
2014
Lua API, 내장 LSP, 비동기 처리
1.2 왜 Vim을 배워야 하는가
어디서나 사용 가능: SSH 접속한 원격 서버, Docker 컨테이너, 임베디드 장치 — 거의 모든 Unix 환경에 Vi/Vim이 설치되어 있다.
손이 키보드를 벗어나지 않는다: 마우스 없이 모든 조작이 가능하므로 편집 속도가 극적으로 향상된다.
강력한 조합 언어: d3w(단어 3개 삭제), ci"(따옴표 안 내용 변경) 처럼 동사+횟수+명사 구조로 복잡한 조작을 간결하게 표현한다.
매크로와 자동화: 반복 작업을 매크로로 기록하여 수천 줄을 순식간에 변환한다.
Vim 키바인딩의 범용성: VS Code, IntelliJ, Obsidian, Jupyter, bash readline, tmux copy mode 등 수십 가지 도구가 Vim 키바인딩을 지원한다. Vim을 배우면 모든 도구가 빨라진다.
2. 모드(Mode) 개념
Vim의 가장 중요한 특징은 모달 편집이다. 키를 누를 때의 동작이 현재 모드에 따라 완전히 달라진다.
규칙: 언제든 <Esc>를 누르면 Normal Mode로 돌아간다. 방향을 잃었을 때 <Esc>를 2번 누르는 것이 Vim 생존 법칙 #1이다.
3. 이동 명령어
3.1 기본 이동 (hjkl)
키
동작
h
왼쪽 한 칸
j
아래 한 줄
k
위 한 줄
l
오른쪽 한 칸
5j
아래 5줄 (숫자 접두어 조합 가능)
10k
위 10줄
3.2 단어 단위 이동
키
동작
w
다음 단어 시작으로 이동 (구두점 구분)
W
다음 WORD 시작으로 이동 (공백 구분)
b
이전 단어 시작으로 이동
B
이전 WORD 시작으로 이동
e
현재/다음 단어 끝으로 이동
E
현재/다음 WORD 끝으로 이동
ge
이전 단어 끝으로 이동
소문자(w, b, e)는 구두점을 단어 경계로 인식하고, 대문자(W, B, E)는 공백만 경계로 인식한다. hello_world에서 w는 2번, W는 1번에 이동한다.
3.3 줄 단위 이동
키
동작
0
줄의 맨 처음(컬럼 0)으로 이동
^
줄의 첫 번째 비공백 문자로 이동
$
줄의 맨 끝으로 이동
g_
줄의 마지막 비공백 문자로 이동
gg
파일의 첫 번째 줄로 이동
G
파일의 마지막 줄로 이동
42G
42번 줄로 이동
:42
42번 줄로 이동 (명령 모드)
%
매칭되는 괄호/중괄호/대괄호로 이동
3.4 화면 스크롤
키
동작
<C-u>
화면 절반 위로 스크롤
<C-d>
화면 절반 아래로 스크롤
<C-f>
화면 전체 아래로 스크롤 (Page Down)
<C-b>
화면 전체 위로 스크롤 (Page Up)
H
화면 맨 위 줄로 커서 이동 (High)
M
화면 중간 줄로 커서 이동 (Middle)
L
화면 맨 아래 줄로 커서 이동 (Low)
zz
현재 줄을 화면 중앙에 맞춤
zt
현재 줄을 화면 상단에 맞춤
zb
현재 줄을 화면 하단에 맞춤
3.5 검색 이동
키
동작
/pattern
아래 방향으로 pattern 검색
?pattern
위 방향으로 pattern 검색
n
같은 방향으로 다음 검색 결과
N
반대 방향으로 다음 검색 결과
*
커서 아래 단어를 아래 방향으로 검색
#
커서 아래 단어를 위 방향으로 검색
f{char}
현재 줄에서 char를 앞 방향 검색, 그 위치로 이동
F{char}
현재 줄에서 char를 뒤 방향 검색
t{char}
char 바로 앞으로 이동 (till)
T{char}
char 바로 뒤(역방향)로 이동
;
f/F/t/T 방향으로 반복
,
f/F/t/T 역방향으로 반복
3.6 점프 이동
키
동작
<C-o>
이전 커서 위치로 이동 (jump back)
<C-i>
다음 커서 위치로 이동 (jump forward)
''
직전 점프 위치로 복귀 (작은따옴표 2번)
m{a-z}
현재 위치를 마크 a~z로 저장
'{a-z}
마크로 이동
gd
로컬 정의(declaration)로 이동
gD
전역 정의로 이동
4. 편집 명령어
4.1 삽입 모드 진입
키
동작
i
커서 앞에서 Insert Mode 진입
I
줄의 첫 비공백 문자 앞에서 Insert Mode 진입
a
커서 뒤에서 Insert Mode 진입 (append)
A
줄의 끝에서 Insert Mode 진입
o
현재 줄 아래에 새 줄을 추가하고 Insert Mode 진입
O
현재 줄 위에 새 줄을 추가하고 Insert Mode 진입
gi
마지막으로 편집한 위치에서 Insert Mode 진입
4.2 삭제 명령어
키
동작
x
커서 아래 문자 삭제
X
커서 앞 문자 삭제 (Backspace)
dd
현재 줄 삭제
3dd
현재 줄부터 3줄 삭제
D
커서부터 줄 끝까지 삭제 (d$와 동일)
dw
커서부터 다음 단어 시작 전까지 삭제
de
커서부터 단어 끝까지 삭제
d0
커서부터 줄 시작까지 삭제
dG
현재 줄부터 파일 끝까지 삭제
dgg
현재 줄부터 파일 시작까지 삭제
삭제된 텍스트는 레지스터에 저장되어 p로 붙여넣기할 수 있다. Vim의 삭제는 "잘라내기(Cut)"와 동일하다.
4.3 변경 명령어
키
동작
r{char}
커서 아래 문자를 char로 교체 (Normal Mode 유지)
R
Replace Mode 진입 (연속 덮어쓰기)
s
커서 아래 문자 삭제 후 Insert Mode 진입
S
현재 줄 내용 삭제 후 Insert Mode 진입 (cc와 동일)
cw
커서부터 단어 끝까지 변경
cc
현재 줄 내용 변경
C
커서부터 줄 끝까지 변경 (c$와 동일)
c0
커서부터 줄 시작까지 변경
~
커서 아래 문자의 대소문자 토글
g~w
단어의 대소문자 토글
guw
단어를 소문자로 변환
gUw
단어를 대문자로 변환
4.4 복사 및 붙여넣기
키
동작
yy
현재 줄 복사 (yank)
Y
현재 줄 복사 (yy와 동일)
3yy
현재 줄부터 3줄 복사
yw
커서부터 단어 끝까지 복사
y$
커서부터 줄 끝까지 복사
y0
커서부터 줄 시작까지 복사
p
커서 뒤(아래)에 붙여넣기
P
커서 앞(위)에 붙여넣기
gp
p와 동일하나 붙여넣기 후 커서를 붙여넣은 텍스트 끝으로 이동
"ayy
레지스터 a에 현재 줄 복사
"ap
레지스터 a의 내용 붙여넣기
4.5 Undo / Redo
키
동작
u
마지막 변경 취소 (Undo)
3u
마지막 3개 변경 취소
<C-r>
Undo 취소 (Redo)
U
현재 줄에 대한 모든 변경 취소
4.6 들여쓰기
키
동작
>>
현재 줄 들여쓰기
<<
현재 줄 내어쓰기
3>>
3줄 들여쓰기
=
자동 들여쓰기 (Visual 선택 후 또는 ==으로 현재 줄)
==
현재 줄 자동 들여쓰기
gg=G
파일 전체 자동 들여쓰기
5. Visual Mode
5.1 Visual Mode 종류
키
모드
설명
v
Visual (문자)
문자 단위 선택
V
Visual Line
줄 단위 선택
<C-v>
Visual Block
열(column) 단위 블록 선택
gv
—
이전 Visual 선택 영역 재선택
5.2 Visual Mode에서 사용 가능한 조작
키
동작
d / x
선택 영역 삭제
y
선택 영역 복사
c
선택 영역 삭제 후 Insert Mode 진입
> / <
선택 영역 들여쓰기 / 내어쓰기
=
선택 영역 자동 들여쓰기
~
선택 영역 대소문자 토글
u
선택 영역 소문자 변환
U
선택 영역 대문자 변환
:
선택 영역에 명령 적용 (:'<,'>)
o
선택 영역의 반대 끝으로 커서 이동
5.3 Visual Block 실전 예제
Visual Block(<C-v>)은 여러 줄에 동시에 텍스트를 삽입하거나 삭제할 때 매우 유용하다.
예시: 여러 줄 앞에 // 주석 추가하기
1.<C-v>로 VisualBlock 진입
2. j를 눌러 원하는 줄 수만큼 선택
3.I 를 눌러 블록 InsertMode 진입
4.// 입력5.<Esc> 를 누르면 모든 선택된 줄에 // 가 삽입됨
예시: 여러 줄의 특정 컬럼 내용 삭제
1.<C-v>로 VisualBlock 진입
2. 원하는 범위 선택(hjkl로 열 범위 조정 가능)3. d로 삭제
6. 텍스트 객체 (Text Objects)
텍스트 객체는 Vim 편집의 핵심 개념이다. {operator}{a|i}{object} 구조로 "동사 + 전치사 + 명사" 형태의 명령을 구성한다.
a (around): 객체와 주변 공백/구분자 포함
i (inner): 객체 내부만 선택
6.1 텍스트 객체 목록
객체
i (inner)
a (around)
w
단어 내부
단어 + 주변 공백
W
WORD 내부
WORD + 주변 공백
s
문장 내부
문장 + 뒤 공백
p
단락 내부
단락 + 앞뒤 빈 줄
"
"..." 안쪽 내용
"..." 전체
'
'...' 안쪽 내용
'...' 전체
`
`...` 안쪽 내용
`...` 전체
( / )
(...) 안쪽
(...) 전체
[ / ]
[...] 안쪽
[...] 전체
{ / }
{...} 안쪽
{...} 전체
< / >
<...> 안쪽
<...> 전체
t
XML/HTML 태그 내부
태그 포함 전체
6.2 텍스트 객체 + Operator 조합 예제
명령
동작
예시 상황
diw
커서 아래 단어 삭제
hello 위에서 → 단어 삭제
daw
커서 아래 단어 + 공백 삭제
문장 중 단어 완전 제거
ci"
"..." 안 내용 변경
"old" → 따옴표 유지하고 내용 교체
ca"
"..." 전체 변경
"old" → 따옴표까지 교체
di(
(...) 안 내용 삭제
함수 인자 전체 삭제
da(
(...) 전체 삭제
괄호 포함 삭제
yip
현재 단락 복사
단락 전체 복사
dap
현재 단락 삭제
단락 전체 삭제
vit
HTML 태그 내부 Visual 선택
<div>content</div>에서 content 선택
cit
HTML 태그 내부 변경
태그 내용 교체
=i{
중괄호 안 자동 들여쓰기
함수 바디 전체 정렬
>i{
중괄호 안 들여쓰기 추가
7. 명령 모드 (Command-line Mode)
7.1 파일 조작
명령
동작
:w
저장
:w filename
다른 이름으로 저장
:q
종료 (변경 없을 때)
:q!
변경 사항 무시하고 강제 종료
:wq
저장 후 종료
:wq!
강제 저장 후 종료
:x
변경 사항이 있을 때만 저장 후 종료 (ZZ와 동일)
ZZ
:x와 동일
ZQ
:q!와 동일
:e filename
파일 열기
:e!
현재 파일 변경 사항 버리고 재로드
:r filename
파일 내용을 현재 위치에 삽입
:r !command
명령 실행 결과를 현재 위치에 삽입
7.2 검색 및 치환
명령
동작
:%s/old/new/g
파일 전체에서 old를 new로 모두 치환
:%s/old/new/gc
전체 치환, 각 항목마다 확인
:%s/old/new/gi
대소문자 무시하고 전체 치환
:5,20s/old/new/g
5~20번 줄에서 치환
:'<,'>s/old/new/g
Visual 선택 영역에서 치환
:%s/\s\+$//e
줄 끝 공백 제거
:%s/^/ /
모든 줄 앞에 공백 4개 추가
7.3 외부 명령 실행
명령
동작
:!command
외부 명령 실행 (예: :!ls -la)
:!python %
현재 파일을 Python으로 실행
:%!command
파일 전체를 command의 입력으로 넘기고 출력으로 교체
:.!command
현재 줄을 command의 입력으로 넘기고 출력으로 교체
:shell
임시로 쉘로 나가기 (exit으로 복귀)
7.4 범위 지정
범위 표현
의미
:5
5번 줄
:5,10
5번에서 10번 줄
:%
파일 전체 (1,$와 동일)
:.
현재 줄
:.,$
현재 줄부터 파일 끝
:'<,'>
Visual 선택 영역
:.,+5
현재 줄부터 5줄
8. 버퍼, 윈도우, 탭
8.1 버퍼 관리
**버퍼(Buffer)**는 메모리에 열려 있는 파일이다. 여러 파일을 동시에 열어 편집할 수 있다.
명령
동작
:ls / :buffers
열려 있는 버퍼 목록 표시
:b2
2번 버퍼로 전환
:bn
다음 버퍼로 전환
:bp
이전 버퍼로 전환
:bd
현재 버퍼 닫기
:ba
모든 버퍼를 분할 창으로 열기
8.2 창 분할
명령
동작
:sp / :split
수평 분할 (horizontal split)
:vsp / :vsplit
수직 분할 (vertical split)
:sp filename
파일을 새 수평 분할 창에서 열기
:vsp filename
파일을 새 수직 분할 창에서 열기
<C-w>s
수평 분할 (Normal Mode)
<C-w>v
수직 분할 (Normal Mode)
<C-w>w
다음 창으로 포커스 이동
<C-w>h/j/k/l
방향으로 창 이동
<C-w>H/J/K/L
창을 해당 방향으로 이동
<C-w>=
모든 창 크기 균등 분배
<C-w>+ / <C-w>-
수평 크기 조정
Ctrl-w > / Ctrl-w <
수직 크기 조정
Ctrl-w _
현재 창 수직 최대화
Ctrl-w |
현재 창 수평 최대화
<C-w>q
현재 창 닫기
<C-w>o
다른 모든 창 닫기 (only)
8.3 탭 관리
명령
동작
:tabnew
새 탭 열기
:tabnew filename
파일을 새 탭에서 열기
gt
다음 탭으로 이동
gT
이전 탭으로 이동
2gt
2번 탭으로 이동
:tabclose
현재 탭 닫기
:tabonly
다른 모든 탭 닫기
:tabs
탭 목록 표시
9. 매크로와 레지스터
9.1 매크로 (Macro)
매크로는 일련의 키 입력을 기록하여 반복 실행하는 기능이다.
키
동작
q{a-z}
레지스터 a~z에 매크로 기록 시작
q
매크로 기록 종료
@{a-z}
레지스터의 매크로 실행
@@
마지막 실행한 매크로 재실행
10@a
레지스터 a의 매크로를 10회 반복 실행
매크로 실전 예제: CSV 각 줄의 첫 번째 필드에 따옴표 추가
원본: hello,world
목표:"hello",world
1. q a(레지스터 a에 기록 시작)2.0(줄 시작으로 이동)3. i"<Esc> (줄 앞에 " 삽입)4. f,(첫 번째 , 앞으로 이동)5. i"<Esc> (, 앞에 " 삽입)6.j(다음 줄로 이동)7.q(기록 종료)8.99@a(나머지 줄에 반복 적용)
9.2 레지스터 종류
레지스터
설명
" (unnamed)
기본 레지스터. 삭제/복사 시 자동 사용
0
마지막 yank(복사) 내용
1~9
최근 삭제/변경 내용 (순환)
a~z
사용자 지정 레지스터
A~Z
소문자 레지스터에 추가(append)
+
시스템 클립보드
*
Primary selection (Linux X11)
_
Black hole 레지스터 (삭제해도 레지스터 오염 없음)
%
현재 파일명
:
마지막 실행한 명령
/
마지막 검색 패턴
레지스터 사용 예시:
"+yy " 현재 줄을 시스템 클립보드에 복사
"+p " 시스템 클립보드 내용 붙여넣기
"_dd " 줄을 삭제하되 레지스터를 오염시키지 않음
"ayy " 레지스터 a에 현재 줄 복사
"Ayy " 레지스터 a에 현재 줄을 추가(append):reg" 모든 레지스터 내용 확인:reg a " 레지스터 a 내용 확인
10. .vimrc 필수 설정
10.1 기본 설정 코드블록
" ===================================================" .vimrc 기본 필수 설정" ===================================================" 기본 편의 설정setnocompatible" Vim 모드 (Vi 호환 모드 비활성화)setencoding=utf-8" 인코딩setfileencoding=utf-8setnumber" 줄 번호 표시set relativenumber " 상대 줄 번호 (현재 줄 기준)setcursorline" 현재 줄 강조setshowmatch" 매칭 괄호 강조setnowrap" 줄 바꿈 비활성화setscrolloff=8" 화면 스크롤 시 여백 유지set signcolumn=yes " 사인 컬럼 항상 표시" 검색 설정sethlsearch" 검색 결과 강조setincsearch" 실시간 검색setignorecase" 대소문자 무시setsmartcase" 대문자 포함 시 case sensitive" 탭/들여쓰기 설정settabstop=4" 탭 = 4칸setshiftwidth=4" 들여쓰기 = 4칸setsofttabstop=4setexpandtab" 탭을 스페이스로 변환setautoindent" 자동 들여쓰기setsmartindent" 스마트 들여쓰기" 성능/UX 설정setlazyredraw" 매크로 실행 중 화면 갱신 최소화setupdatetime=250" Swap 파일 갱신 간격 (ms)settimeoutlen=300" 키 입력 대기 시간 (ms)sethidden" 버퍼 숨기기 허용 (저장 안 해도 전환 가능)sethistory=1000" 명령 히스토리 1000개setundolevels=1000" Undo 최대 횟수" 파일 타입 및 구문 강조filetype plugin indent on" 파일 타입별 플러그인/들여쓰기 활성화syntaxon" 구문 강조 활성화setbackground=dark " 어두운 배경" 클립보드setclipboard=unnamedplus " 시스템 클립보드 사용 (Linux)" set clipboard=unnamed " macOS
" 백업 파일 비활성화setnobackupsetnowritebackupsetnoswapfile" 상태바setlaststatus=2" 상태바 항상 표시setruler" 커서 위치 표시setshowcmd" 입력 중인 명령 표시" 마우스 지원 (선택 사항)setmouse=a
10.2 유용한 키 매핑
" ===================================================" Key Mappings" ===================================================let mapleader =" "" Leader 키를 스페이스바로 설정" 일반 편의 매핑nnoremap <Leader>w:w<CR>" <Space>w 로 저장nnoremap <Leader>q:q<CR>" <Space>q 로 종료nnoremap <Leader>wq:wq<CR>" <Space>wq 로 저장+종료nnoremap <Leader>ev :e ~/.vimrc<CR>" vimrc 빠른 편집" 검색 결과 강조 해제nnoremap <Leader>/:nohlsearch<CR>" 창 이동 (Ctrl + hjkl)nnoremap <C-h><C-w>hnnoremap <C-j><C-w>jnnoremap <C-k><C-w>knnoremap <C-l><C-w>l" 줄 이동 (Alt + j/k)nnoremap <A-j>:m.+1<CR>==nnoremap <A-k>:m.-2<CR>==vnoremap <A-j>:m '>+1<CR>gv=gv
vnoremap <A-k>:m '<-2<CR>gv=gv
" 들여쓰기 후 Visual 유지vnoremap <<gv
vnoremap >>gv
" 터미널 모드 탈출tnoremap <Esc><C-\><C-n>" Y를 D, C처럼 동작하게 (커서부터 줄 끝까지 복사)nnoremap Y y$
" 중앙 정렬 유지하며 검색nnoremap n nzzzv
nnoremap N Nzzzv
" 붙여넣기 후 레지스터 유지xnoremap<Leader>p"_dP" 버퍼 이동nnoremap <Leader>bn:bnext<CR>nnoremap <Leader>bp:bprevious<CR>nnoremap <Leader>bd:bdelete<CR>
cs"' → "Hello" 를 'Hello'로 변경(change surrounding)cs({→(Hello) 를 {Hello}로 변경
ds" → "Hello" 의 따옴표 제거(delete surrounding)ysiw" → 커서 아래 단어에 "" 추가(you surround inner word)yss) → 현재 줄 전체를()로 감싸기
S" → Visual 선택 영역을 ""로 감싸기