dotfiles 관리, GNU Stow로 정착한 이야기
2026.04.18dotfiles 관리 도구만 세 번 갈아탔다
새 노트북을 받을 때마다 환경 설정을 다시 한다는 게 너무 번거로웠다. .zshrc, .gitconfig, .tmux.conf, .config/nvim/... 매번 같은 파일을 다시 만들고 있었다.
처음에는 git 레포에 통째로 넣고 bash 스크립트로 심볼릭 링크를 만들었다. 그 다음에는 chezmoi라는 도구로 갈아탔다. 그 다음에는 yadm을 시도했다. 그러다 결국 GNU Stow에 정착했다.
가장 단순한 게 가장 오래 살아남았다. 이 글은 그 여정과, 왜 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 패키지 링크 제거스크립트도 없고, 템플릿도 없고, 별도 툴 명령어도 없다. 이 단순함이 답이었다.
실제 디렉토리 구조
내 dotfiles 레포 구조다.
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 관리 도구를 세 번 갈아탄 후 정착한 답은 가장 오래된 도구였다. GNU Stow는 단순하고, 학습할 게 거의 없고, 깨질 일이 없다. 도구가 단순할수록 평생 쓰기 좋다는 것을 새삼 느꼈다.
내 셋업의 본질은 두 줄이다.
git clone https://github.com/me/dotfiles
cd dotfiles && stow -t ~ */그 위에 Brewfile이 패키지를 깔고, install.sh가 두 줄을 자동화한다. 수년째 그대로 쓰고 있다. 도구가 안 바뀐다는 게 안정성이다.
dotfiles 도구를 고민 중이라면, 일단 Stow를 써보길 권한다. 한 시간이면 셋업 끝난다. 더 강력한 도구가 필요한 시점이 오면 그때 옮기면 된다. 대부분은 그 시점이 안 온다.