이 글은 Neovim 시리즈의 다섯 번째 글이다.

  1. Neovim 입문: Vim을 넘어서는 첫걸음
  2. Neovim 중급: 생산성을 높이는 기능들
  3. Neovim 고급: 플러그인과 LSP로 IDE처럼 쓰기
  4. 나의 Neovim 설정 전체 공개
  5. LazyVim distro로 갈아타기 ← 현재 글

함께 읽기: LazyVim 키맵 치트시트


들어가며

플러그인 23개를 직접 큐레이션해서 1년 가까이 굴렸지만, 결국 LazyVim distro로 갈아탔다. 늘어난 건 플러그인 수(23 → 42)지만 줄어든 건 내가 직접 관리해야 하는 파일(15 → 5)이다. 이 비대칭이 distro의 핵심이다.

직전 셋업 공개 글에서 정리했던 lazy.nvim 수동 구성은 잘 동작했다. 다만 새 언어 LSP 하나 붙일 때마다 mason 설정·conform 포매터·nvim-cmp 소스를 손으로 동기화해야 했고, 새 머신에 그대로 옮길 때마다 의존성 누락이 한두 개씩 났다. distro는 그 동기화를 일괄로 위임하고, 내 영역은 “취향 차이가 나는 부분"에만 남기는 구조다.

이 글은 LazyVim이라는 distro가 무엇이고, 수동 셋업에서 어떤 흐름으로 옮겼고, 어디에 백업을 두고 어떻게 롤백할 수 있는지를 정리한다.


distro란 무엇인가

Neovim distro는 lazy.nvim·LSP·treesitter·자동완성·UI 같은 표준 기반을 한 묶음으로 깔아주고, 사용자는 그 위에 얇게 커스텀만 얹는 셋업 패턴이다. 직접 lua 파일을 한 줄 한 줄 짜는 대신, 프레임워크가 정해 둔 슬롯에 옵션이나 추가 spec만 끼워 넣으면 된다.

distro분위기
LazyVim가장 표준적·미니멀. lazy.nvim 작성자가 직접 운영. 본 글 대상
LunarVim자체 CLI(lvim)를 가진 비교적 무거운 셋업
NvChadUI·테마 중심, 화려한 시작 화면이 특징
AstroNvim대시보드·아이콘·통계 정보가 많은 풍성한 셋업

LazyVim을 고른 이유는 단순하다. 이미 쓰던 lazy.nvim 위에 그대로 얹히고, 빠지더라도 ~/.config/nvim을 통째로 갈아엎지 않아도 되는 구조라서다. distro 자체가 lazy 플러그인 하나처럼 동작한다.


직전 상태 — 수동 lazy.nvim 23 플러그인

자세한 구성은 나의 Neovim 설정 전체 공개 글에 있다. 요약하면:

  • init.lua 1줄 → lua/config/에서 globals/options/keymaps 분리 로드
  • lua/plugins/ 아래 플러그인별 파일 15개 (telescope, neo-tree, lsp, cmp, treesitter, conform, kanagawa 등)
  • 자체 작성한 keyMapper 유틸로 noremap=true silent=true 일괄 적용
  • 테마는 Kanagawa Dragon (저채도 다크)

문제는 없었다. 단지 새 언어 추가가 매번 작은 의식이었다. Go를 붙이려면 mason.nvim에 gopls를 추가하고, conform.nvim에 gofmt를 등록하고, nvim-lspconfig 호출 라인을 늘리고, treesitter parser 목록도 손봐야 했다. 그렇게 해 둔 걸 새 노트북에 옮기면 :checkhealth 빨간 줄이 한두 개 떴다.


LazyVim이 자동으로 가져오는 것

LazyVim 15.x를 깔면 다음이 한 번에 따라온다.

영역들어오는 것
플러그인 매니저lazy.nvim
파일 탐색·검색snacks.picker, snacks.dashboard, neo-tree
키 안내which-key
LSP·포매터·린터nvim-lspconfig + mason 자동 설치
자동완성blink.cmp (또는 nvim-cmp 옵션)
구문 파싱nvim-treesitter
Gitgitsigns, lazygit 연동
UIbufferline, lualine, noice, mini.icons
포매팅conform.nvim + format-on-save

여기에 내가 켠 LazyExtras 6종(go, typescript, markdown, json, yaml, python)이 마저 붙는다. 합쳐 42개. 직접 관리할 필요는 없고, 동작에 손대고 싶으면 같은 spec을 opts만 덮어씌우는 식으로 가볍게 끼어든다.

