NeoVim: Vim 사용자를 위한 현대적 에디터

NeoVim: Vim 사용자를 위한 현대적 에디터

개발하다 보면 한 번쯤 마우스에서 손을 떼고 싶은 순간이 옵니다. 코드를 쓰다가 파일을 열려고 마우스로 사이드바를 클릭하고, 다시 키보드로 돌아와서 코드를 치고, 또 마우스로 터미널을 클릭하고… 이 왔다 갔다 하는 시간이 쌓이면 생각보다 꽤 거슬리거든요.

NeoVim은 바로 이 불편함을 없애주는 텍스트 에디터입니다. 키보드에서 손을 뗄 필요 없이 파일 편집, 검색, 탐색을 전부 할 수 있죠. “그냥 Vim 아닌가?” 싶으실 수 있는데, NeoVim은 Vim을 뿌리로 두되 현대 개발 환경에 맞게 새로 설계된 에디터예요.

이 글에서는 NeoVim을 처음 접하는 분들을 위해 설치부터 기본 사용법, 그리고 일상적인 코딩에 활용하는 방법까지 다뤄보겠습니다.

NeoVim은 왜 만들어졌을까

vi(1976)에서 시작된 모드 기반 편집의 역사와 Vim(1991)이 어떻게 발전해왔는지는 Vim 완벽 가이드에서 자세히 다루고 있으니 여기서는 NeoVim의 등장 배경만 짚어보겠습니다.

Vim은 수십 년간 사랑받았지만 세월이 쌓이면서 한계가 드러나기 시작했습니다. 비동기 처리가 안 되고, 플러그인 시스템이 제한적이며, 기여하기 어려운 레거시 코드가 잔뜩 쌓여 있었죠.

NeoVim은 2014년에 이런 한계를 극복하기 위해 Vim을 포크(fork)해서 시작된 프로젝트입니다. 뭐가 바뀌었느냐면요.

가장 눈에 띄는 건 Lua를 내장 스크립팅 언어로 채택한 겁니다. 설정과 플러그인을 훨씬 빠르고 직관적으로 작성할 수 있게 됐어요. Vim의 VimScript도 여전히 쓸 수 있지만 요즘 나오는 플러그인은 대부분 Lua로 작성되고 있습니다.

비동기 작업도 기본 지원하기 때문에 LSP(Language Server Protocol)와의 연동이 매끄럽습니다. 코드 자동 완성, 정의로 이동, 리네이밍 같은 IDE급 기능을 별도의 무거운 프로그램 없이 쓸 수 있게 된 거죠.

내장 터미널도 제공해서 에디터를 벗어나지 않고 명령어를 실행할 수 있고요. tmux나 Zellij 같은 터미널 멀티플렉서와 조합하면 마우스 없이 개발 환경을 갖출 수 있습니다.

NeoVim 설치

macOS에서는 Homebrew로 간편하게 설치할 수 있습니다.

$ brew install neovim

Ubuntu/Debian 계열 리눅스에서는 apt로 설치할 수 있는데, 저장소 버전이 오래된 경우가 많아서 최신 버전을 쓰려면 PPA를 추가하는 편이 낫습니다.

$ sudo add-apt-repository ppa:neovim-ppa/unstable
$ sudo apt update
$ sudo apt install neovim

Arch 리눅스라면 간단하게 pacman으로 됩니다.

$ sudo pacman -S neovim

설치가 끝나면 터미널에서 nvim을 입력해보세요.

$ nvim

빈 화면에 커서가 깜빡이고 있으면 성공입니다. 당황하지 마세요. 원래 이렇게 생겼습니다. 😅

혹시 “이걸 어떻게 끄지?”가 첫 번째 생각이라면 :q를 입력하고 Enter를 누르면 됩니다. Vim/NeoVim을 종료하는 방법은 프로그래밍 세계에서 유명한 밈이기도 하죠.

Vim 기본기 빠르게 복습

NeoVim의 편집 방식은 Vim에서 물려받은 것입니다. 모드 전환, hjkl 이동, 동사+명사 조합, 검색/치환, 버퍼와 화면 분할 같은 기본기는 Vim 완벽 가이드에서 자세히 다루고 있어요.

여기서는 NeoVim을 쓸 때 특히 알아두면 좋은 것들만 짚어보겠습니다.

Vim 사용자를 위한 NeoVim 차이점

Vim을 쓸 줄 아는데 NeoVim을 처음 접한다면 이 부분부터 보시면 됩니다.

