Neovim 설정 정리 (1편) — init.lua 구조와 Lua 기초

2026. 5. 25. 15:17·블로그, 컴퓨터/Cheatsheets

vim, neovim cheatsheet thumbnail

vim 명령어를 어느 정도 익히고 나면 자연스럽게 설정 파일에 손이 가게 됩니다. 예전에 일반 vim을 쓸 때는 ~/.vimrc 하나에 set number 같은 걸 몇 줄 넣는 게 전부였는데, Neovim으로 넘어오면 init.lua라는 게 등장하고, Lua 스크립트로 설정을 한다는 얘기가 나옵니다.

처음엔 "vim 쓰려고 언어를 또 배워야 해?" 싶었는데, 막상 보면 설정 파일 맥락에서 쓰는 Lua는 그렇게 방대하지 않습니다. 그리고 Vimscript로 비슷한 걸 짜는 것보다 확실히 읽기 편합니다.

1편에서는 init.lua가 어디에 있고 어떻게 구성되는지, Lua 문법 중 설정 파일에서 실제로 쓰이는 것들, 키매핑, autocmd를 정리합니다.


init.lua는 어디에 있나

Neovim의 설정 파일 위치는 운영체제마다 다릅니다.

Linux / macOS   ~/.config/nvim/init.lua
Windows         ~\AppData\Local\nvim\init.lua

nvim 디렉토리가 없으면 만들면 됩니다. 기존에 init.vim을 쓰고 있었다면 같은 위치에 init.lua로 대체하면 됩니다. 둘을 같이 두면 충돌이 생기니 하나만 씁니다.

파일 하나에 전부 써도 되고, 여러 파일로 나눠서 require()로 불러오는 구조로 가도 됩니다. 처음엔 init.lua 하나에 다 쓰다가 길어지면 나누는 게 자연스러운 흐름입니다.


Vimscript와 Lua, 뭐가 다른가

Neovim은 Lua를 1급 스크립트 언어로 내장하고 있습니다. Vimscript로 쓰던 설정을 Lua로 쓸 수 있고, 두 가지를 섞어 써도 됩니다. 같은 설정을 두 가지 방식으로 쓰면 이렇게 됩니다.

" Vimscript (.vimrc 또는 init.vim)
set number
set tabstop=4
nnoremap <leader>w :w<CR>
-- Lua (init.lua)
vim.opt.number = true
vim.opt.tabstop = 4
vim.keymap.set('n', '<leader>w', ':w<CR>')

Vimscript가 짧아 보이지만, 설정이 복잡해질수록 Lua가 훨씬 읽기 편합니다. 조건문, 함수, 모듈화 같은 걸 쓸 때 차이가 큽니다.

init.lua 안에서 Vimscript 명령어를 그대로 실행하고 싶으면 vim.cmd()를 씁니다.

vim.cmd('colorscheme habamax')
vim.cmd([[
  augroup MyGroup
    autocmd!
  augroup END
]])

설정값 쓰기 (vim.opt)

set에 해당하는 게 vim.opt입니다.

vim.opt.number = true           -- set number
vim.opt.relativenumber = true   -- set relativenumber
vim.opt.tabstop = 4             -- set tabstop=4
vim.opt.shiftwidth = 4          -- set shiftwidth=4
vim.opt.expandtab = true        -- set expandtab
vim.opt.hlsearch = true         -- set hlsearch
vim.opt.incsearch = true        -- set incsearch
vim.opt.ignorecase = true       -- set ignorecase
vim.opt.smartcase = true        -- set smartcase
vim.opt.wrap = false            -- set nowrap
vim.opt.termguicolors = true    -- set termguicolors
vim.opt.signcolumn = 'yes'      -- 좌측 기호 열 항상 표시 (LSP 진단 표시용)
vim.opt.updatetime = 250        -- 자동저장, CursorHold 반응 속도 (ms)
vim.opt.clipboard = 'unnamedplus'  -- 시스템 클립보드 연동

vim.opt 외에 vim.o(전역), vim.wo(창 단위), vim.bo(버퍼 단위)도 있습니다. 대부분의 경우 vim.opt를 쓰면 Neovim이 알아서 적절한 범위에 적용합니다.

리더 키 설정

플러그인 키맵에서 <leader>를 많이 씁니다. 기본값은 \인데 보통 스페이스로 바꿔 씁니다. vim.opt보다 먼저 선언해야 플러그인 설정에 반영됩니다.

vim.g.mapleader = ' '
vim.g.maplocalleader = ' '

Lua 문법 — 설정 파일에서 쓰는 것들

Lua 언어 전체를 배울 필요는 없고, init.lua에서 실제로 나오는 패턴들만 알면 됩니다.