핵심은 “내가 짠 파일이 5개 남았다"는 것이다. 나머지는 distro 본체가 가져간 책임이다.


백업과 롤백 안전망

distro 전환은 비가역 작업이 아니어야 한다. Neovim의 상태는 네 군데에 흩어져 있어서, 그걸 다 같이 빼두지 않으면 깔끔한 롤백이 어렵다.

기존 nvim 상태 4종을 .backup-2026-05-07 suffix로 옮긴 뒤 새 LazyVim을 깔았다.

원본백업
~/.config/nvim~/.config/nvim.backup-2026-05-07
~/.local/share/nvim (164MB, 컴파일된 플러그인)~/.local/share/nvim.backup-2026-05-07
~/.local/state/nvim~/.local/state/nvim.backup-2026-05-07
~/.cache/nvim~/.cache/nvim.backup-2026-05-07

문제 생겼을 때 롤백은 4쌍을 역순으로 mv하면 된다. 새 LazyVim을 같은 suffix로 옮긴 뒤 백업을 원래 자리로:

DATE=2026-05-07
mv ~/.config/nvim       ~/.config/nvim.lazyvim-$DATE
mv ~/.local/share/nvim  ~/.local/share/nvim.lazyvim-$DATE
mv ~/.local/state/nvim  ~/.local/state/nvim.lazyvim-$DATE
mv ~/.cache/nvim        ~/.cache/nvim.lazyvim-$DATE

mv ~/.config/nvim.backup-$DATE       ~/.config/nvim
mv ~/.local/share/nvim.backup-$DATE  ~/.local/share/nvim
mv ~/.local/state/nvim.backup-$DATE  ~/.local/state/nvim
mv ~/.cache/nvim.backup-$DATE        ~/.cache/nvim

이 안전망이 있어야 distro 전환을 부담 없이 시도해볼 수 있다.


새 디렉토리 구조

~/.config/nvim/
├── init.lua                 # LazyVim 부트스트랩 (starter 그대로)
├── lua/
│   ├── config/
│   │   ├── options.lua      # 사용자 추가: scrolloff=10
│   │   ├── keymaps.lua      # 사용자 추가: <leader>h, <C-;>
│   │   ├── autocmds.lua     # 사용자 추가: 마크다운 wrap/linebreak/spell=false 등
│   │   └── lazy.lua         # LazyVim 부트스트랩 (수정 X)
│   └── plugins/
│       ├── colorscheme.lua  # 신규: Solarized + Everforest + Gruvbox Material
│       ├── markdown.lua     # 신규: render-markdown.nvim 옵션 강화
│       ├── ufo.lua          # 신규: nvim-ufo (LSP 폴딩)
│       ├── floaterm.lua     # 신규: vim-floaterm + <C-;>
│       ├── lang-extras.lua  # 신규: LazyExtras 6종 일괄 import
│       └── example.lua      # starter 동봉 예제 (`if true then return {} end`로 비활성)
├── lazyvim.json             # LazyVim 자동 생성
├── lazy-lock.json           # lazy.nvim이 잠금 관리
└── stylua.toml              # starter 동봉 (lua 포매터 설정)

config/는 LazyVim의 starter 템플릿이 깔아준 그대로다. 사용자 영역은 plugins/ 아래 5개 파일 + config/의 keymaps/options/autocmds 추가분. 그게 전부다.


커스텀 5개 플러그인 파일

distro가 가져가지 않은 “내 취향"은 다섯 갈래로 정리됐다.

lua/plugins/colorscheme.lua — 테마 후보 3종 동시 등록

직전엔 Kanagawa Dragon 단일 테마였는데, 마크다운 작성 비중이 늘면서 헤딩 위계와 코드블록 배경이 더 또렷한 테마가 필요해졌다. 즉시 비교를 위해 셋을 같이 등록했다.

  • maxmx03/solarized.nvim (variant=winter) — 기본
  • neanias/everforest-nvim (background=soft)
  • sainnhe/gruvbox-material (background=medium)

런타임에 :colorscheme everforest처럼 즉시 갈아끼울 수 있고, 영구화는 LazyVim 기본 colorscheme 라인을 바꾸면 된다. UI에서 라이브 프리뷰로 고르고 싶으면 <Space>uC.

