devAlice
← Mac

Brewfile 관리 — `brew bundle`로 맥 환경을 코드로 재현하기

맥 환경을 한 파일로 굳히는 Brewfile 패턴. dump → 정리 → cleanup → 다른 머신에 install까지 한 사이클.

새 맥에 셋업할 때마다 brew install 명령을 일일이 적는 건 비효율이다. brew bundleBrewfile 한 파일로 brew 패키지·cask·VS Code 확장·App Store 앱까지 묶어서 재현 가능하게 만든다. 한 번 익혀두면 머신 교체나 동료 온보딩 시간이 30분 단위로 줄어든다.

이 가이드는 macOS 14+ / Homebrew 4.x 기준. Mac 초기 셋업 이후 환경을 코드로 굳히는 단계다.

TL;DR

  1. brew bundle dump --describe로 현재 상태를 Brewfile로 추출
  2. 손으로 정리(중복·테스트 패키지 제거) → Git에 커밋
  3. 새 맥에서 brew bundle install --file=./Brewfile → 끝
  4. 정기적으로 brew bundle cleanup으로 Brewfile에 없는 것 제거

사전 조건

  • Homebrew 4.x 설치 — Mac 초기 셋업
  • (선택) GitHub repo 또는 Gist (Brewfile 보관용)
  • (선택) mas-cli — Mac App Store 앱까지 묶으려면 brew install mas

Brewfile 예시 다운로드

devAlice 권장 베이스라인 Brewfile — 그대로 받아 자신의 환경에 맞게 편집해서 시작하면 된다.

Brewfile
# 1. 다운로드
curl -fsSL https://devalice.jaceclub.com/assets/mac/brewfile-management/Brewfile.example -o Brewfile
 
# 2. SHA-256 검증
shasum -a 256 Brewfile
# 기대값: 2b54214d29391d15666fe5e15768aa2e6e6eabea8b3c772989d6e1216a816c5f
 
# 3. 코드 검사 (어떤 패키지가 들어있는지 확인 후 본인 환경에 맞게 편집)
less Brewfile
 
# 4. 적용
brew bundle install --file=./Brewfile

1. Brewfile 기본 문법 — 5분

Ruby DSL 기반이지만 사실상 5개 키워드면 충분.

# Brewfile
 
# tap — 추가 저장소
tap "homebrew/bundle"
tap "homebrew/services"
 
# brew — formula (CLI 도구)
brew "git"
brew "gh"
brew "mise"
 
# 옵션 인자 가능
brew "postgresql@16", restart_service: :changed
brew "redis",         start_service: true
 
# cask — GUI 앱
cask "visual-studio-code"
cask "rectangle"
 
# Mac App Store (mas-cli 필요)
mas "Xcode", id: 497799835
 
# VS Code 확장 (mas 비슷한 문법)
vscode "dbaeumer.vscode-eslint"
vscode "esbenp.prettier-vscode"

주석 + 섹션화

# ─── CLI ──────────────────────────────────────
brew "git"
brew "gh"
 
# ─── GUI ──────────────────────────────────────
cask "visual-studio-code"

읽기 좋게 섹션 구분하는 것이 유지보수에 매우 큰 차이를 만든다. (커밋 후 diff가 의미 있게 보인다.)


2. 현재 상태에서 Brewfile 만들기 — dump — 3분

이미 잘 깔린 머신이 있다면, 거기서 한 번에 추출.

# 현재 디렉토리에 Brewfile 생성 (--force는 기존 덮어쓰기)
brew bundle dump --force --describe
 
# --describe는 각 라인에 # 설명을 자동 추가 — 가독성 ↑

산출 예시:

# ./Brewfile (자동 생성)
tap "homebrew/services"
brew "git"
# Distributed revision control system
brew "gh"
# GitHub command-line tool
brew "jq"
# Lightweight and flexible command-line JSON processor
brew "mise"
# Polyglot runtime manager (asdf rust clone)
cask "visual-studio-code"
# Open-source code editor

dump 후 손으로 정리하기

dump 결과는 현재 깔린 모든 것이라 보통 노이즈가 많다. 정리 체크리스트:

  1. 테스트로 깔았다가 안 쓰는 패키지 제거
  2. 언어 런타임은 빼기mise로 관리할 거라면 node, python@3.x 등은 Brewfile에서 빼는 게 단정함
  3. 회사 전용·개인 전용 분리 (Brewfile.work / Brewfile.personal)
  4. 섹션 구분 주석 추가

10분 투자로 향후 셋업 시간 1시간 절약.


3. 다른 머신에서 적용 — install — 10~30분

새 맥 또는 정리 후 머신에서:

# Brewfile이 있는 디렉토리에서
brew bundle install --file=./Brewfile
 
# 또는 절대 경로
brew bundle install --file=$HOME/dotfiles/Brewfile
 
# 이미 깔린 건 건너뜀 (멱등성)

처음 실행 시 cask 다운로드가 가장 오래 걸린다 (각 50200MB). 10~30분 정도 예상.

단계별 확인 — --verbose

진행 상황을 자세히 보고 싶을 때:

brew bundle install --file=./Brewfile --verbose

실패 라인만 확인 — --quiet

성공 라인은 숨기고 실패만 보고 싶다면:

brew bundle install --file=./Brewfile --quiet

4. Brewfile에 없는 패키지 정리 — cleanup — 5분

Brewfile을 진실원으로 만들고 싶다면 — Brewfile에 없는 패키지를 정리.

# Dry-run — 무엇이 제거될지 미리 확인
brew bundle cleanup --file=./Brewfile
 
# 실제 제거 — 신중히
brew bundle cleanup --file=./Brewfile --force

⚠️ --force는 즉시 uninstall한다. Brewfile이 완전히 정리된 후에만 실행. 안 그러면 다시 깔아야 할 수도 있다.


5. 분할 전략 — work / personal / experiment

단일 Brewfile은 결국 비대해진다. 컨텍스트별로 나누자.

~/dotfiles/
├── Brewfile           # 모두 공통 (CLI 필수)
├── Brewfile.work      # 회사 전용 (Slack, Zoom 등)
├── Brewfile.personal  # 개인 전용 (게임 런처 등)
└── Brewfile.optional  # 가끔 쓰는 것

조합해서 한 번에 적용

cd ~/dotfiles
brew bundle install --file=./Brewfile
brew bundle install --file=./Brewfile.work
brew bundle install --file=./Brewfile.personal

한 번에 묶기 (Makefile 또는 셸 스크립트)

# ~/dotfiles/bundle.sh
#!/usr/bin/env bash
set -euo pipefail
cd "$(dirname "$0")"
for f in Brewfile Brewfile.work Brewfile.personal; do
  [ -f "$f" ] && brew bundle install --file="./$f"
done
echo "✓ All Brewfiles applied"

6. Git으로 버전 관리 — 3분

Brewfile은 dotfiles repo의 핵심 파일 중 하나다.

cd ~/dotfiles
git init
git add Brewfile Brewfile.*
git commit -m "feat: initial Brewfile baseline"
git remote add origin git@github.com:<user>/dotfiles.git
git push -u origin main

이후 패키지 추가/제거 시:

brew bundle dump --force --describe   # 갱신
git diff Brewfile                     # 변경 확인
git commit -am "feat: add postgresql + redis"
git push

새 머신에선:

git clone git@github.com:<user>/dotfiles.git ~/dotfiles
cd ~/dotfiles
brew bundle install --file=./Brewfile

7. 자동화 — brew services + macOS LaunchAgent

매일 한 번 자동 dump해서 brew 상태가 drift하지 않도록.

~/Library/LaunchAgents/dev.local.brewdump.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key><string>dev.local.brewdump</string>
  <key>ProgramArguments</key>
  <array>
    <string>/bin/bash</string>
    <string>-lc</string>
    <string>cd $HOME/dotfiles && /opt/homebrew/bin/brew bundle dump --force --describe</string>
  </array>
  <key>StartCalendarInterval</key>
  <dict><key>Hour</key><integer>22</integer><key>Minute</key><integer>0</integer></dict>
</dict>
</plist>
launchctl load ~/Library/LaunchAgents/dev.local.brewdump.plist

매일 22시에 자동 dump. 다음 날 아침 git diff로 어떤 변경이 있었는지 확인.


8. 트러블슈팅

"Error: Cask 'X' is not installed" (cleanup 시)

이미 다른 곳에서 제거된 cask. brew bundle cleanup --force 한 번 더 실행하면 정리됨.

dump 결과에 의도하지 않은 패키지가 너무 많음

이전에 dependency로 설치된 것들이 명시적으로 노출됨. 정리:

brew autoremove   # dependency만 사용된 leaf 패키지 제거
brew bundle dump --force --describe  # 다시 dump

Mac App Store 앱이 dump에 안 들어옴

mas-cli가 없다. brew install mas 후 다시 dump.

Brewfile 적용 시 일부 cask가 SHA-256 mismatch

Homebrew가 cask 정의를 막 갱신한 직후 발생 가능. brew update 후 재시도.


다음 단계

참고 링크

변경 이력

  • 2026-05-12 — 초안 (devAlice M2 시드 확장)

댓글