
git worktree로 실현하는 AI 병렬 개발 권장
요약
AI 코딩 에이전트 활용 시 발생하는 작업 충돌을 방지하기 위해 git worktree를 활용한 병렬 개발 방식을 제안합니다. 하나의 리포지토리에서 여러 작업 디렉토리를 생성하여 에이전트별 독립적인 환경을 구축하는 방법을 다룹니다.
핵심 포인트
- AI 에이전트 다중 실행 시 발생하는 파일 충돌 문제 해결
- git worktree를 통한 1 리포지토리 - 다중 작업 디렉토리 구현
- 브랜치 전환(switch/checkout) 방식의 한계 및 위험성 분석
- 병렬 개발을 통한 작업 효율성 및 개발 흐름 유지
서론
Claude Code나 Cursor와 같은 AI 코딩 에이전트(AI Coding Agent)가 보급되면서, 개발 방식이 크게 변하고 있습니다. 특히 큰 변화는,
"인간 1명이 AI 에이전트를 여러 개 동시에 실행한다"
라는 작업 방식이 현실적이 되었다는 점입니다.
- 태스크 A를 에이전트에게 맡기는 동안, 태스크 B를 다른 에이전트에게 할당한다
- 동일한 기능에 대해 "접근 방식이 다른 두 가지 구현"을 병행시키고, 더 나은 쪽을 채택한다
- 리뷰 지적 사항의 수정을 AI에게 맡기면서, 자신은 다음 기능의 설계를 진행한다
하지만, 이를 하나의 작업 디렉토리(하나의 체크아웃)에서 동시에 하려고 하면 파탄에 이릅니다. 에이전트 A가 src/foo.ts를 수정하고 있는 도중에, 에이전트 B가 같은 파일을 다른 의도로 편집하면 당연히 충돌이 발생합니다. 브랜치(Branch)를 전환하면, 다른 한쪽의 작업은 사라져 보이지 않게 됩니다.
이러 "1 리포지토리 = 1 작업 디렉토리"라는 제약을 벗어나, 동일한 리포지토리로부터 여러 개의 작업 디렉토리를 생성하기 위한 메커니즘이 Git에 표준으로 탑재되어 있는 git worktree입니다.
본 기사에서는,
- 왜 병렬 개발에
git worktree가 적합한가 git worktree의 구조와 기본 명령어- AI 에이전트를 여러 개 실행하는 실전 플로우
- 장점과 빠지기 쉬운 주의점
을 순서대로 정리해 나가겠습니다.
전제: 브랜치 전환만으로는 무엇이 문제인가
git worktree를 이해하기 전에, 기존의 "하나의 작업 디렉토리에서 브랜치를 전환하는" 방식의 한계를 확인해 두겠습니다.
통상적으로 다른 작업으로 옮길 때는 git switch (구 git checkout)로 브랜치를 전환합니다.
git switch feature-a # feature-a 작업
# ...
git switch feature-b # feature-b로 전환
이 방식에는 병렬 작업 관점에서 다음과 같은 문제가 있습니다.
1. 작업 중인 변경 사항이 브랜치 전환과 충돌함
feature-a에서 편집 중인 파일이 전환 대상인 feature-b 측에서도 변경되어 있는 경우(=브랜치 간 내용이 다른 경우), Git은 "커밋(Commit)하거나 퇴피(Stash)하라"며 동작을 멈춥니다.
$ git switch feature-b
error: Your local changes to the following files would be overwritten by checkout:
src/foo.ts
...
결국, git stash로 퇴피 → 전환 → 돌아와서 git stash pop이라는 과정을 반복하게 되어, 퇴피 대상을 착각하거나 되돌리는 것을 잊어버리는 원인이 됩니다.
또한, 전환 대상과 차분이 없는 파일이라면 에러 없이 전환할 수 있지만, 그 경우에는 커밋되지 않은 변경 사항을 품은 채 브랜치가 전환됩니다. feature-a를 위한 작업 중인 변경 사항이 feature-b의 커밋에 섞여 들어갈 수 있으며, 이는 사고의 원인이 됩니다.
2. "동시에 실행하기"가 불가능함
브랜치 전환은 작업 디렉토리의 내용을 해당 브랜치의 상태로 써 내려가는 작업입니다. 즉, 어느 순간 디스크 상에 존재할 수 있는 것은 단 하나의 브랜치 상태뿐입니다.
feature-a의 개발 서버를 실행해 둔 채로,feature-b의 테스트를 실행한다- A에는 에이전트 A, B에는 에이전트 B를 할당하여 별도로 작업시킨다
와 같은 "동시 병행"은 하나의 작업 디렉토리에서는 원리적으로 불가능합니다.
3. 빌드 결과물이나 캐시가 매번 다시 만들어짐
브랜치를 전환할 때마다 소스 내용이 바뀌기 때문에, node_modules의 차이점, 빌드 캐시, 타입 정보 등이 맞지 않게 되어 재설치나 재빌드가 필요해지기 쉽습니다. 이 또한 전환할 때마다 발생하는 비용이 됩니다.
이러한 문제들을 한꺼번에 해결하는 것이 git worktree입니다. "브랜치를 전환하는 것"이 아니라 "브랜치별로 작업 디렉토리를 늘리는 것"이라는 발상의 전환으로 이해해 주세요.
git worktree란
git worktree
는, 하나의 Git 리포지토리(Repository)로부터 여러 개의 작업 디렉토리(Working Tree)를 동시에 전개하는 Git 표준 기능입니다.
보통 git clone을 한 리포지토리는,
.git/
: 리포지토리 본체 (커밋 이력, 브랜치, 설정 등 모든 것)
- 그 외의 파일: 작업 디렉토리 (체크아웃된 브랜치의 실체)
라는 1대1 구성입니다. git worktree를 사용하면, 이 작업 디렉토리 부분만을 여러 개로 늘릴 수 있습니다.
원리: 리포지토리 본체는 공유하고, 작업 디렉토리만 분리
핵심은, 커밋 이력이나 브랜치와 같은 "리포지토리 본체"는 한 곳에서 공유하고, 작업 디렉토리(와 HEAD, 인덱스)만 분리한다는 점에 있습니다.
my-app/ ← 메인 작업 디렉토리 (git clone한 곳)
├─ .git/ ← 리포지토리 본체 (이것이 유일한 실체)
│ └─ worktrees/ ← 각 worktree의 관리 정보가 여기에 매달림
...
- 추가된 작업 디렉토리의
.git은 디렉토리가 아니라 파일이며, 내용은gitdir: /path/to/my-app/.git/worktrees/feature-a와 같은 본체에 대한 참조뿐입니다. - 커밋, 브랜치, 태그, 설정, 스태시(Stash) 등은 원칙적으로 모든 worktree에서 공유됩니다 (실체는 본체의
.git/에 하나만 존재. 설정의 경우extensions.worktreeConfig를 활성화하면 worktree 고유의 값을 가질 수 있습니다). - 반면, 작업 디렉토리의 내용, HEAD (현재 어떤 브랜치에 있는지), 인덱스 (스테이징)는 worktree마다 독립적입니다.
최대의 장점: 동일한 이력을 공유하면서, 여러 브랜치를 동시에 디스크 상에 전개할 수 있음
git worktree를 사용하면,
이력·브랜치는 한 세트로 공유하고 작업 디렉토리만 여러 개로 나누기 때문에,
"feature-a에서 커밋한 내용을 feature-b에서 즉시 git merge 할 수 있다", "브랜치 목록은 어디서 보든 동일하다"와 같은 일관성을 유지하면서도, 물리적으로 서로 다른 디렉토리에서 병렬 작업을 수행할 수 있습니다.
기본 명령어
git worktree의 서브 명령어는 많지 않습니다. 실무에서 주로 사용하는 것은 4가지입니다.
| 명령어 | 역할 |
|---|---|
git worktree add <path> [<branch>] | <path>에 작업 디렉토리 추가 |
git worktree list | 현재 worktree 목록 표시 |
git worktree remove <path> | <path>의 작업 디렉토리 삭제 |
git worktree prune | 실체가 사라진 worktree의 관리 정보 (.git/worktrees/) 정리 |
git worktree add
worktree 추가하기:
기존 브랜치를 체크아웃한 worktree를 만드는 경우:
git worktree add ../my-app-feature-a feature-a # feature-a를 ../my-app-feature-a에 전개
새로운 브랜치를 생성하면서 worktree를 만드는 경우 (병렬 개발에서는 이 방식이 주역입니다):
git worktree add -b feature-x ../my-app-feature-x main # main에서 feature-x를 따서 전개
-b <new-branch>: 새로운 브랜치를 생성하고, 해당 worktree에서 체크아웃합니다.- 끝의
main: 분기점 (이 부분을 생략하면 현재의 HEAD가 기점이 됩니다).
git worktree list
목록 보기:
$ git worktree list
/Users/you/my-app a1b2c3d [main]
/Users/you/my-app-feature-a e4f5a6b [feature-a]
...
어느 경로에 어떤 브랜치가 전개되어 있는지 한눈에 알 수 있습니다.
git worktree remove와 prune
정리하기: 작업이 끝나고 머지(Merge)가 완료되었다면 worktree를 삭제합니다.
작업 디렉터리째로 안전하게 삭제 (커밋되지 않은 변경 사항이나 추적되지 않는 파일이 있으면 중단됨)
git worktree remove ../my-app-feature-x
디렉터리를 수동으로 rm -rf 해버린 경우에는 관리 정보만 .git/worktrees/에 남게 됩니다. 이것을 청소하는 것이 prune입니다.
git worktree prune # 실체가 사라진 worktree의 관리 정보를 삭제
보충: 동일한 브랜치는 두 개의 worktree에서 동시에 체크아웃할 수 없음
git worktree의 중요한 규칙으로서, 기본적으로 1개의 브랜치를 여러 개의 worktree에서 동시에 체크아웃할 수 없습니다.
$ git worktree add ../another main
Preparing worktree (checking out 'main')
fatal: 'main' is already used by worktree at '/Users/you/my-app'
이는 "같은 브랜치를 두 곳에서 별도로 편집하여 커밋했을 때, 어느 쪽이 정답인지 파괴되는 상황"을 방지하기 위한 사양입니다 (git worktree add --force로 덮어쓸 수 있지만, 바로 이 불일치를 초래하기 때문에 권장되지 않습니다). 병렬로 실행할 때는 worktree마다 별도의 브랜치를 할당하는 것이 철칙입니다 (어떻게든 같은 커밋을 기점으로 삼고 싶을 뿐이라면, --detach로 Detached HEAD 상태로 만드는 방법도 있습니다).
AI 병렬 개발의 실천 플로우
여기서부터가 본론입니다. git worktree를 사용하여, 여러 AI 에이전트에게 동시에 작업을 시키는 흐름을 구체적으로 살펴보겠습니다.
전체상: 1태스크 = 1worktree = 1에이전트
기본적인 발상은 간단합니다. 작업시키고 싶은 태스크마다 worktree를 하나 생성하고, 각각에 1체의 AI 에이전트를 할당하는 것뿐입니다.
┌─────────────────────────────┐
│ 리포지토리 본체 (.git) │
│ 이력·브랜치를 공유 │
...
각 에이전트는 물리적으로 별도의 디렉터리에서 작업하기 때문에 파일 편집이 충돌하지 않습니다. 그러면서도 이력은 공유하고 있으므로, 완성된 것을 순차적으로 main에 머지(Merge)해 나갈 수 있습니다.
단, worktree가 방지해 주는 것은 "작업 중인 파일을 동시에 수정해 버리는 충돌"까지입니다. 여러 브랜치가 동일한 부분을 변경하고 있다면, main으로 통합할 때는 평소와 같이 머지 컨플릭트 (Merge Conflict)가 발생합니다 . 태스크를 분할하는 단계에서 수정할 파일이 가급적 겹치지 않도록 해두면 원활하게 진행할 수 있습니다.
스텝 1: 태스크별로 worktree 만들기
# 프로젝트 직하단에서 실행
git worktree add -b feature-search ../app-feat-search main
git worktree add -b feature-notify ../app-feat-notify main
...
이로써 main을 기점으로 한 3개의 독립된 작업 디렉터리가 만들어졌습니다.
스텝 2: 각 worktree에서 의존성(Dependency) 설정하기
node_modules나 .env는 통상적으로 Git 관리 외 (gitignore 대상)이므로, 새로운 worktree에는 복사되지 않습니다 . 각 worktree에서 개별적으로 설정이 필요합니다.
cd ../app-feat-search && npm install
cd ../app-feat-notify && npm install
cd ../app-fix-login && npm install
스텝 3: 각 worktree에서 에이전트 실행하기
worktree마다 별도의 터미널(또는 탭)을 열고, 각각에서 AI 에이전트를 실행하여 서로 다른 태스크를 지시합니다.
# 터미널 1
cd ../app-feat-search && claude # "검색 기능을 구현해줘"라고 지시
# 터미널 2
...
각 에이전트에게는 자신의 worktree 안에서만 작업하도록 시키기 때문에, 서로의 작업을 침범하지 않습니다 (에이전트가 worktree 외부를 조작할 수 없도록 권한 설정도 함께 확인해 두면 안전합니다). 당신은 3개의 탭을 오가며 진행 상황을 확인하거나 리뷰하기만 하면 됩니다.
단계 4: 완성된 것부터 순서대로 머지(Merge) 및 정리
작업이 완료되고 테스트도 통과한 브랜치부터 main 브랜치로 가져옵니다.
cd ../my-app # 메인 worktree (main)로 복귀
git merge feature-search # 완성된 기능을 가져옴
git worktree remove ../app-feat-search # 역할을 다한 worktree를 삭제
...
장점
git worktree를 사용한 AI 병렬 개발의 장점을 정리합니다.
1. 파일 충돌 없이 진정으로 "병렬"로 동작 가능
가장 큰 장점입니다. 에이전트마다 작업 디렉터리가 물리적으로 분리되어 있기 때문에, 같은 파일을 동시에 편집해도 OS/Git 상에서 충돌하지 않습니다. git stash를 넣고 빼는 작업이나 브랜치 전환을 기다릴 필요도 없습니다 (앞서 언급했듯이, 같은 부분을 변경한 브랜치 간의 머지 컨플릭트(Merge Conflict)는 별개의 문제로 남습니다).
2. 컨텍스트 스위칭 (Context Switching) 비용이 제로에 가까움
"에이전트 A의 결과를 기다리는 동안 에이전트 B를 확인하는 것"이 디렉터리(탭)를 전환하는 것만으로 완결됩니다. 브랜치 전환에 따른 재빌드(Rebuild)나 재설치(Reinstall)도 발생하지 않습니다. 각각의 worktree는 실행 중인 개발 서버나 워치(Watch) 프로세스를 계속 유지할 수 있습니다.
3. 동일한 태스크의 "여러 안"을 병행하여 비교 가능
AI 개발 특유의 활용법입니다.
git worktree add -b approach-a ../app-approach-a main
git worktree add -b approach-b ../app-approach-b main
동일한 요구사항을 서로 다른 접근 방식으로 에이전트에게 구현하게 하여, 완성된 두 가지 안을 나란히 놓고 비교해 보고 더 좋은 쪽을 채택할 수 있습니다. 실패한 쪽은 worktree째로 버리면 그만이며, main은 전혀 더러워지지 않습니다.
4. 이력과 브랜치가 한 세트이므로 통합이 쉬움
git clone을 여러 개 만드는 방식과 달리, 이력(History)은 공유됩니다. 특정 worktree의 커밋을 다른 worktree에서 즉시 merge / rebase / cherry-pick 할 수 있으며, 브랜치 목록도 어디서 보든 동일합니다.
5. "부수고 테스트하기"를 안전하게 수행 가능
실험적인 리팩터링(Refactoring)이나 파괴적인 변경도 전용 worktree 안에서만 완결됩니다. 잘 되지 않는다면 디렉터리째로 삭제하면 됩니다. 메인 작업 환경은 항상 깨끗하게 유지할 수 있습니다.
주의사항 및 주의할 점
장점의 이면에는 병렬이기 때문에 발생하는 함정도 있습니다. 이 부분을 파악하지 않고 시작하면 "왜 안 되지?"를 양산하게 되므로, 확실히 확인해 둡니다.
1. Git 관리 외의 파일은 승계되지 않음 (가장 중요)
반복해서 말씀드리지만, worktree 간에 공유되는 것은 리포지터리 본체(이력·브랜치)뿐입니다. 추적 대상 파일은 이력으로부터 체크아웃되어 각 worktree에 실체화되지만, 다음과 같은 Git 관리 외의 파일(gitignore 대상 등)은 새로운 worktree에 존재하지 않습니다.
| 승계되지 않는 것 | 대처 방법 |
|---|---|
node_modules/ | worktree마다 npm install |
.env / .env.local | 원래 worktree에서 복사 (후술할 스크립트로 자동화 권장) |
| 빌드 결과물·각종 캐시 | 필요에 따라 재빌드 |
| 로컬 설정 파일류 | 필요한 것을 개별적으로 복사 |
.env 복사 누락은 "환경 변수를 읽지 못해 실행 실패"하는 형태로 자주 발생하므로, 초기에 해결해 둡니다.
# 새로운 worktree를 만든 후 가장 먼저 할 일
cp ../my-app/.env ./.env
npm install
2. 포트 충돌
여러 worktree에서 개발 서버를 동시에 실행하면, 기본 포트(예: 3000)가 충돌합니다.
Error: listen EADDRINUSE: address already in use :::3000
worktree마다 포트를 변경하거나, 환경 변수(Environment Variable)로 전환할 수 있도록 설정해 둡니다.
PORT=3001 npm run dev # worktree A는 3001, B는 3002... 와 같이 할당
3. 공유되는 외부 리소스의 경합
파일은 분리할 수 있어도, worktree 외부에 있는 공유 리소스는 분리되지 않습니다. 대표적인 예:
- 로컬 DB (Local DB): 여러 에이전트가 동일한 DB에 마이그레이션 (Migration)을 적용하면 스키마가 깨질 수 있음
- 캐시/메시지 큐 등의 미들웨어 (Middleware): 상태를 공유하게 됨
- 외부 API의 속도 제한 (Rate Limit) 및 과금: 병렬 실행 시 한꺼번에 소비됨
DB는 worktree마다 스키마 이름이나 DB 이름을 분리하거나, Docker로 격리하는 등의 대책이 필요합니다. **"디스크 상의 파일은 병렬화할 수 있지만, 그 너머의 상태는 별개의 문제"**라는 인식이 중요합니다.
4. 동일한 브랜치는 두 곳에서 열 수 없음
앞서 언급했듯이, 기본적으로 1브랜치 = 1worktree입니다. "같은 브랜치로 두 가지 실험을 하고 싶다"면, 브랜치를 나누거나 --detach를 사용합니다.
5. 뒷정리를 잊지 말 것
방치된 worktree와 브랜치가 쌓이면, git worktree list가 어지러워져 어떤 것이 살아있는지 알 수 없게 됩니다. 머지(Merge)하면 remove, 디렉토리를 수동으로 삭제했다면 prune 하는 것을 습관화해야 합니다.
보충: 에이전트가 무관한 디렉토리를 건드리지 않게 하기
worktree를 원래 리포지토리(Original Repository) 내부 (예: my-app/worktrees/feature-a)에 두면, 도구에 따라 상위 디렉토리의 파일 검색이나 빌드가 자식 worktree까지 포함될 수 있습니다. 기본적으로는 리포지토리 외부(형제 디렉토리)에 두는 것이 무난합니다. 배치 장소를 통일해 두면 뒷정리나 스크립트화도 쉬워집니다.
병렬 개발의 고충과 앞으로 시도해보고 싶은 것
지금까지 장점 중심으로 작성했지만, 실제로 해보면 은근히 힘든 점도 있습니다.
node_modules가 worktree 수만큼 증가함
가장 신경 쓰이는 부분입니다. node_modules는 Git 관리 대상이 아니므로, worktree를 만들 때마다 npm install이 필요하며, 동일한 의존성 패키지의 실체가 worktree 수만큼 디스크에 복제됩니다. 병렬 수를 늘릴수록 설치 대기 시간과 디스크 사용량도 쌓여갑니다.
이 문제는 pnpm으로 해결할 수 있지 않을까 생각하고 있습니다. pnpm은 패키지 실체를 글로벌 스토어(Content-addressable store)에 하나만 두고, 각 node_modules에서는 하드 링크(Hard link)로 공유하는 방식이므로, worktree를 늘려도 디스크 소비를 억제할 수 있을 것 같습니다. 상세한 메커니즘은 공식 문서에 설명되어 있습니다.
아직 실제로 시도해보지는 못했으므로, 도입해본 뒤 다시 정리하도록 하겠습니다.
결국, 인간 측이 병목(Bottleneck)이 된다
에이전트를 병행시키면 코드가 완성되는 속도는 올라가지만, 리뷰하고 반영할지를 판단하는 것은 여전히 나 혼자입니다. 병렬 수를 욕심내면 리뷰 대기 중인 브랜치가 쌓이게 되고, 컨텍스트 스위칭(Context Switching) 비용도 만만치 않습니다. 자신이 처리할 수 있는 수준(체감상 2~3개 병렬)으로 억제하는 것이 현실적이라고 느낍니다.
요약
- AI 에이전트를 여러 개 동시에 실행하는 병렬 개발에서는, 1리포지토리 = 1작업 디렉토리라는 제약이 가장 큰 걸림돌이 됨
git worktree는 이력과 브랜치를 공유한 채로 작업 디렉토리만 여러 개로 늘리는 Git 표준 메커니즘- 1태스크 = 1worktree = 1에이전트로 할당하면, 파일 충돌 없이 진정한 병렬 작업이 가능하며 여러 접근 방식을 안전하게 비교할 수 있음
- 반면,
node_modules,.env등 Git 관리 외의 것은 인계되지 않으며, 포트·DB 등 외부 리소스는 경합할 수 있고, 뒷정리가 필요하다는 주의점이 있음
"AI에게 맡기는 양"을 늘리고 싶다면, 맡길 작업 장소를 늘리는 것——그 가장 솔직한 수단이 git worktree입니다.
참고 자료
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기