알림: 이 글은 조쉬 데이비스의 글(https://joshldavis.com/2014/04/05/vim-tab-madness-buffers-vs-tabs)을 번역한 것이다. 저자의 허락을 구하고 번역했음을 밝힌다. -박연오

우선 말하자면 나는 Vim에서 탭을 무척 많이 썼다.

다른 대부분의 프로그램들(크롬, 터미널, 아디움 등)에서 탭을 쓰듯이 Vim의 탭을 사용한 것이다. 나는 탭을 문서가 활성화되어 존재하는 모종의 공간으로 여기고 있었다.

문서를 편집하려면 탭을 하나 새로 열어 편집한다! 이게 탭이 작동하는 방식이고 Vim에서도 마찬가지일 것이다. 그렇지 않은가?

틀렸다.

탭 오용은 이제 그만

만일 그런 방식으로 탭을 사용하는 중이라면 자기 손발을 묶는 셈이다. Vim이 제공하는 기능을 본연의 방식으로 사용하지 못하기 때문이다.

여러 사람들이 지적하는 것처럼, 사실 Vim의 탭은 엉뚱한 이름이 붙은 셈이다. 레이아웃이라는 이름이 더 어울릴 듯하다.

이에 관해 설명하기 전에, 몇가지 기초 사항과 함께 Vim의 버퍼가 무엇인지 정확히 알고 가자. 그 뒤에 Vim에서 탭을 사용하는 올바른 방법을 설명하겠다.

버퍼

버퍼는 바로 편집중인 텍스트다. 예를 들어, 파일을 열면 그 파일의 내용이 버퍼로 로드된다. 따라서 다음과 같은 명령을 실행하면,

$ vim .vimrc

.vimrc 파일의 내용을 담은 하나의 버퍼를 갖도록 하여 Vim을 실행하는 것이다. 뭐, 간단한 이야기.

그러면 여러 개의 파일을 편집할 때는 어떻게 되는지 보자. 다음 명령을 실행해보자.

$ vim .vimrc .zshrc
# 그 후, Vim에서 다음 명령을 실행
#   :bnext

Vim은 아까와 같이 실행되지만 버퍼를 하나만 갖는 것이 아니라 .zshrc 파일의 내용을 담은 버퍼를 추가로 연다. 따라서 이제 버퍼 두 개가 열렸다.

.vimrc 편집을 멈추고 .zshrc 를 편집하려면 :bnext 명령을 실행한다. 그러면 Vim은 .zshrc 버퍼를 표시한다. :h buffer-list 명령을 입력하면 버퍼를 조작하는 다양한 명령어들을 볼 수 있다.

출력 화면:

버퍼 두 개 편집

▲ 버퍼 두 개 편집

윈도우

Vim의 윈도우는 버퍼를 출력하는 방법이다. 편집 화면을 세로 또는 가로로 분리할 때 만들어지는 것이 바로 윈도우다. 예를 들어, :help 명령어를 실행하면 도움말 문서를 출력하는 새로운 윈도우가 실행될 것이다.

여기서 중요한 점은 윈도우는 어떤 버퍼든 출력할 수 있다는 것이다. 윈도우 하나가 버퍼 하나만 계속 출력하도록 강제되는 게 아니다. 물론 이 사실은 누구나 알 수 있다. 파일 하나를 편집할 때 :vsplit을 입력하면 윈도우가 세로로 나눠지고, 새로 만들어진 윈도우에도 지금 편집하고 있는 버퍼가 출력되는 것이다!

이 점은 더 헷갈릴 것이 없다. 윈도우는 어떤 버퍼든 출력할 수 있다. :split 또는 :vsplit 명령으로 윈도우를 분할하면 새 윈도우에 출력되는 내용은 현재 버퍼다.

:h buffer-list에서 볼 수 있는 버퍼 명령어로 윈도우가 출력할 버퍼를 바꿀 수 있다.

예를 들어, 아래 명령어로 다음과 같은 일을 할 수 있다. Vim에서 두 파일의 편집을 시작하고, 화면을 가로로 나눠 새 윈도우를 열고, 첫 윈도우에 두 번째 버퍼를 출력한다.

$ vim .vimrc .zshrc
# Vim에서 다음 명령을 실행한다:
#   :split
#   :bnext

위 명령을 실행하면 이렇게 된다:

윈도우 두 개로 버퍼 두 개 편집

▲ 윈도우 두 개로 버퍼 두 개 편집

그러면 탭은 뭐냐?

이제 버퍼와 윈도우가 무엇인지 알았다. Vim의 공식 문서는 버퍼, 윈도우, 탭을 다음과 같이 설명한다:

요약:
    버퍼는 메모리 상의 텍스트 파일이다.
    윈도우는 버퍼의 출력영역(viewport)이다.
    탭 페이지는 윈도우의 집합이다.

이 문서에 따르면 탭은 단지 윈도우의 집합일 뿐이다. 이 설명은 처음에 탭이 사실상 레이아웃이라고 한 정의와 부합한다.

탭은 다양한 윈도우 레이아웃을 제공하기 위해 만들어진 것이다.

아래는 아까와 똑같은 상황(파일 두 개와 가로로 나눠진 화면)에 다른 윈도우 레이아웃을 가진 탭이 하나 추가된 모습이다.

윈도우 레이아웃이 서로 다른 두 개의 탭

▲ 윈도우 레이아웃이 서로 다른 두 개의 탭

첫 번째 탭은 가로로 분할됐고, 두 번째 탭은 가로와 세로로 나눠졌다.

보다시피 두 탭은 레이아웃이 서로 다르지만 둘 다 똑같은 버퍼(.vimrc.zshrc)를 출력하고 있다.

이제 Vim에서 탭을 쓸 때의 문제로 돌아가 보자.

탭을 잘못 쓰는 문제

탭은 다양한 윈도우 레이아웃을 제공하기 위해 만들어졌다. 탭은 파일이 존재하는 공간이 아니다. 파일은 탭이 아니라 버퍼에 로드된다.

앞에서 본 gif는 이 문제를 보여준다. 똑같은 버퍼를 여러 탭에서 볼 수 있다면, Vim의 탭이 다른 에디터의 일반적인 탭과 어찌 비슷하겠는가?

탭 하나가 버퍼 하나를 가리키도록 강제하는 것은 좋은 방식이 아니다. Vim은 그런 방식으로 동작하지 않는다.

해결책

이 모두를 조화시키고 Vim의 버퍼/윈도우의 효과적인 사용법을 배우려면 버퍼/윈도우만으로 편집하는 법을 이해할 때까지 탭을 쓰지 않는 것이 도움이 될 듯 하다.

버퍼를 사용하는 두 가지 방법을 제시하겠다. 첫번째 방법은 일반 편집기의 탭 기능을 버퍼가 흉내내도록 하는 것이다.

두 번째 방법은 Vim 편집기의 본연에 더 가까운 방법으로, 더 강력한 파워를 가진다.

해결책 1: 탭을 버퍼로 대체

내가 처음 해 본 방법은 모든 버퍼를 화면 상단에 보여주는 플러그인을 설치하는 것이었다. 이걸 해주는 플러그인이 여러 가지 있다.

나는 이미 vim-airline을 쓰고 있었기 때문에 이 플러그인의 기능 중 버퍼 목록을 화면 상단에 출력하는 기능을 켰다. airline의 이 기능을 사용하려면 airline을 설치한 뒤 .vimrc 파일에 다음 내용을 추가한다.

" 버퍼 목록 켜기
let g:airline#extensions#tabline#enabled = 1

" 파일명만 출력
let g:airline#extensions#tabline#fnamemod = ':t'

그러면 이렇게 된다.

모든 버퍼를 보여주는 플러그인

▲ 모든 버퍼를 보여주는 플러그인

그 다음으로 나는 더이상 쓰지 않는 탭 단축키를 교체해야 했다. 이것도 .vimrc 파일을 수정하면 되는 일이었다.

" 이 옵션은 버퍼를 수정한 직후 버퍼를 감춰지도록 한다.
" 이 방법으로 버퍼를 사용하려면 거의 필수다.
set hidden

" 버퍼 새로 열기
" 원래 이 단축키로 바인딩해 두었던 :tabnew를 대체한다.
nmap <leader>T :enew<cr>

" 다음 버퍼로 이동
nmap <leader>l :bnext<CR>

" 이전 버퍼로 이동
nmap <leader>h :bprevious<CR>

" 현재 버퍼를 닫고 이전 버퍼로 이동
" 탭 닫기 단축키를 대체한다.
nmap <leader>bq :bp <BAR> bd #<CR>

" 모든 버퍼와 각 버퍼 상태 출력
nmap <leader>bl :ls<CR>

이렇게 설정하니 일반적인 탭 방식을 Vim에서 쓰는 것과 버퍼를 제대로 이해하고 사용할 때 쓸 수 있는 강력한 기능들을 결합할 수 있었다.

해결책 2: 숨은 버퍼

탭을 흉내낸 첫번째 방법 대신, 어느 버퍼가 열렸는지 걱정할 필요 없이 여러 버퍼를 동시에 열어 작업하는 강력한 기능을 이용해보자.

나는 두 가지 플러그인에서 많은 도움을 얻을 수 있었다. 첫번째 플러그인은 버퍼를 관리하는 훌륭한 방법을 제공하는 Buffergator다. 두번째는 Vim 사용자들 사이에 인기 많은 CtrlP다. 이 플러그인은 파일 퍼지 파인드 기능을 제공한다.

앞서 제시한 해결책처럼 버퍼를 닫거나 가짜 탭을 관리하는 대신, 그냥 CtrlP로 편집할 파일을 열면 되고 버퍼를 닫는 문제나 버퍼를 얼마나 많이 열었는가에 관해서는 신경쓰지 않아도 된다.

파일 편집을 마치면 그냥 저장하고 CtrlP를 열어 다음 파일로 넘어가면 된다.

CtrlP는 퍼지 파인드를 위한 몇 가지 방법을 제공한다. 다음 퍼지 기능을 이용할 수 있다.

  1. 현재 디렉토리에서 찾기
  2. 모든 버퍼에서 찾기
  3. 모든 버퍼에서 찾기 (최근 사용순 정렬)
  4. 위 방법들을 모두 결합한 방식

다음은 내가 유용하게 사용하고 있는 CtrlP 설정이다.

" 기본 무시 설정
let g:ctrlp_custom_ignore = {
  \ 'dir':  '\v[\/](\.(git|hg|svn)|\_site)$',
  \ 'file': '\v\.(exe|so|dll|class|png|jpg|jpeg)$',
\}

" 가장 가까운 .git 디렉토리를 cwd(현재 작업 디렉토리)로 사용
" 버전 관리를 사용하는 프로젝트를 할 때 꽤 적절하다.
" .svn, .hg, .bzr도 지원한다.
let g:ctrlp_working_path_mode = 'r'

" 단축키를 리더 키로 대체
nmap <leader>p :CtrlP<cr>

" 여러 모드를 위한 단축키
nmap <leader>bb :CtrlPBuffer<cr>
nmap <leader>bm :CtrlPMixed<cr>
nmap <leader>bs :CtrlPMRU<cr>

나는 Buffergator를 버퍼들을 정리하는 용도와 저장하는 걸 잊은 경우를 위해 편집한 파일들을 보는 용도로 사용한다.

다음은 내 Buffergator 설정과 단축키 바인딩이다.

" 화면 오른쪽을 사용
let g:buffergator_viewport_split_policy = 'R'

" 단축키를 직접 지정하겠음
let g:buffergator_suppress_keymaps = 1

" 버퍼 돌기 (Looper buffers)
"let g:buffergator_mru_cycle_loop = 1

" 이전 버퍼로 이동
nmap <leader>jj :BuffergatorMruCyclePrev<cr>

" 다음 버퍼로 이동
nmap <leader>kk :BuffergatorMruCycleNext<cr>

" 모든 버퍼 보기
nmap <leader>bl :BuffergatorOpen<cr>

" 위의 첫번재 해결책과 공유하는 단축키 (버퍼 닫기를 뜻함)
nmap <leader>T :enew<cr>
nmap <leader>bq :bp <BAR> bd #<cr>

탭의 올바른 사용

이 글은 탭을 완전히 쓰지 말라는 뜻은 아니다. Vim이 제시하는 방법으로 탭을 쓰자는 것이다.

탭은 윈도우들의 레이아웃을 변경하기 위한 용도로 사용해야 한다. C 프로젝트를 한다고 생각해 보자. 탭 하나는 일반적인 편집용으로 쓰고, 다른 탭 하나는 화면을 세로로 나눠 file.hfile.c 편집하는 용도로 쓴다면 여러 파일을 편집하기에 편리할 것이다.

탭은 여러 작업을 나누는 데도 유용하다. 한 탭에서 프로젝트의 한 부분을 작업하고 다른 탭에서 같은 프로젝트의 다른 부분을 작업할 수 있다.

탭 하나당 파일 하나를 할당하는 방식은 Vim이 의도하는 사용법이 아니라는 것만은 기억해주기 바란다.

버퍼 활용 사례

내가 이 글의 서두에서 주장한 것처럼, 잘못된 방법으로 탭을 쓰는 것보다 버퍼를 쓰는 것이 훨씬 강력하다.

이 점을 보기 위해 예를 들어 본다. 편집할 때 당신이 하는 일이다.

  1. 블로그에 새 글을 쓴다고 생각해보자. 분할 화면 한 쪽에는 base.css 파일을 참고용으로 펼쳐 놓았고, 그 위에는 실제 편집하고 있는 글이 있다.

  2. 그러면 여기서 홈페이지 레이아웃을 수정한다고 해 보자. 탭을 새로 여는(이전의 사고방식) 대신, CtrlP를 이용해 새로운 버퍼에 index.html을 연다.

  3. 이렇게 하면 지금 보고 있는 윈도우가 index.html의 버퍼를 보이도록 전환시킨다. 하단의 윈도우는 건드려지지 않은 채로 계속 base.css를 참고용으로 출력하고 있다.

  4. 레이아웃 편집을 마친 후에는 <leader>bq 를 눌러 포스트 편집으로 돌아간다.

위 과정을 진행한 화면:

버퍼의 활용 사례

▲ 버퍼의 활용 사례

결론

Vim에서 탭을 쓰는 방법은 다른 프로그램과 다르다. 하지만 언제 Vim이 다른 프로그램과 비슷했던 적이 있었던가.

버퍼와 윈도우를 사용하는 방법을 배우고 받아들이면 훨씬 아귀가 맞는 편집 경험을 누릴 수 있으며 탭을 부적절한 방법으로 사용할 때 겪는 여러 가지 어려움을 해결해준다.

이 기사에 대한 의견이나 다른 일반적인 Vim에 관한 의견이 있으면 연락해주기 바란다. 사람들과 대화하는 것을 좋아한다. =]

원문 URL: https://joshldavis.com/2014/04/05/vim-tab-madness-buffers-vs-tabs

원문 초판: 2014-04-05 / 원문 수정: 2014-10-25 / 번역: 2015-08-13