lua/plugins/markdown.lua — render-markdown.nvim 옵션 강화

LazyExtras lang.markdown이 이미 render-markdown.nvim의 spec을 등록한다. 거기에 opts만 덮어씌워 가독성 옵션을 강화했다.

return {
  {
    "MeanderingProgrammer/render-markdown.nvim",
    opts = {
      heading = {
        sign = false,
        icons = { "◉ ", "○ ", "✸ ", "✿ ", "✤ ", "✜ " },
        backgrounds = {
          "RenderMarkdownH1Bg", "RenderMarkdownH2Bg",
          "RenderMarkdownH3Bg", "RenderMarkdownH4Bg",
          "RenderMarkdownH5Bg", "RenderMarkdownH6Bg",
        },
      },
      code = {
        style = "full",
        position = "left",
        width = "block",
        left_pad = 2,
      },
      quote = { icon = "┃" },
      bullet = { icons = { "●", "○", "◆", "◇" } },
      checkbox = {
        unchecked = { icon = "󰄱 " },
        checked = { icon = "󰱒 " },
      },
      pipe_table = { style = "full", alignment_indicator = "━" },
      link = { image = "󰥶 ", hyperlink = "󰌹 " },
    },
  },
}
옵션효과
heading.iconsH1~H6 아이콘으로 위계 구분
heading.backgrounds헤딩 줄 전체 배경 틴트 (테마의 RenderMarkdownH* highlight 그룹 위임)
code.style = "full"코드블록 전체 배경 + 좌측 언어 라벨
code.width = "block"코드블록 너비를 본문보다 좁게 (들여쓰기 효과)
quote.icon인용문 좌측 세로바
bullet.icons리스트 깊이별 글리프 (● ○ ◆ ◇)
checkbox[ ]/[x]를 Nerd Font 글리프로
pipe_table.style = "full"표 경계 전체 표시

색상은 테마의 highlight 그룹에 위임했기 때문에 colorscheme를 바꿔도 헤딩 틴트가 자동으로 따라온다.

lua/plugins/ufo.lua — LSP 인지 폴딩

nvim-ufo. foldcolumn=0, foldlevel=99로 기본은 모두 펼친 상태로 두고, 필요할 때만 zc/zo로 접고 편다.

lua/plugins/floaterm.lua<C-;> 토글

LazyVim 기본 <C-/> snacks.terminal과 별개로, 손에 익은 floaterm을 같이 붙였다. <C-;>로 토글. 둘이 충돌하지 않고 병존한다.

lua/plugins/lang-extras.lua — LazyExtras 일괄 활성화

return {
  { import = "lazyvim.plugins.extras.lang.go" },
  { import = "lazyvim.plugins.extras.lang.typescript" },
  { import = "lazyvim.plugins.extras.lang.markdown" },
  { import = "lazyvim.plugins.extras.lang.json" },
  { import = "lazyvim.plugins.extras.lang.yaml" },
  { import = "lazyvim.plugins.extras.lang.python" },
}

이 한 파일이 mason에게 marksman·gopls·ts_ls·pyright·ruff·jsonls·yamlls를 자동 설치하도록 위임한다. 직전 셋업에서 손으로 동기화하던 그 영역이다.


사용자 영역 추가

keymaps (config/keymaps.lua)

LazyVim 기본 키맵으로 이미 커버되는 건 이식하지 않았다. 기존에 손에 박힌 두 개만 살렸다.

동작
<leader>hsearch highlight 끄기
<C-;>floaterm 토글

이미 LazyVim이 잡아주는 것: <leader>e neo-tree, <C-h/j/k/l> 패인 이동, < > visual indent stay, <leader>ff 파일 찾기 등. 전체는 LazyVim 키맵 치트시트 참고.

마크다운 filetype 동작 (config/autocmds.lua)

