에이전트 팬아웃과 git 워크트리: 충돌 없는 병렬 편집의 비밀
병렬 처리는 약속하기는 쉽지만 안전하게 만들기는 어렵습니다. Muse Code의 해답은 오래되고 검증된 git 기술을 정확한 자리에 쓰는 것이었습니다.
부모 하나, 쓰기 가능한 자식 여럿
Muse Code의 동작 원리는 단순한 규칙 하나로 요약됩니다. 작업이 여러 개의 독립적인 태스크로 나뉘면, 그 태스크들은 자동으로 별도의 에이전트에게 팬아웃됩니다. 부모 에이전트가 태스크마다 쓰기 권한을 가진 자식 에이전트를 하나씩 띄우는 구조입니다. 별도의 설정도 필요 없고, 특별한 병렬 모드를 켤 필요도 없습니다. 작업이 병렬화할 만큼 크다면 분해와 분배가 그냥 기본 동작입니다.
여기서 당연한 질문이 하나 떠오릅니다. 여러 에이전트가 같은 저장소에서 동시에 코드를 고치는데, 왜 머지 충돌과 덮어쓰기 지옥이 벌어지지 않을까요?

실제 팬아웃 세션의 모습입니다. 게임 하나에 태스크 6개, 4개는 머지 완료, 2개는 아직 실행 중 — 각각 .muse/worktrees/ 아래 자기만의 워크트리에서 돌아가고, 메인 체크아웃은 손끝 하나 건드리지 않습니다.
워크트리: git답게 격리하기
모든 자식 에이전트는 자기만의 git worktree를 받습니다. 메인 저장소와 히스토리는 공유하지만 작업 디렉터리와 브랜치는 별도인, 독립된 체크아웃입니다. 두 자식이 같은 파일을 각자의 워크트리에서 수정해도 작업 도중에는 서로의 변경 사항을 볼 일이 없습니다. 구조적으로 충돌 자체가 일어날 수 없는 것입니다.
그만큼 중요한 점이 하나 더 있습니다. 내 작업 디렉터리는 항상 깨끗하게 유지된다는 것입니다. 에디터에 열어둔 디렉터리를 에이전트가 건드리는 일은 없습니다. 커서 아래에서 코드가 움직이지 않고, 에이전트가 만들다 만 수정본이 diff에 끼어들지 않으며, 에이전트의 작업이 마음에 들지 않으면 워크트리째 버리면 그만입니다. 변경 사항이 내 브랜치에 도달하는 것은 작업이 끝나고 리뷰를 통과한 뒤뿐입니다.
왜 그냥 브랜치나 컨테이너가 아닌가
일반 브랜치는 작업 디렉터리 하나를 공유합니다. 작업 도중에 브랜치를 전환하면 실행 중인 에이전트의 발밑에서 양탄자를 빼는 꼴이 됩니다. 컨테이너나 저장소 전체 클론을 쓰는 방법도 있지만 너무 무겁습니다. 객체 저장소가 중복되고, 셋업이 느리고, 머지도 번거롭습니다. 워크트리는 딱 그 중간 지점을 짚습니다. 생성은 거의 즉시 끝나고, git 객체 데이터베이스는 공유하며, 자식이 끝낸 브랜치를 다시 합치는 것도 평범한 git 작업일 뿐입니다. 믿어야 할 커스텀 동기화 레이어도, 디버깅해야 할 독자 규격 상태도 없습니다.
기능 6개를 동시에, 실제로
출시 데모는 이 메커니즘을 전면에 내세웠습니다. 게임 개발 예제에서 Muse Code는 게임 기능 6개를 동시에 만들었는데, 에이전트마다 자기 워크트리에서 작업했고 모든 브랜치가 깔끔하게 머지되었습니다. 이것이 실질적인 이득입니다. 여러 기능을 만드는 스프린트의 총 소요 시간이 모든 태스크의 합이 아니라, 가장 오래 걸리는 태스크 하나의 시간에 수렴하는 것입니다.
레시피로 직접 해보기
에이전트 팬아웃은 Meta가 쿡북 레시피로 제공하는 세 가지 패턴 중 하나입니다. 큰 작업 하나를 서브에이전트들에게 쪼개 맡기되, 도중에 아무것도 충돌하지 않게 하는 패턴이죠. 실행 가능한 버전은 쿡북에 있습니다. 그리고 팬아웃된 작업이야말로 나중에 감사하고 싶어질 종류의 작업이기에, 모든 자식의 생성, 툴 호출, 머지는 이벤트 로그에 빠짐없이 기록됩니다. 병렬로 실행됐다는 이유로 기록에서 빠지는 일은 없습니다.