실행 명령어가 다릅니다. Vim은 vim으로 실행하지만 NeoVim은 nvim입니다. 셸에 alias vim=nvim을 추가해두면 기존 습관 그대로 쓸 수 있어요.

설정 파일의 위치와 언어가 다릅니다. Vim은 ~/.vimrc에 VimScript로 설정을 작성하지만, NeoVim은 ~/.config/nvim/init.lua에 Lua로 작성합니다. Lua가 VimScript보다 빠르고 범용적인 언어라서 설정과 플러그인 작성이 훨씬 수월해요. 기존 .vimrc가 있다면 NeoVim에서도 set runtimepath^=~/.vim으로 불러올 수 있지만, 장기적으로는 Lua로 마이그레이션하는 게 좋습니다.

기본 옵션이 더 현대적입니다. Vim에서는 .vimrc에 직접 넣어야 했던 옵션들(구문 강조, 자동 들여쓰기, 백스페이스 동작, 증분 검색 등)이 NeoVim에서는 기본으로 켜져 있어요. 빈 설정 파일로 시작해도 어느 정도 쾌적합니다.

내장 튜토리얼이 에디터 안에 있습니다. Vim은 터미널에서 vimtutor 명령어를 별도로 실행해야 하지만, NeoVim은 에디터를 켠 상태에서 :Tutor를 입력하면 바로 인터랙티브 튜토리얼이 시작됩니다.

LSP가 기본 내장되어 있습니다. Vim에서 자동 완성이나 코드 진단을 쓰려면 coc.nvim 같은 무거운 플러그인이 필요했는데, NeoVim은 LSP 클라이언트가 코어에 포함되어 있어서 가볍게 설정할 수 있습니다.

설정 파일 시작하기

NeoVim의 설정 파일은 ~/.config/nvim/init.lua에 위치합니다. 이 파일이 NeoVim을 켤 때마다 자동으로 실행되는데, 여기에 원하는 옵션을 적어두면 됩니다.

파일이 없으면 직접 만들어야 합니다.

$ mkdir -p ~/.config/nvim
$ nvim ~/.config/nvim/init.lua

기본적인 설정부터 시작해볼까요?

-- 줄 번호 표시
vim.opt.number = true
vim.opt.relativenumber = true

-- 들여쓰기 설정
vim.opt.tabstop = 2
vim.opt.shiftwidth = 2
vim.opt.expandtab = true

-- 검색 설정
vim.opt.ignorecase = true
vim.opt.smartcase = true
vim.opt.hlsearch = true

-- 시스템 클립보드 연동
vim.opt.clipboard = "unnamedplus"

-- 커서 라인 강조
vim.opt.cursorline = true

-- 스크롤할 때 위아래 여백 유지
vim.opt.scrolloff = 8

relativenumber를 켜두면 현재 줄 기준으로 상대적인 줄 번호가 표시됩니다. 5j(5줄 아래로 이동) 같은 명령어를 쓸 때 몇 줄 떨어져 있는지 바로 보여서 편리해요.

smartcase는 검색어에 대문자가 포함되어 있을 때만 대소문자를 구분하는 옵션입니다. 소문자로만 검색하면 대소문자 무시, 대문자가 섞여 있으면 정확히 일치하는 것만 찾아줍니다.

clipboard = "unnamedplus"를 설정해두면 NeoVim에서 y로 복사한 텍스트를 다른 프로그램에서 Cmd+V로 바로 붙여넣을 수 있습니다. 이거 안 해두면 NeoVim 내부 클립보드와 시스템 클립보드가 따로 놀아서 처음에 많이 혼란스러워요.

키 매핑 설정

NeoVim의 큰 장점 중 하나는 키 매핑을 자유자재로 바꿀 수 있다는 점입니다. init.lua에 이런 식으로 추가하면 돼요.

-- Leader 키를 스페이스바로 설정
vim.g.mapleader = " "

-- 파일 저장
vim.keymap.set("n", "<leader>w", ":w<CR>")

-- 창 이동을 좀 더 편하게
vim.keymap.set("n", "<C-h>", "<C-w>h")
vim.keymap.set("n", "<C-j>", "<C-w>j")
vim.keymap.set("n", "<C-k>", "<C-w>k")
vim.keymap.set("n", "<C-l>", "<C-w>l")

-- 줄 이동
vim.keymap.set("v", "J", ":m '>+1<CR>gv=gv")
vim.keymap.set("v", "K", ":m '<-2<CR>gv=gv")

-- 검색 후 하이라이트 끄기
vim.keymap.set("n", "<leader>h", ":nohlsearch<CR>")

