
AI 에이전트 6개를 병렬로 가동하여 12일 만에 웹 서비스를 실서비스로 출시한 병행 개발 설계
요약
Claude Code의 서브 에이전트 6개를 병렬로 활용하여 12일 만에 웹 서비스를 출시한 개발 설계 방식을 소개합니다. 인간은 요구사항 정의와 의사결정만 담당하고, AI 에이전트들이 역할 분담과 티켓 기반 시스템을 통해 병렬로 구현을 진행하는 아키텍처를 다룹니다.
핵심 포인트
- 구현은 병렬로, 통합은 직렬로 진행하는 원칙 준수
- 메인 세션(PM/리뷰어)과 구현 에이전트 간의 명확한 역할 분담
- BE/FE 리포지토리 분리를 통한 PR 독립성 및 충돌 최소화
- 설계 판단을 메인 세션에서 일원화하여 에이전트 간 사상 일치
- GitHub Issue와 Ticket-driven 방식을 통한 자동화된 진척 관리
Claude Code의 서브 에이전트를 최대 6개 병렬로 돌려, 인간은 코드를 단 한 줄도 쓰지 않고 프리랜서 매칭 서비스(scrum for freelance)를 12일 만에 실서비스(Production)로 출시했습니다.
체험기는 Qiita에 작성했으므로(→https://qiita.com/suzuyoshi/items/c1d965a0d5bdc0c691c6), 여기에서는 「왜 병행 AI 에이전트 개발이 파탄 나지 않았는가」의 설계만을 기술적으로 상세히 설명합니다. 결론부터 말하자면, 인간의 팀 개발에서 당연하게 하는 일을 AI에게도 당연하게 시켰을 뿐입니다. 다만 「당연함」을 명문화하여 규칙화하지 않으면 AI는 지킬 수 없으므로, 그 명문화의 내용이 이 기사입니다.
전체 아키텍처
인간(Product Owner)
└─ 메인 세션(PM 겸 리뷰어 겸 머지 권한자)
├─ 구현 에이전트 1(api worktree A・전용 테스트 DB)
...

역할 분담이 모든 시작점입니다.
메인 세션: 요구사항을 티켓화하고, 에이전트를 투입하며, PR을 리뷰·머지하고, 컨플릭트(Conflict)를 해결한다. 코드를 작성하지 않는다 -
구현 에이전트: 1티켓 = 1에이전트. worktree에서 구현하고, 테스트와 실기 확인을 통해 PR을 만든다. 머지하지 않는다 -
인간: 요구사항과 의사결정만 담당. SaaS 대시보드(AWS/Stripe 등) 조작도 인간의 담당
「구현은 병렬·통합은 직렬」. 이것이 유일하고도 최대의 원칙입니다.
리포지토리 전략: BE/FE 분리와 릴레이 방식
Rails(API 모드)와 Next.js를 별도 리포지토리로 구성했습니다. 병행 AI 개발과 궁합이 좋았던 점은 다음과 같습니다:
PR의 입도가 자연스럽게 닫힌다. BE의 PR은 spec이 green이면 완결, FE의 PR은 tsc/lint/build + 실기 확인으로 완결됩니다. 혼재된 리포지토리라면 「BE만 수정하고 FE는 망가진 상태인 PR」이 생기기 쉽습니다 -
릴레이가 명확하다. 기능은 BE → FE의 2개 티켓으로 분할하며, BE의 PR이 머지된 시점에 해당 PR 본문(응답 사양을 작성하게 해둠)을 FE 에이전트에 대한 지시 사항으로 복사하여 붙여넣습니다. BE PR에 「프론트엔드용 사양」 섹션을 반드시 작성하게 하는 것이 요령입니다 -
컨플릭트 측면이 반감된다. 6개 레인 중 api 3 + front 3와 같이 분산할 수 있어, 동일 리포지토리 내의 충돌이 줄어듭니다
티켓 드리븐(Ticket-driven): AI에게 작성하게 하는 issue의 형태
아무리 작은 수정이라도 착수 전에 GitHub issue를 생성합니다. issue에는 반드시 3가지를 작성하게 합니다(작성하는 것은 메인 세션):
## 개요 ← 무엇을・왜(사용자 확정 사항은 「사용자 확정 YYYY-MM-DD」라고 명기)
## 구현 ← 설계 판단까지 포함하여 작성(엔드포인트・데이터 구조・제약 사항)
## 수락 조건 ← 테스트 가능한 형태로
포인트는 「구현」란에서 설계 판단을 미리 끝내두는 것입니다. 에이전트에게 설계부터 맡기면 병행 레인 간에 사상이 어긋납니다. 설계는 메인 세션에서 일원화하고, 에이전트에게는 「issue 본문 필독」이라고 지시합니다. 이를 통해 6개 레인이 동일한 설계 사상으로 움직입니다.
티켓은 GitHub Projects(Kanban)에 자동으로 추가되게 하여 Todo → In Progress → Done으로 흐르게 합니다. PR 본문에 Closes #N을 반드시 넣게 하면, 머지와 동시에 issue가 닫히고 보드가 Done으로 이동하므로 진척 관리 비용이 제로가 됩니다(이 표기법을 잊어버려 자동 클로즈가 되지 않는 사고가 한 번 있었기에, 지시 템플릿에 박아 넣었습니다).
worktree 분리: 6개 레인이 충돌하지 않는 물리적 설계
각 에이전트의 작업 환경은 다음과 같이 분리합니다.
# 에이전트 투입 시 메인 세션이 준비시키도록 함
git worktree add /tmp/.../wt-<기능명> -b feature/<기능명> origin/main
| 리소스 | 분리 방법 |
|---|---|
| 작업 트리 | git worktree (메인 트리는 건드리지 않음) |
| 데이터베이스 | DATABASE_URL 덮어쓰기로 레인 전용 DB (예: ..._wt_161_test) |
| Docker 프로젝트 | docker compose -p <레인명>으로 네임스페이스 분리 |
| dev 서버 | FE는 레인마다 전용 포트 (8114, 8115, …) |
.env | 모든 레인 변경 금지 (인간이 관리) |
특히 테스트 DB의 분리는 필수입니다. 병행 레인(Parallel Lane)이 동일한 테스트 DB를 사용하면, migration 상태가 뒤섞여 모든 레인의 spec이 깨지게 됩니다.
주의할 점은, Gemfile.lock을 변경하는 레인(gem 추가)의 경우 dev 컨테이너의 이미지와 의존성이 어긋나 compose build가 통과하지 못하게 된다는 것입니다. 저희는 "가동 중인 이미지에 worktree를 bind-mount하여, 전용 gem 볼륨에 bundle install을 수행한다"라는 우회 방법을 템플릿화하여, 에이전트의 지시 사항에 전례(Precedent)로서 붙여두었습니다. 이처럼 "한 번 성공한 절차를 다음 에이전트의 지시에 붙여넣는" 과정의 축적이 후반부의 안정적인 운영을 뒷받침합니다.
머지의 직렬화: 통합만큼은 병렬로 하지 않는다
구현 에이전트의 산출물은 PR(Pull Request)까지입니다. 머지(Merge)는 메인 세션이 한 번에 하나씩 수행합니다.
- 머지 순서는 메인 세션이 의존 관계에 따라 결정합니다 (BE 기반 → 그 위에 올라가는 기능 → FE 추종).
- 컨플릭트(Conflict) 해결도 메인 세션이 전담합니다. 병행 개발에서는 "옆 레인이 먼저 머지되어 내 PR이 오래된 상태가 되는 것"이 일상적이므로, PR 생성 전에 origin/main으로 rebase 하여 모든 테스트를 재실행하는 것을 에이전트의 완료 조건에 포함했습니다. 그럼에도 머지 시 충돌이 발생하면, 메인 세션이 로컬에서 rebase, 해결, 재push(에이전트를 다시 호출하는 것보다 빠름)를 수행합니다.
schema.rb로 인해 한 번 실패했던 이야기
Rails로 병행 개발을 하면 반드시 부딪히는 것이 db/schema.rb입니다.
당초에는 "레인마다 migration 번호 대역을 수동으로 할당하는" (2026071204xxxx와 같은) 운영을 했으나, 이는 하지 않는 것이 좋습니다. schema.rb의 버전 행을 수동으로 수정하는 운영이 되면서, 예상대로 재생성 결과와 한 줄이 어긋나 외래 키(Foreign Key)가 누락되었습니다.
정답은 간단합니다. bin/rails g migration의 실시간 타임스탬프 채번 + 반드시 db:migrate를 실행하여 자동 생성된 schema.rb를 커밋하는 것입니다. rebase로 충돌이 나면 수동으로 고치지 말고 migrate를 재실행하여 재생성합니다. Rails의 통상적인 운영 방식 그대로이지만, AI는 한 번 "번호 대역 할당"을 학습하면 계속 반복하려 하므로, 규칙을 명시적으로 덮어쓸 필요가 있었습니다.
품질 게이트: 머지 조건을 기계적으로 만들기
"괜찮아 보이니 머지"하는 것을 배제하고, 모든 PR에 동일한 게이트(Gate)를 부과합니다.
BE (Rails)
- 모든 spec green (전용 DB에서, 레인 단위가 아니라 전부 실행) — 옆 레인이 머지한 변경 사항과의 통합을 여기서 검출 - rebase 후에도 다시 한번 모든 spec 실행
- PR 본문에 프론트엔드용 사양, 설계 판단, Render 측 작업 내용을 명기
FE (Next.js)
tsc --noEmit/lint/build실행- Playwright를 통한 실기 시나리오 확인 (seed 사용자로 로그인 → 대상 기능 일주 → 스크린샷 육안 확인). tsc가 통과하더라도 화면은 깨질 수 있으므로, 이 부분을 생략하지 못하게 합니다. - 검증 과정에서 생성한 데이터의 뒷정리 및 dev 서버 정지까지 완료 조건에 포함

테스트는 최종적으로 2,177개 사례(30,700행)가 되었습니다. "테스트가 앱 코드의 1.5배"라는 말을 들으면 과도해 보일 수 있지만, 병행 AI 개발에서 테스트는 레인 간의 계약서로서 기능합니다. 옆 레인이 토대를 변경했다는 사실을 인간이 아닌 spec이 검출하는 구조입니다.
에이전트 지시 템플릿
구현 에이전트에 대한 지시는 매번 이 구성으로 내보냈습니다.
## 환경 (worktree 분리) ← 명령어를 포함하여 구체적으로. "전례가 있는" 우회 방법도 첨부
## 태스크 ← issue 번호 + "본문 필독"
## 전제 조건 (반드시 읽을 것) ← 의존하는 머지 완료된 PR · 준수해야 할 기존 구현 경로
...
효과적이었던 장치:
- "준수해야 할 기존 구현"을 매번 지정하기: "#149의 AiFeatureGate 패턴을 재사용"과 같이 작성하면 코드베이스의 일관성이 유지됩니다. 지정하지 않으면 매번 미묘하게 다른 구현이 생겨납니다.
- 최종 보고 포맷 지정: (PR URL · spec 결과 · FE용 사양). 다음 에이전트에 대한 지시가 해당 보고서를 복사하여 붙여넣는 것으로 끝날 수 있게 합니다.
- 금지 사항 명시: (main 직접 push 금지 ·
.env금지 · 메인 트리 수정 금지). 성선설에 기반하여 운영하지 않습니다. - "session limit 도달 시 정지 후 현황 보고": 실행 할당량을 다 썼을 때 어중간한 상태로 push를 하지 않도록 합니다.
운용 중에 발생한 일(과 대처)
- 에이전트가 「spec 실행 대기」 상태에서 멈춤: 백그라운드에서 테스트를 돌리고 대기 상태로 들어간 뒤, 그대로 턴(turn)을 종료해 버리는 습관이 있습니다. "spec은 포그라운드(foreground)에서 타임아웃(timeout)을 길게 설정하여 실행하고, 멈추지 말고 완주하라"는 지시를 추가했습니다.
- 세션 제한으로 6개 레인 전멸: 제한이 해제된 후 각 에이전트에게 "재개해 주세요. 현재 main이 여기까지 진행되었습니다"라고 보내면, 모두가 중단 지점부터 복귀합니다. 재개 메시지에 그동안의 main의 변화를 덧붙이는 것이 중요합니다.
- 동일 파일을 수정하는 레인의 조정: 계정 설정 화면을 Pro UI와 역할 변경 UI가 동시에 수정하는 등의 상황에서는 "자신의 섹션 이외에는 재구성하지 마라"를 양측에 지시하고, 그럼에도 충돌이 발생하면 메인 세션이 rebase로 해결합니다. 충돌은 발생한다는 전제하에, 해결 비용을 한 곳으로 모으는 설계입니다.
요약: AI의 수만큼 빨라지는 것은 규칙에 달려 있다
병렬 AI 에이전트 개발은 "에이전트를 늘리면 선형적으로 빨라지는" 것이 아니라, 통합·설계·규칙을 직렬의 한 점(메인 세션)으로 집약했을 때만 스케일(scale)했습니다. 반대로 말하면, worktree 분리·티켓 기반(ticket-driven)·전체 테스트 게이트(test gate)·머지(merge) 직렬화라는 지루한 규율만 지킨다면, 6개 병렬은 실용적이 됩니다.
인간의 팀 개발 지견이 그대로 적용된다는 것이, 12일간 시도하며 얻은 가장 큰 배움입니다. 콘웨이의 법칙(Conway's Law)은 AI 팀에도 적용되는 것일지도 모릅니다.
추기: 완성된 결과물은 등록 없이 볼 수 있습니다
"그래서, 이 체제로 만든 것은 어느 정도 작동하는가?"를 확인할 수 있도록, 이메일 주소 등록 없는 데모 모드를 추가했습니다. 메인 페이지의 "등록하지 않고 데모 보기"를 통해 프리랜서 관점·발주자 관점·Pro 회원 관점(AI 기능 결과 확인 가능)의 3가지를 전환하며 모든 페이지를 열람할 수 있습니다.

데모 중에는 Pro 한정 기능에 「Pro 한정」 배지가 붙으므로, 무료와 유료의 경계도 한눈에 알 수 있습니다. Pro 회원 관점에서는 AI에 의한 경력 요약이나 프로젝트 매칭 분석 결과까지 열람할 수 있습니다.

데모는 열람 전용(쓰기 작업은 서버 측에서 모두 403 처리)이며, 데모 데이터는 실제 사용자와 완전히 분리되어 있습니다. 열람자마다 익명 ID를 부여하여 행동 로그와 이탈률을 admin 화면에서 시각화하는 부분까지 포함하여, 이 데모 모드 자체도 본 기사의 체제(issue 기반 → worktree 분리 → 에이전트 구현 → 리뷰 → 전체 테스트 게이트 → 머지)로 만들었습니다. 개인 정보는 수집하지 않으니 안심하셔도 됩니다.


제작한 서비스: scrum for freelance(수수료는 첫 매칭 시에만 발생 · 지속 계약은 0원인 프리랜서 매칭)
체험기(Qiita): https://qiita.com/suzuyoshi/items/c1d965a0d5bdc0c691c6
개발의 연속: X @e8GU641fyp8wtVS
추신: 이 기사도 Claude Code가 작성했습니다. 구현한 본인이 직접 작성한 설계 해설이므로, 아마 세계에서 가장 정확할 것입니다.
Discussion

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