dotfiles 관리 도구 고르기 — bash 스크립트, chezmoi, yadm, GNU Stow
2026.04.18
dotfiles 관리 도구는 왜 이렇게 많은가
새 노트북을 받을 때마다 환경 설정을 다시 한다는 게 너무 번거로웠다. .zshrc, .gitconfig, .tmux.conf, .config/nvim/... 매번 같은 파일을 다시 만들고 있었다.
방법은 크게 넷이다. git 레포에 통째로 넣고 bash 스크립트로 심볼릭 링크를 만들거나, chezmoi를 쓰거나, yadm을 쓰거나, GNU Stow를 쓴다.
넷을 놓고 따져보면 규모에 따라 답이 갈린다. 이 글은 그 비교와, 왜 가장 단순한 쪽이 오래 살아남는지에 대한 정리다.
dotfiles 관리의 본질
이름만 거창하지 결국 두 가지 일이다.
- 설정 파일들을 git 레포에 모은다
- 새 머신에서 그 파일들을 홈 디렉토리에 적절히 배치한다
문제는 2번이다. .zshrc는 ~/에, init.lua는 ~/.config/nvim/에 있어야 한다. 폴더 구조가 다른 파일들을 한 레포에 모아두면서 어떻게 원래 위치로 보낼지가 핵심이다.
시도 1: bash 스크립트
처음 만든 방법이다. 레포 구조를 홈 디렉토리와 동일하게 만들고, 셸 스크립트로 일괄 심볼릭 링크를 만들었다.
#!/bin/bash
# install.sh
ln -sf $PWD/.zshrc ~/.zshrc
ln -sf $PWD/.gitconfig ~/.gitconfig
mkdir -p ~/.config/nvim
ln -sf $PWD/.config/nvim/init.lua ~/.config/nvim/init.lua
# ...100줄 더처음에는 잘 됐다. 파일이 늘어나면서 install.sh가 200줄을 넘었다. 새 파일을 추가할 때마다 스크립트도 같이 수정해야 했다. 한 번씩 빠뜨려서 동기화가 안 됐다.
시도 2: chezmoi
dotfiles 전용 도구다. 설정 파일에 템플릿을 적용할 수 있고, 머신마다 다른 값(예: 회사 이메일 vs 개인 이메일)을 분기할 수 있다.
chezmoi init
chezmoi add ~/.zshrc
chezmoi apply기능이 많다. 너무 많다는 게 문제였다.
- 템플릿 문법(Go template)을 익혀야 한다
chezmoi managed,chezmoi diff,chezmoi update등 명령어가 많다- 진짜 dotfiles의 어디까지가 템플릿이고 어디까지가 정적 파일인지 구분이 헷갈린다
머신 간 분기가 정말 필요한 사람에게는 좋겠지만, 나는 단일 OS(macOS)에서 1~2대만 쓴다. 도구가 내 사용 사례에 비해 너무 컸다.
시도 3: yadm
Yet Another Dotfiles Manager의 약자. git을 그대로 쓰면서 홈 디렉토리를 git working directory로 다루는 도구다.
yadm clone https://github.com/me/dotfiles
yadm add ~/.zshrc
yadm commit -m "update zshrc"git에 익숙한 사람이라면 자연스럽다. 다만 한 가지 단점이 있었다. 홈 디렉토리 전체가 git working directory가 된다. yadm status를 치면 추적 안 된 파일이 수천 개 나온다. .gitignore 관리가 까다롭다.
또 yadm으로 관리되는 파일과 일반 파일이 같은 경로에 섞여 있어서, "이 파일이 dotfiles에 들어 있나?"를 매번 확인해야 했다.
GNU Stow가 오래 살아남는 이유
Stow는 위 도구들과 비교하면 원시적이다. 심볼릭 링크를 자동으로 만들어주는 작은 유틸리티가 전부다. 1996년에 만들어진 도구다.
설치는 한 줄.
brew install stow기본 사용법은 단순하다. 홈 디렉토리에 두고 싶은 파일을 패키지(폴더)로 묶어서 레포에 둔다.
dotfiles/
├── zsh/
│ └── .zshrc
├── git/
│ └── .gitconfig
├── nvim/
│ └── .config/
│ └── nvim/
│ └── init.lua
└── tmux/
└── .tmux.conf각 패키지는 홈 디렉토리에서 보일 구조를 그대로 가진다. nvim/.config/nvim/init.lua는 ~/.config/nvim/init.lua로 링크된다.
레포 안에서 한 줄.
stow zsh git nvim tmux끝이다. 모든 파일이 홈 디렉토리에 심볼릭 링크로 연결된다. 새 패키지를 추가하면 stow newpkg 한 줄.
언링크도 한 줄.
stow -D nvim # nvim 패키지 링크 제거스크립트도 없고, 템플릿도 없고, 별도 툴 명령어도 없다. 이 단순함이 답이었다.
실제 디렉토리 구조
Stow를 쓸 때 흔히 잡는 레포 구조다.
dotfiles/
├── README.md
├── install.sh # brew install + stow 자동화
├── zsh/
│ ├── .zshrc
│ └── .zsh/aliases.sh
├── git/
│ └── .gitconfig
├── tmux/
│ └── .tmux.conf
├── starship/
│ └── .config/starship.toml
├── nvim/
│ └── .config/nvim/...
├── claude/
│ └── .claude/settings.json
└── vscode/
└── Library/Application\ Support/Code/User/settings.json패키지를 영역별로 분리해뒀다. 새 머신에서 모든 걸 다 깔지 않을 수 있다. 예를 들어 서버에서는 nvim과 tmux만, 노트북에서는 전부.
# 서버에서
stow nvim tmux
# 노트북에서
stow -t ~ */stow -t ~ */는 모든 패키지를 홈 디렉토리로 링크하라는 명령이다.
install.sh 자동화
새 머신을 받으면 한 번만 실행할 스크립트.
#!/bin/bash
set -e
# 1. brew 깔기
if ! command -v brew &> /dev/null; then
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
fi
# 2. brew bundle로 패키지 설치
brew bundle --file=Brewfile
# 3. dotfiles 링크
stow -t ~ */
# 4. zsh 기본 셸로 설정
if [ "$SHELL" != "$(which zsh)" ]; then
chsh -s $(which zsh)
fi
echo "✓ Setup complete"Brewfile에는 brew로 깔 패키지 목록을 적어둔다. (이걸 별도 패키지 매니저로 분리하지 않는 이유는 단순함을 유지하려고.)
새 노트북에서 git clone 후 ./install.sh 한 번. 5분 안에 환경 복원이 끝난다.
작은 함정 몇 가지
함정 1: 중첩된 디렉토리 구조
stow -t ~ */은 폴더 단위로 링크를 만들 수 있다. 예를 들어 ~/.config/nvim 자체를 심볼릭 링크로 만들지, 아니면 그 안의 파일 하나하나를 링크로 만들지 결정한다.
기본 동작은 이미 존재하는 디렉토리에는 파일 단위로, 존재하지 않는 디렉토리는 폴더 자체를 링크한다. 보통 이게 안전하다.
만약 ~/.config/nvim이 이미 존재하면 그 안의 파일들을 개별 심볼릭 링크로 만든다. 직접 만든 파일이 충돌하면 stow가 멈추고 알려준다.
함정 2: 비밀 정보가 섞인다
.gitconfig에 회사 이메일이 들어가 있거나, .aws/credentials에 키가 있으면 git에 푸시되면 안 된다. dotfiles 레포는 보통 public이다.
해결: 비밀 정보가 들어가는 파일은 stow로 관리하지 않는다. 별도 1Password나 Bitwarden 등으로 따로 관리하고, 새 머신에서 직접 만든다.
함정 3: 절대 경로
설정 파일에 절대 경로(/Users/me/...)를 박아두면 새 머신에서 경로가 다르다. $HOME 환경 변수를 쓰거나 ~를 쓴다.
직접 겪은 일: 관리할 dotfiles가 아직 없다
네 가지를 비교해 놓고 실토하면, 내 홈에는 ~/dotfiles가 없다. stow도 안 깔려 있다.
대신 .zshrc 하나가 홈에 그냥 놓여 있다. 17줄이고, 거의 전부 경로 설정이다. .gitconfig가 있고, 그 밖에 관리할 만한 건 사실상 없다.
여기서 알게 된 게 있다. dotfiles 관리 도구는 관리할 dotfiles가 여러 개일 때 값을 한다. 파일이 두어 개면 심볼릭 링크를 걸 이유도, 레포를 팔 이유도 없다. 도구가 해결하는 건 「많은 파일을 여러 머신에 일관되게 뿌리는 일」인데, 나는 아직 그 문제를 안 갖고 있었다.
새 맥을 받으면 후회할 것이다. 그건 안다. 다만 지금 아프지 않은 문제는 늘 뒤로 밀린다. 이 글을 쓴 것 자체가 그 미룸의 일부다 — 알아보는 데까지는 했고 만들지는 않았다.
그래서 순서를 하나 정정한다. 도구를 고르는 일보다 관리할 것을 모으는 일이 먼저다. 순서를 뒤집으면 비교만 하다 끝난다. 지금 내가 딱 그 상태다.
정리
넷을 비교하면 가장 오래된 도구가 가장 오래 간다. GNU Stow는 단순하고, 학습할 게 거의 없고, 깨질 일이 없다. 도구가 단순할수록 오래 쓰기 좋다.
셋업의 본질은 두 줄이다.
git clone https://github.com/me/dotfiles
cd dotfiles && stow -t ~ */그 위에 Brewfile이 패키지를 깔고, install.sh가 두 줄을 자동화한다. 도구가 안 바뀐다는 게 이 구성의 안정성이다.
dotfiles 도구를 고민 중이라면, 일단 Stow를 써보길 권한다. 한 시간이면 셋업 끝난다. 더 강력한 도구가 필요한 시점이 오면 그때 옮기면 된다. 대부분은 그 시점이 안 온다.
같이 읽으면 좋은 글
cmux 터미널 내 취향대로 꾸미기 — 따라 하는 설정 가이드
AI 코딩 에이전트를 병렬로 돌리는 macOS 터미널 cmux를 내 취향대로 꾸미는 법. 설정 파일 두 개의 역할을 나눠서 이해하고, 폰트·테마·투명도·사이드바·워크스페이스 색까지 복붙으로 따라 할 수 있게 정리했다.
cmux터미널개발환경2026.05.02macOS 개발자 필수 brew 패키지 30선: 카테고리별 정리
새 맥북을 받았을 때 가장 먼저 까는 brew 패키지 30개를 카테고리별로 정리한다. 셸, CLI, 개발 도구, 앱(cask)까지 — Brewfile 한 장으로 환경을 복원하는 셋업.
macOSbrew개발환경2026.04.19mise(구 rtx)로 Node·Python·Go 버전 관리 통합하기
nvm, pyenv, gvm을 따로 깔지 않고 mise 하나로 합치는 법. .tool-versions로 프로젝트별 자동 버전 전환, asdf와의 차이, .env 자동 로딩, 그리고 좋은 걸 알면서 아직 안 옮긴 이유까지 정리한다.
개발환경도구2026.04.18