Leader 키는 NeoVim에서 사용자 정의 단축키의 시작점 역할을 합니다. 스페이스바로 설정해두면 스페이스+w로 파일 저장, 스페이스+h로 검색 하이라이트 끄기 같은 식으로 쓸 수 있습니다. 이렇게 하면 NeoVim의 기본 키 바인딩과 충돌하지 않으면서 자기만의 단축키를 만들 수 있어요.

Ctrl+h/j/k/l로 창 이동하는 매핑은 거의 모든 NeoVim 사용자가 쓸 정도로 보편적입니다. Ctrl+w를 매번 누르는 것보다 훨씬 빠르거든요.

Visual 모드에서 JK로 선택한 줄을 위아래로 옮기는 매핑도 코딩할 때 자주 쓰게 됩니다. VSCode에서도 Alt+Up/Down으로 줄을 이동하는 기능이 있는데, NeoVim에서는 이렇게 직접 설정하는 거죠.

플러그인으로 확장하기

NeoVim 자체만으로도 쓸 만하지만, 플러그인을 설치하면 아예 다른 에디터가 됩니다. 플러그인 매니저로는 현재 lazy.nvim이 가장 널리 쓰이고 있어요.

lazy.nvim은 플러그인을 필요할 때만 로딩(lazy loading)해서 NeoVim 시작 속도를 빠르게 유지해줍니다. 설치는 init.lua에 부트스트랩 코드를 추가하면 됩니다.

-- lazy.nvim 부트스트랩
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
  vim.fn.system({
    "git", "clone", "--filter=blob:none",
    "https://github.com/folke/lazy.nvim.git",
    "--branch=stable",
    lazypath,
  })
end
vim.opt.rtp:prepend(lazypath)

-- 플러그인 설정
require("lazy").setup({
  -- 컬러 스킴
  {
    "catppuccin/nvim",
    name = "catppuccin",
    priority = 1000,
    config = function()
      vim.cmd.colorscheme("catppuccin")
    end,
  },
  -- 파일 탐색기
  {
    "nvim-tree/nvim-tree.lua",
    dependencies = { "nvim-tree/nvim-web-devicons" },
    config = function()
      require("nvim-tree").setup()
      vim.keymap.set("n", "<leader>e", ":NvimTreeToggle<CR>")
    end,
  },
  -- 퍼지 파인더
  {
    "nvim-telescope/telescope.nvim",
    dependencies = { "nvim-lua/plenary.nvim" },
    config = function()
      local builtin = require("telescope.builtin")
      vim.keymap.set("n", "<leader>ff", builtin.find_files)
      vim.keymap.set("n", "<leader>fg", builtin.live_grep)
    end,
  },
})

이 설정만으로도 세 가지 핵심 기능이 추가됩니다.

catppuccin은 눈이 편한 컬러 스킴인데, NeoVim의 기본 색상이 좀 투박하기 때문에 컬러 스킴을 하나 깔아두는 걸 추천합니다.

nvim-tree는 VSCode의 사이드바 파일 탐색기와 비슷한 역할을 합니다. 스페이스+e로 토글할 수 있어서 필요할 때만 열고 닫으면 됩니다.

telescope는 VSCode의 Command Palette와 비슷한 퍼지 파인더입니다. 스페이스+ff로 파일 이름 검색, 스페이스+fg로 파일 내용 검색을 할 수 있어요. 프로젝트 내에서 원하는 파일이나 코드를 찾을 때 정말 빠릅니다.

LSP로 IDE처럼 쓰기

LSP(Language Server Protocol)는 에디터와 프로그래밍 언어 서버 사이의 통신 규약입니다. NeoVim에 LSP를 설정하면 코드 자동 완성, 에러 표시, 정의로 이동, 타입 정보 확인 같은 IDE급 기능을 쓸 수 있게 됩니다.

직접 LSP 서버를 하나씩 설정하면 꽤 번거로운데, mason.nvim이라는 플러그인이 이 과정을 크게 단순화해줍니다.