vim.api.nvim_create_autocmd("FileType", {
  pattern = "markdown",
  callback = function()
    vim.opt_local.wrap = true
    vim.opt_local.linebreak = true
    vim.opt_local.conceallevel = 2
    vim.opt_local.spell = false
    vim.opt_local.cursorline = true
    vim.opt_local.signcolumn = "no"
  end,
})
옵션효과
wrap = true한글 긴 줄 자동 래핑
linebreak = true단어 경계에서만 래핑 (어절 중간 잘림 방지)
conceallevel = 2마크업 문자(**, # 등) 숨김 (실제로는 render-markdown이 3으로 덮어씀 — 더 강한 숨김. 의도된 동작)
spell = false한글 문서에서 영어 spell 체크 끔
cursorline = true현재 줄 강조 (긴 문서 위치 추적)
signcolumn = "no"좌측 여백 줄여 본문 폭 확보

클립보드는 별도 설정 없음

비주얼 모드에서 y만 눌러도 macOS 시스템 클립보드로 복사된다. LazyVim 15.x가 clipboard=unnamedplus를 기본값으로 잡아주기 때문이다.

직전 수동 셋업에서는 내 setup 글에 적었듯 opt.clipboard = "unnamedplus" 한 줄을 직접 박았어야 했는데, distro 전환 후엔 이 줄도 지웠다. + 레지스터(시스템 클립보드)와 무명 레지스터(")가 자동 연결돼서 y/p가 양방향 동기화된다.

확인:

:set clipboard?

clipboard=unnamedplus 출력되면 OK.

provider 레벨 진단:

:checkhealth provider

또는 직접:

:let @+ = 'test'

→ 다른 앱에서 Cmd+V 했을 때 test가 붙으면 provider 정상.

tmux 안에서만 안 될 때는 ~/.tmux.conf에 OSC 52 전달 설정이 필요할 수 있다.

set -g set-clipboard on

macOS 로컬 tmux + pbcopy 조합은 보통 이 설정 없이도 동작한다. SSH 원격 nvim에서 OSC 52 핸들링이 깨지는 환경이라면 LazyVim 기본값을 의도적으로 끄고 싶을 수 있다 — options.luavim.opt.clipboard = "".


의존성 (brew 설치)

LazyVim 본체와 무관하게 PATH에 있어야 하는 외부 도구.

도구용도
ripgrep빠른 grep (snacks.picker <leader>sg)
fd빠른 파일 찾기 (snacks.picker <leader>ff)
lazygit<leader>gg git TUI
node, npmLSP 서버들 (ts_ls, yamlls 등)
python3pynvim, mason 도구

mason이 자동 설치하는 도구는 처음 해당 언어 파일을 열 때 받아온다: marksman, gopls, ts_ls, pyright, ruff, jsonls, yamlls, lua_ls, markdownlint-cli2, prettier, stylua, gofumpt, goimports, golangci-lint, shfmt 등.


검증 결과

항목결과
Lazy sync통과 (42개 플러그인 설치)
세 colorscheme 로드통과 (solarized, everforest, gruvbox-material)
마크다운 autocmd 적용통과 (ft=markdown wrap=true cole=3 spell=false)
nvim startup 에러없음

전부 첫 실행에 떨어졌다. 백업해 둔 .backup-2026-05-07은 한 달 정도 묵혀 두고, 회귀 없으면 정리할 예정.


사용 팁

  • <Space> 누르고 1초 대기 → which-key가 카테고리별 메뉴를 띄운다. 가장 빠른 키맵 학습 방법
  • :LazyExtras → 추가 언어팩 ON/OFF UI
  • :Mason → LSP/포매터/린터 설치 상태
  • :LazyHealth, :checkhealth → 의존성·문제 진단
  • :colorscheme <name>으로 테마 즉시 전환. 영구화는 lua/plugins/colorscheme.lua 마지막 블록의 colorscheme = "..." 변경
  • :RenderMarkdown toggle — 렌더링을 잠깐 끄고 원본 마크다운(**bold**, # H1)을 보고 싶을 때

정리

수동 lazy.nvim 셋업은 잘 동작했고, 그 자체로 충분히 좋았다. 다만 “내가 직접 관리해야 하는 것"의 표면적이 넓을수록 새 머신·새 언어를 붙일 때마다 작은 의식이 늘어났다. distro는 그 표면적을 줄여준다 — 자동으로 처리될 수 있는 영역(LSP 자동완성·포매팅·치트시트·Git UI)을 일괄로 위임하고, 사용자는 “취향 차이가 나는 부분"에만 집중한다.

LazyVim의 좋은 점은 lazy.nvim 위에 그대로 얹혀 있다는 것이다. 빠지더라도 ~/.config/nvim을 통째로 갈아엎지 않아도 되고, 위 백업 절차로 언제든 직전 상태로 돌아올 수 있다. 그 안전망 위에서 가볍게 시도해볼 만한 전환이었다.

키맵은 별도 글로 분리했다 — LazyVim 키맵 치트시트.


참고