여러 AI 에이전트가 같은 코드베이스에서 작업할 때 서로 밟지 않게 어떻게 조율하는가?
복잡한 구현을 위한 계획-후-실행 패턴을 실험해왔다. 하나의 에이전트가 순차적으로 작업을 진행하는 대신, 작업을 “웨이브"로 나눈다—서로 의존하지 않기 때문에 이론적으로 병렬로 실행할 수 있는 작업 그룹이다.
결과가 흥미롭다. 속도 향상은 실제로 있지만, 이론적 병렬성과 실제 병렬성 사이의 간극이 AI 조율에 대해 생각하는 방법을 알려줬다.
WHY: 순차는 느리다
일곱 개의 관련 변경이 필요한 기능을 생각해보자:
- 설정 스키마 확장 (기반)
- 이벤트 훅 시스템 추가
- 리뷰 체크 로직 추가
- 커밋 강제 추가
- 이슈 생성 도구 향상
- PR 생성 도구 추가
- 문서 업데이트
순차적으로 하면, 다음을 시작하기 전에 각 작업이 완료되기를 기다린다. 각각 10분이 걸리면, 70분의 벽시계 시간이다—작업 2, 3, 4가 동시에 실행될 수 있었는데도.
통찰: 대부분의 멀티 작업 구현은 병렬성을 허용하는 의존성 구조를 가지고 있다. 그 구조를 찾는 것이 더 빠른 실행의 열쇠다.
HOW: 의존성을 웨이브로 매핑
“웨이브"는 동시에 실행할 수 있는 작업 집합이다. 같은 웨이브의 작업은 서로에 대한 의존성이 없다—이전 웨이브가 완료되면 모두 시작할 수 있다.
플랜 에이전트가 일곱 작업 예제를 구조화한 방법:
웨이브 1 (즉시 시작):
└── 작업 1: 설정 스키마 확장 [의존성 없음]
웨이브 2 (웨이브 1 후):
├── 작업 2: 이벤트 훅 추가 [의존: 1]
├── 작업 3: 리뷰 체크 추가 [의존: 1]
└── 작업 4: 커밋 강제 추가 [의존: 1]
웨이브 3 (웨이브 2 후):
├── 작업 5: 이슈 도구 향상 [의존: 2]
└── 작업 6: PR 도구 추가 [의존: 2, 3, 4]
웨이브 4 (웨이브 3 후):
└── 작업 7: 문서 업데이트 [의존: 5, 6]
크리티컬 패스: 작업 1 → 작업 2 → 작업 6 → 작업 7
예상 속도 향상: 순차보다 ~35% 빠름
크리티컬 패스는 의존 작업의 가장 긴 체인이다. 아무리 병렬화해도, 크리티컬 패스보다 빠르게 갈 수 없다. 하지만 크리티컬 패스에 없는 모든 것은 잠재적으로 동시에 실행될 수 있다.
의존성 그래프 구축
각 작업에 대해 묻는다: “이게 시작되기 전에 무엇이 완료되어야 하나?”
일반적인 의존성 유형:
- 스키마/타입 의존성: 정의되기 전에 새 설정 필드를 사용할 수 없음
- API 의존성: 존재하기 전에 함수를 호출할 수 없음
- 데이터 의존성: 입력이 생성되기 전에 출력을 처리할 수 없음
- 테스트 의존성: 컴포넌트가 존재하기 전에 통합을 검증할 수 없음
의존성이 없는 작업은 웨이브 1로 간다. 웨이브 1 작업에만 의존하는 작업은 웨이브 2로 간다. 그렇게 계속.
WHAT: 이론 vs. 실제
계획은 완벽해 보였다. 웨이브 2에 세 개의 독립 작업이 있었다—이벤트 훅, 리뷰 체크, 커밋 강제. 이론적으로 세 에이전트가 동시에 작업할 수 있었다.
실제로는 세 작업 모두 같은 파일을 수정했다: git-workflow-enforcer.ts.
이론적 병렬성: 작업이 논리적으로 독립적 (다른 기능) 실제 병렬성: 작업에 파일 수준 충돌 있음
여러 에이전트가 같은 파일을 동시에 편집하면, 머지 충돌, 덮어쓰인 변경, 또는 일관성 없는 코드가 된다. 실행 레이어가 계획이 병렬로 표시했음에도 웨이브 2 작업을 올바르게 직렬화했다.
파일 충돌 문제
의존성 계획과 실행 현실 사이의 간극이다:
| 의존성 수준 | 의미 | 예시 |
|---|---|---|
| 기능 의존성 | 작업 B가 작업 A의 출력 사용 | PR 도구가 이슈 번호 필요 |
| API 의존성 | 작업 B가 작업 A의 함수 호출 | 훅 시스템이 먼저 존재해야 |
| 파일 의존성 | 작업 A와 B가 같은 파일 편집 | 둘 다 같은 클래스에 메서드 추가 |
플랜 에이전트는 보통 기능과 API 의존성을 모델링한다. 파일 의존성은 더 깊은 분석이 필요하다—실행 전에 각 작업이 어떤 파일을 건드릴지 아는 것.
완화책
보수적 병렬성: 확신이 없으면 직렬화. 가끔 불필요한 직렬화의 오버헤드가 머지 충돌 해결 비용보다 낮다.
파일 인식 계획: 작업 명세에 “건드리는 파일"을 포함. 같은 파일을 수정하는 작업을 같은 웨이브로 그룹화하고, 순차적으로 실행.
충돌 감지: 병렬 웨이브를 시작하기 전에, 작업이 겹치는 파일을 대상으로 하는지 확인. 그렇다면 해당 웨이브 내에서 순차로 강등.
더 작은 파일: git-workflow-enforcer.ts가 event-hooks.ts, review-checking.ts, commit-enforcement.ts로 분리되었다면, 웨이브 2는 진정으로 병렬이었을 것이다.
실제 속도 향상
웨이브 2의 직렬화에도 불구하고, 전체 실행은 여전히 순수 순차보다 빨랐다:
- 웨이브 3과 4는 계획대로 실행됨
- 병렬 탐색 (컨텍스트 수집)이 작업 실행 전에 일어남
- 에이전트 시작 오버헤드가 더 적은 대기 사이클에 분산됨
35% 이론적 속도 향상이 대략 20% 실제 속도 향상이 되었다. 여전히 할 가치가 있다.
패턴
웨이브 기반 오케스트레이션은 작동하지만, 실제로 병렬인 것에 대한 정직함이 필요하다:
- 의존성 매핑 - 무엇이 무엇에 의존하는지 그래프 구축
- 웨이브로 그룹화 - 의존성이 충족된 작업들이 함께 실행
- 충돌 확인 - 파일 수준, 상태 수준, 테스트 수준
- 폴백과 함께 실행 - 충돌 감지되면 직렬화
- 실제 속도 향상 측정 - 이론이 실제와 거의 일치하지 않음
가장 큰 교훈: 의존성 분석은 싸다; 충돌 해결은 비싸다. 계획에서 과도하게 병렬화하되, 현실이 동의하지 않을 때 실행 레이어가 직렬화할 준비를 갖추라.
복잡한 멀티 에이전트 작업에서 이 웨이브 패턴이 내 기본이 되었다. 명시적인 의존성 사고를 강제하고, 웨이브 사이에 자연스러운 체크포인트를 제공하며, 순차 계획이 놓치는 병렬성 기회를 드러낸다.
파일 diff를 보기 전까지 이론적 속도 향상 숫자를 믿지 마라.