-- lazy.nvim의 플러그인 목록에 추가
{
  "williamboman/mason.nvim",
  config = function()
    require("mason").setup()
  end,
},
{
  "williamboman/mason-lspconfig.nvim",
  config = function()
    require("mason-lspconfig").setup({
      ensure_installed = {
        "lua_ls",       -- Lua
        "ts_ls",        -- TypeScript
        "pyright",      -- Python
        "rust_analyzer", -- Rust
      },
    })
  end,
},
{
  "neovim/nvim-lspconfig",
  config = function()
    local lspconfig = require("lspconfig")
    local servers = { "lua_ls", "ts_ls", "pyright", "rust_analyzer" }
    for _, server in ipairs(servers) do
      lspconfig[server].setup({})
    end

    -- LSP 키 매핑
    vim.keymap.set("n", "gd", vim.lsp.buf.definition)
    vim.keymap.set("n", "K", vim.lsp.buf.hover)
    vim.keymap.set("n", "<leader>rn", vim.lsp.buf.rename)
    vim.keymap.set("n", "<leader>ca", vim.lsp.buf.code_action)
  end,
},

mason.nvim은 :Mason 명령어를 실행하면 GUI 화면이 나타나서 언어 서버를 검색하고 설치할 수 있습니다. mason-lspconfig는 Mason으로 설치한 서버를 NeoVim의 LSP 클라이언트와 자동 연결해줍니다.

이 설정이 되면 gd로 함수 정의로 바로 이동하고, K로 커서 아래 심볼의 타입 정보를 확인하고, 스페이스+rn으로 변수 이름을 프로젝트 전체에서 한번에 바꿀 수 있습니다.

배워야 할 게 너무 많다고 느껴질 때

솔직히 NeoVim의 학습 곡선은 가파릅니다. 처음 며칠은 오히려 생산성이 떨어지는 게 당연하고요. 여기서 포기하는 분들이 많은데, 몇 가지 팁을 드리자면요.

우선 모든 걸 한 번에 배우려고 하지 마세요. 처음에는 i로 입력 모드 들어가서 글 쓰고, Esc로 나오고, :w로 저장하고, :q로 종료하는 것만 하면 됩니다. 여기에 hjkl 이동이 익숙해지면 w, b, dd, yy, p 정도를 추가하고요. 이틀에 명령어 하나씩 추가하는 속도가 적당합니다.

NeoVim에 내장된 튜토리얼도 큰 도움이 됩니다. 터미널에서 nvim을 실행한 다음 :Tutor를 입력하면 인터랙티브 튜토리얼이 시작돼요. 30분 정도면 기본적인 이동과 편집을 실습할 수 있습니다.

그리고 처음부터 설정을 직접 짜려고 하면 에디터 설정하느라 코딩은 못 하는 상황이 벌어질 수 있습니다. kickstart.nvim이라는 최소한의 스타터 설정을 받아서 시작하는 것도 좋은 방법입니다. LSP, 자동 완성, 파일 탐색 같은 기본적인 것들이 미리 설정되어 있어서 바로 코딩에 쓸 수 있고, 코드를 읽으면서 NeoVim 설정을 자연스럽게 배울 수 있어요.

마치며

NeoVim은 진입 장벽이 높은 편이지만 그만큼 보상도 확실합니다. 키보드에서 손을 떼지 않는 편집 흐름에 한번 익숙해지면 다른 에디터가 답답하게 느껴질 정도예요.

Vim의 기본 조작법(모드 전환, hjkl 이동, 동사+명사 조합 등)이 아직 낯설다면 Vim 완벽 가이드부터 읽어보는 것도 좋습니다.

이 글에서 다룬 내용만으로도 기본적인 코딩은 충분히 할 수 있습니다. 여기서 더 나아가고 싶다면 Treesitter(구문 강조), 자동 완성(nvim-cmp), Git 연동(gitsigns.nvim) 같은 플러그인을 하나씩 추가해보세요. 플러그인을 하나씩 설정하는 게 번거롭다면 NvChad를 써보는 것도 좋습니다. 설치 한 줄이면 예쁜 UI와 실용적인 플러그인 구성이 한 번에 갖춰져서, 바로 코딩에 집중할 수 있거든요.

터미널 기반 개발 환경에 관심이 있다면 Zellij와 함께 쓰는 걸 추천합니다. NeoVim으로 코드를 편집하면서 Zellij로 터미널을 분할해서 빌드, 테스트, Git 작업을 동시에 하면 마우스 없이도 쾌적한 개발 환경이 만들어져요.

터미널이 아닌 GUI 에디터에서 Vim 모드를 쓰고 싶다면 Rust로 만들어진 Zed 에디터도 살펴보세요. Vim 모드를 기본 지원하면서 GPU 가속으로 빠릿빠릿하고 AI 기능까지 내장되어 있습니다.

더 자세한 내용은 NeoVim 공식 문서kickstart.nvim 저장소를 참고하세요.

This work is licensed under CC BY 4.0 CC BY

Discord