C.W.K.
Stream
Lesson 01 of 04 · published

nvim-cmp (또는 blink.cmp) 와 함께 auto-completion

~14 min · neovim, completion, lsp

Level 0갇힌 자
0 XP0/35 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

왜 completion 엔진이 중요해

Native LSP 가 데이터 줘: "여기 가능한 심볼들이고, 이 시그니처와 함께." Completion 엔진이 그 데이터 가져다가 사용 가능한 팝업으로 표시 — 제안 ranking, 스니펫 expand, buffer 단어와 파일 경로 통합, tab 동작 처리. Neovim 이 2026 에 두 강한 옵션 가져:

  • nvim-cmp — 오랜 기본. 성숙, 거대한 plugin 생태계, 많은 source plugin.
  • blink.cmp — 더 새로움 (2024+), Rust 백엔드, 더 빠르고 단순하게 디자인. 빠르게 parity 따라잡고 있음. 시작-perf 중요하면 시도 가치 있음.

이 레슨은 nvim-cmp 사용 — 한 번 설정하고 잊을 거면 더 안전한 선택. 나중에 blink.cmp 로 마이그레이션은 직관적; spec 모양 비슷.

뭘 와이어업해

  • Completion 엔진 자체.
  • Source — LSP, buffer 단어, 파일 경로, 스니펫.
  • 스니펫 expander (LuaSnip).
  • 팝업 안 키 매핑 (Tab 으로 navigate, Enter 로 confirm, Esc 로 dismiss).
  • 클라이언트가 뭘 지원하는지 LSP 서버에 알리는 capabilities 객체 — 스니펫 completion, auto-import 등 활성화.

정신 모델

Completion 이 각 source 의 candidate 의 정렬, 필터, ranking 된 merge. nvim-cmp 가 매 source 쿼리, 제안 받음, ranking 룰 적용, 팝업 표시. 각 source 가 독립적 — Markdown 파일에 buffer 단어 비활성화, Python 파일에 LSP 우선 등.

LSP source 먼저 믿어. Buffer-단어 completion 이 산문에 좋지만 코드에 noisy; LSP 인식 제안이 type, scope, import 알아. 소스 파일에 LSP 를 buffer 위로 ranking; Markdown / commit message 에 역. nvim-cmp 의 filetype 별 config 가 이걸 인코드하는 방법.

Code

nvim-cmp 풀 셋업 — lazy.nvim spec 에 붙여·lua
{
  "hrsh7th/nvim-cmp",
  event = "InsertEnter",
  dependencies = {
    "hrsh7th/cmp-nvim-lsp",     -- LSP source
    "hrsh7th/cmp-buffer",       -- buffer-단어 source
    "hrsh7th/cmp-path",         -- 파일시스템-경로 source
    "L3MON4D3/LuaSnip",         -- 스니펫 엔진
    "saadparwaiz1/cmp_luasnip", -- 스니펫 source
    "rafamadriz/friendly-snippets", -- 언어별 prebuilt 스니펫
  },
  config = function()
    local cmp = require("cmp")
    local luasnip = require("luasnip")
    require("luasnip.loaders.from_vscode").lazy_load()

    cmp.setup({
      snippet = {
        expand = function(args) luasnip.lsp_expand(args.body) end,
      },
      mapping = cmp.mapping.preset.insert({
        ["<C-b>"] = cmp.mapping.scroll_docs(-4),
        ["<C-f>"] = cmp.mapping.scroll_docs(4),
        ["<C-Space>"] = cmp.mapping.complete(),
        ["<C-e>"] = cmp.mapping.abort(),
        ["<CR>"]  = cmp.mapping.confirm({ select = true }),
        ["<Tab>"] = cmp.mapping(function(fallback)
          if cmp.visible() then
            cmp.select_next_item()
          elseif luasnip.expand_or_jumpable() then
            luasnip.expand_or_jump()
          else
            fallback()
          end
        end, { "i", "s" }),
        ["<S-Tab>"] = cmp.mapping(function(fallback)
          if cmp.visible() then
            cmp.select_prev_item()
          elseif luasnip.jumpable(-1) then
            luasnip.jump(-1)
          else
            fallback()
          end
        end, { "i", "s" }),
      }),
      sources = cmp.config.sources({
        { name = "nvim_lsp", priority = 1000 },
        { name = "luasnip",  priority = 750 },
      }, {
        { name = "buffer", priority = 500 },
        { name = "path",   priority = 250 },
      }),
    })
  end,
}
클라이언트가 뭐 지원하는지 LSP 서버에 알리기·lua
-- 한 번 붙이고 매 서버 config 에 재사용
local capabilities = require("cmp_nvim_lsp").default_capabilities()

vim.lsp.config("pyright", {
  cmd = { "pyright-langserver", "--stdio" },
  root_markers = { "pyproject.toml", "setup.py", ".git" },
  capabilities = capabilities,   -- 스니펫 completion 등 활성화
})
blink.cmp 대안 (더 빠르고, 더 단순)·lua
-- 현대 대안 시도하고 싶으면:
{
  "saghen/blink.cmp",
  event = "InsertEnter",
  version = "*",
  opts = {
    keymap = { preset = "default" },
    appearance = { use_nvim_cmp_as_default = true },
    sources = {
      default = { "lsp", "path", "snippets", "buffer" },
    },
  },
}

External links

Exercise

Config 에 nvim-cmp 셋업과 capabilities hook 추가. Neovim 재시작. LSP 서버 attach 되는 프로젝트 (확인은 :LspInfo) 의 Python (또는 자기 언어) 파일 열기. 이름 입력 시작; 팝업 나타나야 함. Tab 으로 navigate, Enter 로 confirm, Esc 로 dismiss. 스니펫 발동 (예: Python 에서 main 입력 후 expand) 해서 LuaSnip 작동 확인.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.