주석

-- 한 줄 주석
--[[
  여러 줄 주석
]]

변수

local x = 10           -- 지역 변수 (local 권장)
y = 20                 -- 전역 변수 (가능하면 안 씀)
local s = "hello"
local flag = true
local nothing = nil    -- 값 없음

local을 붙이는 게 기본입니다. 안 붙이면 전역 변수가 되어서 다른 파일 설정과 충돌할 수 있습니다.

테이블

Lua에서 테이블은 배열이자 딕셔너리입니다. 플러그인 설정에서 가장 자주 보이는 자료구조입니다.

-- 배열처럼
local colors = { 'red', 'green', 'blue' }
print(colors[1])    -- Lua 인덱스는 1부터 시작

-- 딕셔너리처럼
local opts = {
  noremap = true,
  silent = true,
}
print(opts.noremap)    -- true

조건문

if vim.fn.has('mac') == 1 then
  vim.opt.shell = 'zsh'
elseif vim.fn.has('win32') == 1 then
  vim.opt.shell = 'pwsh'
else
  vim.opt.shell = 'bash'
end

함수

local function my_func(a, b)
  return a + b
end

-- 익명 함수를 변수에 담는 방식도 자주 씁니다
local greet = function(name)
  print('Hello, ' .. name)
end

require로 모듈 불러오기

init.lua가 길어지면 파일을 나눠서 require로 불러옵니다.

-- init.lua
require('config.options')    -- ~/.config/nvim/lua/config/options.lua
require('config.keymaps')    -- ~/.config/nvim/lua/config/keymaps.lua
require('config.plugins')    -- ~/.config/nvim/lua/config/plugins.lua

lua/ 디렉토리 아래에 파일을 만들면 require()로 불러올 수 있습니다. .은 디렉토리 구분자로 씁니다.

~/.config/nvim/
├── init.lua
└── lua/
    └── config/
        ├── options.lua
        ├── keymaps.lua
        └── plugins.lua

키매핑 (vim.keymap.set)

Vimscript의 nnoremap, inoremap 등을 대체합니다.

vim.keymap.set(모드, 키, 동작, 옵션)

모드는 문자열로 씁니다: 'n'(Normal), 'i'(Insert), 'v'(Visual), 'x'(Visual+Select), 't'(Terminal), 'c'(Command), ''(전체).

local map = vim.keymap.set

-- 기본 예시
map('n', '<leader>w', ':w<CR>', { desc = '저장' })
map('n', '<leader>q', ':q<CR>', { desc = '종료' })

-- noremap + silent 기본으로 붙이는 패턴
local opts = { noremap = true, silent = true }
map('n', '<C-h>', '<C-w>h', opts)    -- 왼쪽 창으로
map('n', '<C-j>', '<C-w>j', opts)    -- 아래 창으로
map('n', '<C-k>', '<C-w>k', opts)    -- 위 창으로
map('n', '<C-l>', '<C-w>l', opts)    -- 오른쪽 창으로

-- 검색 하이라이트 끄기
map('n', '<Esc>', ':nohlsearch<CR>', opts)

-- 줄 이동 (선택 후 J/K로 이동)
map('v', 'J', ":m '>+1<CR>gv=gv", opts)
map('v', 'K', ":m '<-2<CR>gv=gv", opts)

-- Lua 함수를 직접 연결할 수도 있습니다
map('n', '<leader>e', function()
  vim.diagnostic.open_float()
end, { desc = '진단 메시지 열기' })

noremap = true는 키맵 재귀 방지, silent = true는 명령어를 하단 커맨드라인에 출력하지 않는 옵션입니다. desc는 which-key 같은 플러그인이 설명을 보여줄 때 쓰입니다.


autocmd

특정 이벤트가 발생할 때 자동으로 실행할 동작을 등록합니다.

vim.api.nvim_create_autocmd(이벤트, 옵션)

자주 쓰는 패턴

-- 파일 저장 시 trailing whitespace 제거
vim.api.nvim_create_autocmd('BufWritePre', {
  pattern = '*',
  callback = function()
    vim.cmd('%s/\\s\\+$//e')
  end,
})

-- 파일 타입별 들여쓰기 설정
vim.api.nvim_create_autocmd('FileType', {
  pattern = { 'lua', 'javascript', 'typescript' },
  callback = function()
    vim.opt_local.tabstop = 2
    vim.opt_local.shiftwidth = 2
  end,
})

-- 터미널 열면 Insert 모드로 진입
vim.api.nvim_create_autocmd('TermOpen', {
  pattern = '*',
  callback = function()
    vim.cmd('startinsert')
  end,
})

