
git worktree로 AI 코딩 에이전트의 충돌을 방지하는 6가지 규칙 — 병렬 개발 실무 템플릿
요약
AI 코딩 에이전트의 병렬 작업 시 발생하는 파일 충돌과 리소스 경합을 방지하기 위해 Git worktree를 활용하는 실무 가이드를 제공합니다. 작업 공간, DB, 포트 등 실행 자원을 분리하는 '병렬 작업 경계' 설계의 중요성을 강조합니다.
핵심 포인트
- Git worktree를 사용하여 하나의 리포지토리에 여러 작업 디렉토리를 생성
- 1개 태스크당 1개 브랜치와 1개 worktree를 할당하여 격리
- DB, 포트, 캐시 등 실행 자원까지 분리하는 운영 경계 설계 필요
- AI의 역할을 단순 구현에서 경계 설계로 확장하는 인간의 역할 강조
업데이트 날짜: 2026-07-23
두 개의 AI 코딩 에이전트에게 각각 다른 수정을 요청했는데, 같은 작업 폴더에서 파일을 수정하여 한쪽의 변경 사항을 다른 쪽이 지워버리는 경우가 있습니다.
병렬화를 시도했지만, 결국 마지막에는 차이점(diff)을 추적하는 고고학 작업이 되어버립니다. 이건 정말 너무 아까운 일이죠.
결론부터 말씀드리면, AI를 병렬화하기 전에 작업 공간을 분리하는 것이 우선입니다. Git의 worktree를 사용하면, 하나의 리포지토리(repository)에 여러 개의 작업 디렉토리(directory)를 연결하여 서로 다른 브랜치(branch)를 동시에 checkout할 수 있습니다.
하지만 worktree를 만드는 것만으로는 불충분합니다. 코드의 위치는 분리되더라도, 동일한 DB, 동일한 포트(port), 동일한 파일 담당, 그리고 뒷정리 판단은 자동으로 분리되지 않습니다.
따라서 이 기사에서는 AI 병렬 개발의 사고를 줄이는 6가지 규칙을 소개합니다.
- 1개 태스크를 1개 브랜치 · 1개 worktree로 구성하기
- 변경해도 좋은 파일을 미리 분리하기
- DB · 포트 · 캐시(cache)도 분리하기
- 종료 전에 clean gate를 통과하기
- 의존 관계 순서대로 통합하기
- 정식적인
git worktree remove로 마무리하기
저는 이 전체를 **「병렬 작업 경계」**라고 부릅니다. AI마다 코드, 브랜치, 실행 자원, 종료 조건을 분리하는 운영 경계입니다.
우선 10분 만에 두 개의 작업 공간이 동시에 존재하는 단계까지 진행해 봅시다.
working tree는 현재 실제로 파일을 편집하고 있는 작업 디렉토리입니다.
branch는 변경 이력의 목적지에 붙이는 이름입니다.
worktree는 동일한 Git 리포지토리에 추가하는 별도의 작업 디렉토리입니다. 비유하자면, 같은 설계도를 참조하면서 책상을 두 개 준비하는 것과 같습니다.
통상적인 git switch는 하나의 책상에서 자료를 교체합니다. git worktree는 책상 자체를 늘립니다. 한쪽에서 미완성된 변경 사항을 펼쳐둔 채로, 다른 한쪽에서 별도의 브랜치를 작업할 수 있습니다. Git 공식 문서에서도 여러 개의 working tree로 여러 개의 branch를 동시에 checkout할 수 있는 메커니즘으로 설명하고 있습니다.
| 담당 | 맡기는 것 | 맡기지 않는 것 |
|---|---|---|
| 인간 | 태스크 분할, 담당 파일, 통합 순서, 삭제 승인 | 각 worktree 내의 단순 구현 |
| ... |
AI는 코드를 쓰는 속도를 높일 수 있습니다. 하지만 "이 두 태스크는 동일한 DB migration을 건드리니까 직렬로 처리하자"라는 판단은, 리포지토리 전체의 의도를 가진 인간의 일입니다.
AI에게 맡기는 범위를 늘릴수록 인간의 일이 줄어드는 것이 아니라, 경계를 설계하는 일로 옮겨갑니다. 이건 마치 팀 개발 그 자체와 같습니다.
메인 리포지토리에서 다음을 실행합니다. main은 자신의 기준 branch로 교체해 주세요.
git fetch origin
git worktree add -b agent/api-tests ../project-agent-api origin/main
git worktree add -b agent/docs-fix ../project-agent-docs origin/main
...
이렇게 나누어집니다.
project/ # 인간이 통합을 확인하는 메인 작업 공간
project-agent-api/ # AI A: API 테스트
project-agent-docs/ # AI B: 문서 수정
각각 확인합니다.
git -C ../project-agent-api branch --show-current
git -C ../project-agent-docs branch --show-current
agent/api-tests와 agent/docs-fix가 별도로 표시된다면 첫 번째 성공입니다. 아직 AI를 두 개 실행할 필요는 없습니다. 먼저 "충돌하지 않는 책상"을 만들 수 있었다는 점이 중요합니다.
참고로 Git은 동일한 branch를 다른 worktree에서 checkout하려고 하면 기본적으로 거부합니다. 이때 성급하게 --force를 붙이지 마세요. 공들여 만든 충돌 방지 기능을 스스로 제거하는 꼴이 됩니다.
나쁜 분리 방식은 "AI A는 프론트엔드, AI B는 백엔드"와 같이 너무 큰 단위의 담당입니다. 기간이 길어지면 양쪽 모두 설정 파일이나 타입 정의(type definition)를 건드리기 시작합니다.
좋은 분리 방식은 완료 조건까지 포함하는 작은 태스크입니다.
agent/api-tests
- 변경 대상: tests/api/**, src/api/validator.py
- 완료 조건: 대상 테스트 통과
...
브랜치(branch) 이름, 디렉터리, AI에 대한 요청을 동일한 태스크 이름으로 맞추면, 로그를 확인했을 때 혼란을 줄일 수 있습니다.
worktree는 파일을 별도의 디렉터리에 두지만, 마지막에 머지(merge)하면 동일한 히스토리로 돌아옵니다. 두 AI가 같은 행을 수정한다면 통합 시의 충돌(conflict)은 남게 됩니다.
따라서 시작하기 전에, allowed_paths와 forbidden_paths를 선언합니다.
task: api-tests
allowed_paths:
- tests/api/
...
AI에게는 "필요하다면 담당 외 영역도 수정해"가 아니라, "담당 외의 변경이 필요하다면 중단하고 이유만 보고해"라고 전달합니다. 중단하는 것은 실패가 아닙니다. 경계(boundary)가 작동했다는 증거입니다.
당신은 agent/api-tests worktree만 담당합니다.
변경 가능: tests/api/**, src/api/validator.py
변경 금지: migrations/**, package-lock.json, .github/workflows/**
...
이 부분이 worktree 관련 글에서 생략되기 쉬운 지점입니다.
디렉터리를 나누더라도 양쪽 모두 localhost:3000을 사용한다면 한쪽은 실행할 수 없습니다. 동일한 테스트 DB에 마이그레이션(migration)을 실행하면, 파일은 무사하더라도 데이터가 손상될 수 있습니다.
# agent/api-tests
export APP_PORT=3101
export TEST_DB_NAME=app_agent_api
...
분리 후보는 다음과 같습니다.
- HTTP 포트
- 테스트 DB 이름 또는 스키마(schema)
- Redis 키 접두사(key prefix)
- 임시 디렉터리
- Docker Compose 프로젝트 이름
- 브라우저 테스트 프로필
비밀 정보를 worktree마다 복사하는 것은 피해야 합니다. .env를 Git에 추가하지 말고, 기존의 안전한 비밀 관리(secret management) 체계로부터 필요한 최소한의 정보만 주입하십시오.
가장 무서운 상황은 AI의 작업이 끝났다고 생각하여 worktree를 삭제했는데, 커밋되지 않은(uncommitted) 수정 사항이 남아 있는 경우입니다.
Git의 status --porcelain은 스크립트에서 다루기 위한 안정적인 형식입니다. 출력이 비어 있으면 clean 상태이며, 한 글자라도 있으면 저장되지 않은 변경 사항이 있다는 뜻입니다.
#!/usr/bin/env bash
set -euo pipefail
target="${1:?usage: check-worktree.sh PATH}"
...
이 코드는 임시 Git 리포지토리에서 clean 상태일 때는 종료 코드 0을, 추적되지 않은 파일(untracked file)이 추가된 후에는 1이 되는지 확인합니다.
이 worktree의 종료 리포트를 작성해 주세요.
- git status --short
- git diff --stat
...
두 브랜치가 모두 clean 상태더라도, 머지 순서에 따라 의미가 달라질 수 있습니다.
예를 들어 AI A가 API의 타입을 추가하고, AI B가 그 타입을 사용하는 화면을 만든다면 A가 먼저여야 합니다. 반대로 독립적인 테스트 추가와 문장 수정이라면 순서의 영향은 작습니다.
통합 전에 다음 세 가지만 나열합니다.
- 어떤 브랜치가 공개 인터페이스(public interface)를 변경하는가
- 어떤 브랜치가 그것에 의존(dependency)하는가
- 각 머지 후에 어떤 테스트를 실행할 것인가
1. agent/api-contract 를 merge
2. API contract test를 실행
3. agent/ui-client 를 최신 main에 rebase
...
두 브랜치의 차이점 요약으로부터 통합 순서의 후보를 출력해 주세요.
관점:
- 공개 API, schema, 타입, migration의 의존성
...
AI는 순서 후보를 정리할 수 있습니다. 하지만 어떤 사양(specification)을 정답으로 할지, 마이그레이션을 운영 환경에 반영할지는 인간이 결정합니다.
작업 디렉터리를 Finder나 rm -rf로 직접 삭제하면 Git 측의 관리 정보가 남을 수 있습니다. Git 공식 문서에서는 완료된 연결된 worktree(linked worktree)를 git worktree remove로 삭제하는 흐름을 안내하고 있습니다.
git worktree list
git -C ../project-agent-api status --porcelain
git worktree remove ../project-agent-api
...
remove 명령은 dirty한 (변경 사항이 있는) worktree를 기본적으로 거부합니다. 여기서도 즉시 --force를 붙이기보다는 무엇이 남아 있는지 먼저 확인하세요.
만약 디렉터리를 수동으로 삭제하여 관리 정보만 남은 상태라면, 먼저 dry-run을 실행하세요.
git worktree prune --dry-run --verbose
git worktree prune --verbose
위치를 수동으로 이동하여 연결이 깨진 경우에는 git worktree repair가 준비되어 있습니다. 추측하여 .git/worktrees를 직접 편집하는 것보다 정규 명령어를 통해 시도하는 것이 더 안전합니다.
처음부터 거대한 자동화는 필요하지 않습니다. 다음 순서만으로도 충분합니다.
# 1. 생성
git worktree add -b "agent/$TASK_NAME" "../project-$TASK_NAME" origin/main
# 2. AI에게 allowed / forbidden paths와 완료 조건을 전달
...
TASK_NAME에 외부 입력을 그대로 넣는 스크립트는 피하고, 팀에서 허가한 짧은 이름만 사용하세요. 경로를 자동 생성하는 로직일수록 입력 검증 (input validation)이 필요합니다.
반론도 남겨둡니다.
두 개의 태스크가 동일한 파일, 동일한 DB migration, 동일한 공개 API를 동시에 변경한다면, worktree를 나누더라도 본질적인 충돌은 사라지지 않습니다. 충돌이 "작업 중"에서 "merge 시"로 옮겨갈 뿐입니다.
구분 방법은 간단합니다. 두 태스크의 allowed_paths를 나열하고, 중요 파일이 겹치는지 확인합니다.
- 겹치지 않음: 병렬화하기 쉬움
- 테스트나 docs만 겹침: 소유자를 정하면 병렬화 가능
- schema, migration, 공개 타입이 겹침: 직렬화하거나, 먼저 인터페이스를 고정해야 함
작은 1개 파일 수정을 2개 병렬화하는 것도 준비와 통합 비용이 더 많이 들 수 있습니다. 비용 없이 충분한 사람이라기보다, 일반적인 1 branch로 충분한 태스크는 확실히 존재합니다.
병렬화는 목적이 아닙니다. 대기 시간을 줄이면서, 실패했을 때의 영향을 최소화하는 수단입니다.
- 동일한 branch가 다른 worktree에서 사용 중입니다.
git worktree list로 위치를 확인하고, 다른 branch를 만드세요. 안일하게 force로 우회하지 마세요. git worktree prune --dry-run --verbose로 대상을 확인한 후 prune 하세요.- 가능하다면
git worktree move를 사용하세요. 수동 이동 후에는git worktree repair를 검토합니다. - worktree의 결함이 아니라, 태스크 경계가 겹쳐 있습니다. 어느 쪽을 정답으로 할지 사람이 결정하고, 다음에는 allowed paths나 통합 순서를 먼저 고정합니다.
독립적인 소규모 태스크 2개를 골라, 다음 명령어로 작업 공간만 만드세요.
git worktree add -b agent/task-a ../project-task-a origin/main
git worktree add -b agent/task-b ../project-task-b origin/main
git worktree list
그 후에 각 태스크에 변경 가능한 경로를 3줄로 작성합니다. AI를 구동하는 것은 그 시점부터입니다.
빠르게 달리기에 앞서, 충돌하지 않는 장소를 만드세요. 미래의 자신이 차분(diff)의 고고학을 하지 않아도 된다면, 내일의 자신으로부터 "고마워요"라는 인사를 받게 될 것입니다.
- Git - git-worktree Documentation
- Git - git-status Documentation
- GitHub Docs - Managing worktrees in GitHub Desktop
생성형 AI 활용 엔지니어 & 세 아이의 아빠. AI × 개발의 실천적 지식을 매일 발신하고 있습니다 → X
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기