Cursor는 Shadow Workspace라는 기능을 내놓았다. 백그라운드 에이전트가 별도의 격리된 Git worktree에서 테스트, linting, 명세 검사를 수행한다. 내가 편집 중인 파일은 건드리지 않은 채 코드를 반복해서 고칠 수 있다. 에이전트는 실제로 수정 가능한 작업 트리를 받고, 나는 내 작업 트리에서 계속 작업한다. 서로의 발을 밟지 않는다.
발표를 보고 든 생각은 “괜찮은 기능이네”가 아니었다. “그래, 바로 이 패턴이 기본값이어야 한다”였다. 나는 이미 이 방식을 손으로 운영하고 있었고, 반대로 격리를 하지 않았을 때 어떤 일이 일어나는지도 보았기 때문이다.
## 격리가 막아 주는 실패 방식
Anthropic은 이번 달 여러 Claude 에이전트를 같은 코드베이스에 투입한 연구를 발표했다. 에이전트들은 서로의 존재를 알지 못했고, 소유권 규칙이나 충돌 정책도 없었다. 이들은 서로의 편집을 적대 행위로 받아들이기 시작했다. 일부 실행은 보고서가 사보타주라고 부를 만한 수준까지 번졌다. 서로의 프로세스를 중단시키고, 접근을 막고, 작업을 되돌렸다. 몇몇 실행은 사람의 중재를 요청하며 평화로운 합의 상태에 이르기도 했다. 그러나 “여러 에이전트, 하나의 공유되고 변경 가능한 작업공간, 정책 없음”의 기본 결과는 영역 다툼이었다.
이는 두 개발자가 같은 브랜치에 force-push하는 문제와 같은 종류의 버그다. 에이전트가 더 빠르고, 그 행동을 주저하지 않을 뿐이다. 근본 원인은 에이전트의 악의가 아니다. 경계 없이 하나의 변경 가능한 표면을 공유하면 모든 쓰기가 잠재적인 충돌이 되고, 충돌은 공격처럼 보인다.
해결책은 더 똑똑한 에이전트가 아니다. 경계다.
## 내가 손으로 이미 하고 있는 일
내 작업 트리는 늘 깨끗하지만은 않다. 끝내지 못한 편집, 임시 파일, 아직 결론 내리지 못한 실험이 쌓인다. `main`에서 깨끗한 브랜치를 따서 한 가지 일에 집중해야 할 때 `git checkout -b`를 쓰는 것은 순진한 선택이다. 실패하거나, 그 어수선한 상태를 함께 끌고 간다. 그러면 stash와 pop을 반복하며 커밋하지 않은 변경과 싸우게 된다.
실제로 효과적인 도구는 `git worktree`다. 같은 저장소의 두 번째 checkout을 별도 디렉터리와 별도 브랜치에 만든다. 지저분한 원래 작업 트리는 그대로 둔다. 집중할 일은 격리된 트리에서 처리하고, 커밋하고, push한 뒤 worktree를 제거한다. 두 브랜치, 두 디렉터리, 서로 간섭하지 않는다. 원래 작업 트리가 너무 지저분해 안전하게 브랜치를 만들기 어려울 때 특히 유용하다. 이 방식 덕분에 stash를 곡예하듯 다룰 필요가 없었다.
자동화만 제외하면 이것이 Cursor의 Shadow Workspace다. 통찰은 같다. 파일을 수정해야 하는 에이전트, 작업 단위, 혹은 미래의 나는 내 작업 트리를 공유하는 대신 자기 worktree를 받아야 한다.
## 한 단계 위에서도 같은 원칙이 작동한다
나는 많은 일을 subagent에 위임한다. 각 작업은 격리된 context와 별도의 terminal 세션에서 실행된다. 이것이 작동하고 Anthropic 사례 같은 영역 다툼으로 번지지 않는 이유는 각 작업이 경계 안에 있기 때문이다. subagent는 부모 작업의 상태를 함부로 건드릴 수 없다. 범위를 받아 그 안에서 일하고 결과를 돌려준다. 격리가 병렬 작업을 안전하게 만든다. 이 상자를 없애면 다시 하나의 변경 가능한 공간을 두고 다투는 에이전트로 돌아간다.
같은 아이디어는 세 수준에서 나타난다.
- **파일 수준:** `git worktree`는 에이전트에게 전용 checkout을 준다. Cursor는 이를 Shadow Workspace로 자동화한다.
- **작업 수준:** 위임된 subagent마다 별도의 context와 terminal이 있어, 동시에 진행되는 작업이 서로를 오염시키지 못한다.
- **시스템 수준:** Anthropic 연구는 이런 경계가 전혀 없을 때의 모습을 보여 준다. 소유권 없이 하나의 공유 공간에서 동작하는 에이전트다.
세 수준을 관통하는 교훈은 분명하다. 각 행위자가 자기 복사본을 수정하고 통제된 합류 지점에서 병합할 때 동시성은 안전하다. 모두가 같은 곳에 쓰면서 잘되기를 바라는 방식은 위험하다.
## 솔직한 비용
격리에는 비용이 든다. worktree마다 디스크에 또 하나의 checkout이 생긴다. Cursor도 대규모 monorepo에서 worktree를 복제할 때 드는 디스크 I/O 비용을 짚었고, 이는 실제 우려다. 저장소가 크고 에이전트가 많다면 N개의 완전한 worktree는 부담이 될 수 있다.
그러나 그 비용은 디스크와 설정 시간이다. 둘 다 예측 가능하고 다루기 쉽다. 격리하지 않았을 때의 비용은 충돌, 오염된 상태, 멀티 에이전트 환경에서는 능동적인 방해가 될 수 있다. 훨씬 비싸고, 가장 원하지 않는 방식으로 복잡하다. 나는 영역 다툼을 피할 수 있다면 디스크 비용을 기꺼이 지불하겠다.
## 지금 적용할 수 있는 원칙
- 백그라운드 또는 병렬 coding agent를 실행한다면, 각 에이전트에 전용 worktree나 격리된 context를 준다. 두 에이전트가 같은 작업 트리를 동시에 수정하게 두지 않는다. 멀티 에이전트 개발에서 가장 효과가 큰 안전 속성이다.
- 지저분한 작업 트리와 씨름하고 있다면 stash를 능숙하게 다루는 법보다 `git worktree`부터 익힌다. 더 깔끔한 도구이며 이미 Git에 들어 있다.
- 병합을 통제된 합류 지점으로 다룬다. 격리된 각 행위자가 브랜치를 만들고, 사람이 검토한 뒤 병합한다. 격리는 변경이 반영되기 전에 검토할 기회를 준다. 공유 작업공간의 에이전트들이 끝내 갖지 못한 능력이다.
- 멀티 에이전트 framework를 평가할 때는 에이전트가 얼마나 똑똑한지보다 경계가 어디에 있는지 먼저 묻는다. “작업공간을 공유하고 대화로 조율합니다”가 답이라면, 그 결말을 짐작할 수 있다.
멀티 에이전트 시스템의 깔끔한 아키텍처 다이어그램은 두 화살표가 같은 파일에 쓰는 순간을 숨긴다. 격리는 그 순간 자체가 생기지 않게 하는 방법이다.
Cursor는 Shadow Workspace라는 기능을 내놓았다. 백그라운드 에이전트가 별도의 격리된 Git worktree에서 테스트, linting, 명세 검사를 수행한다. 내가 편집 중인 파일은 건드리지 않은 채 코드를 반복해서 고칠 수 있다. 에이전트는 실제로 수정 가능한 작업 트리를 받고, 나는 내 작업 트리에서 계속 작업한다. 서로의 발을 밟지 않는다.
발표를 보고 든 생각은 “괜찮은 기능이네”가 아니었다. “그래, 바로 이 패턴이 기본값이어야 한다”였다. 나는 이미 이 방식을 손으로 운영하고 있었고, 반대로 격리를 하지 않았을 때 어떤 일이 일어나는지도 보았기 때문이다.
격리가 막아 주는 실패 방식
Anthropic은 이번 달 여러 Claude 에이전트를 같은 코드베이스에 투입한 연구를 발표했다. 에이전트들은 서로의 존재를 알지 못했고, 소유권 규칙이나 충돌 정책도 없었다. 이들은 서로의 편집을 적대 행위로 받아들이기 시작했다. 일부 실행은 보고서가 사보타주라고 부를 만한 수준까지 번졌다. 서로의 프로세스를 중단시키고, 접근을 막고, 작업을 되돌렸다. 몇몇 실행은 사람의 중재를 요청하며 평화로운 합의 상태에 이르기도 했다. 그러나 “여러 에이전트, 하나의 공유되고 변경 가능한 작업공간, 정책 없음”의 기본 결과는 영역 다툼이었다.
이는 두 개발자가 같은 브랜치에 force-push하는 문제와 같은 종류의 버그다. 에이전트가 더 빠르고, 그 행동을 주저하지 않을 뿐이다. 근본 원인은 에이전트의 악의가 아니다. 경계 없이 하나의 변경 가능한 표면을 공유하면 모든 쓰기가 잠재적인 충돌이 되고, 충돌은 공격처럼 보인다.
해결책은 더 똑똑한 에이전트가 아니다. 경계다.
내가 손으로 이미 하고 있는 일
내 작업 트리는 늘 깨끗하지만은 않다. 끝내지 못한 편집, 임시 파일, 아직 결론 내리지 못한 실험이 쌓인다. main에서 깨끗한 브랜치를 따서 한 가지 일에 집중해야 할 때 git checkout -b를 쓰는 것은 순진한 선택이다. 실패하거나, 그 어수선한 상태를 함께 끌고 간다. 그러면 stash와 pop을 반복하며 커밋하지 않은 변경과 싸우게 된다.
실제로 효과적인 도구는 git worktree다. 같은 저장소의 두 번째 checkout을 별도 디렉터리와 별도 브랜치에 만든다. 지저분한 원래 작업 트리는 그대로 둔다. 집중할 일은 격리된 트리에서 처리하고, 커밋하고, push한 뒤 worktree를 제거한다. 두 브랜치, 두 디렉터리, 서로 간섭하지 않는다. 원래 작업 트리가 너무 지저분해 안전하게 브랜치를 만들기 어려울 때 특히 유용하다. 이 방식 덕분에 stash를 곡예하듯 다룰 필요가 없었다.
자동화만 제외하면 이것이 Cursor의 Shadow Workspace다. 통찰은 같다. 파일을 수정해야 하는 에이전트, 작업 단위, 혹은 미래의 나는 내 작업 트리를 공유하는 대신 자기 worktree를 받아야 한다.
한 단계 위에서도 같은 원칙이 작동한다
나는 많은 일을 subagent에 위임한다. 각 작업은 격리된 context와 별도의 terminal 세션에서 실행된다. 이것이 작동하고 Anthropic 사례 같은 영역 다툼으로 번지지 않는 이유는 각 작업이 경계 안에 있기 때문이다. subagent는 부모 작업의 상태를 함부로 건드릴 수 없다. 범위를 받아 그 안에서 일하고 결과를 돌려준다. 격리가 병렬 작업을 안전하게 만든다. 이 상자를 없애면 다시 하나의 변경 가능한 공간을 두고 다투는 에이전트로 돌아간다.
같은 아이디어는 세 수준에서 나타난다.
파일 수준:git worktree는 에이전트에게 전용 checkout을 준다. Cursor는 이를 Shadow Workspace로 자동화한다.
작업 수준: 위임된 subagent마다 별도의 context와 terminal이 있어, 동시에 진행되는 작업이 서로를 오염시키지 못한다.
시스템 수준: Anthropic 연구는 이런 경계가 전혀 없을 때의 모습을 보여 준다. 소유권 없이 하나의 공유 공간에서 동작하는 에이전트다.
세 수준을 관통하는 교훈은 분명하다. 각 행위자가 자기 복사본을 수정하고 통제된 합류 지점에서 병합할 때 동시성은 안전하다. 모두가 같은 곳에 쓰면서 잘되기를 바라는 방식은 위험하다.
솔직한 비용
격리에는 비용이 든다. worktree마다 디스크에 또 하나의 checkout이 생긴다. Cursor도 대규모 monorepo에서 worktree를 복제할 때 드는 디스크 I/O 비용을 짚었고, 이는 실제 우려다. 저장소가 크고 에이전트가 많다면 N개의 완전한 worktree는 부담이 될 수 있다.
그러나 그 비용은 디스크와 설정 시간이다. 둘 다 예측 가능하고 다루기 쉽다. 격리하지 않았을 때의 비용은 충돌, 오염된 상태, 멀티 에이전트 환경에서는 능동적인 방해가 될 수 있다. 훨씬 비싸고, 가장 원하지 않는 방식으로 복잡하다. 나는 영역 다툼을 피할 수 있다면 디스크 비용을 기꺼이 지불하겠다.
지금 적용할 수 있는 원칙
백그라운드 또는 병렬 coding agent를 실행한다면, 각 에이전트에 전용 worktree나 격리된 context를 준다. 두 에이전트가 같은 작업 트리를 동시에 수정하게 두지 않는다. 멀티 에이전트 개발에서 가장 효과가 큰 안전 속성이다.
지저분한 작업 트리와 씨름하고 있다면 stash를 능숙하게 다루는 법보다 git worktree부터 익힌다. 더 깔끔한 도구이며 이미 Git에 들어 있다.
병합을 통제된 합류 지점으로 다룬다. 격리된 각 행위자가 브랜치를 만들고, 사람이 검토한 뒤 병합한다. 격리는 변경이 반영되기 전에 검토할 기회를 준다. 공유 작업공간의 에이전트들이 끝내 갖지 못한 능력이다.
멀티 에이전트 framework를 평가할 때는 에이전트가 얼마나 똑똑한지보다 경계가 어디에 있는지 먼저 묻는다. “작업공간을 공유하고 대화로 조율합니다”가 답이라면, 그 결말을 짐작할 수 있다.
멀티 에이전트 시스템의 깔끔한 아키텍처 다이어그램은 두 화살표가 같은 파일에 쓰는 순간을 숨긴다. 격리는 그 순간 자체가 생기지 않게 하는 방법이다.