-- yank 시 잠깐 하이라이트 (복사된 영역 시각적 피드백)
vim.api.nvim_create_autocmd('TextYankPost', {
  callback = function()
    vim.highlight.on_yank()
  end,
})

여러 autocmd를 하나의 그룹으로 묶으면 관리가 편합니다. reload 시 중복 등록도 막을 수 있습니다.

local group = vim.api.nvim_create_augroup('MyConfig', { clear = true })

vim.api.nvim_create_autocmd('BufWritePre', {
  group = group,
  pattern = '*',
  callback = function()
    vim.cmd('%s/\\s\\+$//e')
  end,
})

vim.fn — Vimscript 함수 호출

Lua에서 Vimscript 내장 함수를 그대로 쓸 수 있습니다.

vim.fn.has('nvim-0.9')       -- 버전 확인
vim.fn.expand('%:p')          -- 현재 파일 전체 경로
vim.fn.expand('~')            -- 홈 디렉토리 경로
vim.fn.executable('rg')       -- 실행 파일 존재 여부 (1 or 0)
vim.fn.stdpath('config')      -- Neovim 설정 경로
vim.fn.stdpath('data')        -- 데이터 경로 (플러그인 저장 위치)

정리 표

분류 Vimscript Lua
옵션 설정 set number vim.opt.number = true
전역 변수 let g:foo = 1 vim.g.foo = 1
키매핑 nnoremap <key> <cmd> vim.keymap.set('n', ...)
autocmd autocmd Event * cmd vim.api.nvim_create_autocmd(...)
함수 실행 call Func() vim.fn.Func()
명령어 실행 직접 vim.cmd('...')
모듈화 source file.vim require('module')
주석 " --

2편에서는 lazy.nvim으로 플러그인을 관리하는 방법과, LSP(mason + nvim-lspconfig)를 실제로 세팅하는 방법을 다룹니다.

반응형
저작자표시 비영리 변경금지 (새창열림)

'블로그, 컴퓨터 > Cheatsheets' 카테고리의 다른 글

Git 명령어 정리 (1편) — 기본 개념, 설정, 커밋, 로그  (0) 2026.05.26
Neovim 설정 정리 (2편) — lazy.nvim, LSP, 주요 플러그인  (0) 2026.05.25
Vim 명령어 정리 (2편) — 검색/치환, Visual 모드, 분할 화면, 설정  (0) 2026.05.24
Vim 명령어 정리 (1편) — 모드, 이동, 편집, 저장  (0) 2026.05.24
리눅스 터미널 명령어 정리 (2편) — 권한, 프로세스, 네트워크, 검색 & 파이프  (0) 2026.05.23
'블로그, 컴퓨터/Cheatsheets' 카테고리의 다른 글
  • Git 명령어 정리 (1편) — 기본 개념, 설정, 커밋, 로그
  • Neovim 설정 정리 (2편) — lazy.nvim, LSP, 주요 플러그인
  • Vim 명령어 정리 (2편) — 검색/치환, Visual 모드, 분할 화면, 설정
  • Vim 명령어 정리 (1편) — 모드, 이동, 편집, 저장
생각사람
생각사람
지극히 사적인 연구실
  • 생각사람
    생각사람의 별장
    생각사람
  • 전체
    오늘
    어제
    • 분류 전체보기 (207) N
      • 금융 (57)
        • 주식 공부 (11)
        • 파생상품 입문 (17)
        • 파생상품 기초 (15)
        • 파생상품 실전 (14)
      • 블로그, 컴퓨터 (83) N
        • 프로그래밍 (16)
        • DevOps (8)
        • AI, RL, ML, ... (5)
        • 애드센스, SEO (23)
        • 임베디드 (3)
        • 컴퓨터 관련 (7)
        • Cheatsheets (21) N
      • 다른 공부들 (67)
        • 읽고 쓰기 (18)
        • 수학 (15)
        • 물리 (9)
        • 사진 공부 (25)
  • 인기 글

  • 최근 글

  • 최근 댓글

  • 태그

    파생상품
    스트랭글
    프로그래밍
    옵션
    웹크롤러
    오펜하이머
    GIT
    독후감
    코딩
    c
    벡터
    소니 a6000
    공업수학
    선물 옵션
    version control
    c++
    github
    Kreyszig
    깃허브
    스트래들
    행렬
    AI
    깃
    cmake
    선형대수학
    양자역학
    구글 애드센스
    슈뢰딩거 방정식
    옵션 투자
    CheatSheet
  • hELLO· Designed By정상우.v4.10.6
생각사람
Neovim 설정 정리 (1편) — init.lua 구조와 Lua 기초
상단으로

티스토리툴바