
Claude Code와 Codex의 반자동 개발 워크플로우 설계 상세
요약
Claude Code와 Codex를 각각 구현과 리뷰 담당으로 분리하여 구축한 반자동 개발 워크플로우 설계 방식을 다룹니다. 에이전트 간의 역할 분담과 상반된 프롬프트 설계를 통해 셀프 승인 문제를 방지하고 개발 효율을 높이는 전략을 제시합니다.
핵심 포인트
- 구현과 리뷰 에이전트를 분리하여 사고의 방향성 차이 극복
- GitHub 라벨을 매개로 한 비동기식 에이전트 통신 구조
- 상반된 프롬프트 설계를 통한 역할 명확화 및 셀프 승인 방지
- 4시간 단위의 정기적 사이클을 통한 자동화 프로세스 운영
이 기사의 전제
Claude Code와 Codex라는 두 개의 AI 에이전트(Agent)에게 업무를 분담시켜, 7일 동안 30개의 PR을 머지(Merge)하고 70개의 Issue를 기표·처리하는 반자동 개발 워크플로우를 구축했습니다.
경위와 결과의 요약은 별도 기사인 『Claude Code와 Codex로 개인 앱 개발을 반자동화한 이야기』에 정리해 두었습니다.
이 기사에서는 해당 워크플로우를 뒷받침한 개별 설계 판단을 "재현용 레퍼런스"로서 정리합니다. 사이클의 발화 순서, 라벨(Label) 설계, 코멘트 추가 방식, PR 집약, 신규 Issue 기표 금지와 특례, 프롬프트(Prompt) 관리. 각각에 대해 "왜 그렇게 했는가"를 나중에 스스로 다시 검토할 때 찾아낼 수 있는 형태로 기록합니다.
메인 기사를 읽지 않은 분들을 위해 최소한의 전제만 먼저 공유합니다.
Claude Code를 기능 개발 담당으로, Codex를 리뷰 담당으로 나누어 반자동으로 개발이 진행되는 워크플로우를 구성했습니다. 양자는 GitHub의 라벨만을 공유하며 직접 통신하지 않고, 4시간 사이클 × 하루 6회(구현 배치만 5회)로 발화하는 구조입니다.
구현과 상세화·리뷰를 별도의 에이전트로 나눈 이유
두 에이전트 모두 베이스 모델의 능력은 충분히 높아서, 원리적으로는 어느 한쪽에 모든 공정을 맡길 수도 있습니다. 그럼에도 굳이 나눈 이유는, 자신이 작성한 코드를 스스로 리뷰해도 제대로 된 리뷰가 되지 않는다는 인간의 팀 개발에서 흔히 볼 수 있는 제약이 AI 에이전트에게도 동일하게 적용된다고 생각했기 때문입니다.
구현은 "정해진 사양을 최단 거리로 코드에 옮기는" 프로세스이고, 상세화·리뷰는 "정해진 것으로 간주한 사양을 의심하고 누락을 찾는" 프로세스로, 사고의 방향이 반대를 향하고 있습니다.
이 방침을 성립시키는 것은 에이전트 본체가 아니라, 양자에 대한 정반대의 프롬프트입니다. 프롬프트는 docs/claude-code-scheduled/와 docs/codex-automations/에 커밋(Commit)되어 있으며, 서로 보완하도록 나누어 작성되었습니다.
Claude Code 측 프롬프트: Codex의 최신 코멘트(후술할 ## [Codex 상세화 ...] 마커)를 신뢰하여 구현한다는 점을 명시하고, **"머지 판단은 절대 수행하지 않는다", "자신의 PR을 승인하지 않는다"**를 굵은 글씨로 금지 사항으로서 열거
Codex 측 프롬프트: Issue 상세화 배치에서는 "Claude Code가 구현에 착수할 수 있는 입도(Granularity)까지 요건·수락 조건·의존 관계를 도출한다"를 필수화. PR 리뷰 배치에서는 "구현의 정확성뿐만 아니라 Issue의 의도와 괴리되지 않았는지 반드시 확인한다", "CI green을 gh pr checks <pr> --watch로 육안 확인한 후 머지한다"를 명시
특히 효과적이었던 것은 Claude Code 측 프롬프트에 "자신의 PR을 머지하지 않는다"를 강한 어조로 작성한 점이었습니다. 동일한 GitHub 계정으로 두 에이전트를 구동하고 있기 때문에, GitHub 측에서 셀프 승인(Self-approval)을 기계적으로 방지할 수 있는 수단이 없습니다(자세한 내용은 별도 기사 『Claude Code와 Codex의 반자동 개발에서 빠진 6가지 함정』을 참조하십시오). 그럼에도 7일 동안 Claude Code 측이 머지에 손을 댄 케이스는 제로였습니다.
이용 플랜은 Claude Code가 Max 5 플랜, Codex가 Plus 플랜입니다. 토큰(Token) 소비량과 처리 시간을 보면 두 플랜 모두 이번 부하에서는 충분한 여유가 있었으며, Claude Code의 구현 배치는 한 번에 10건 정도까지 Issue를 처리할 수 있을 것 같은 느낌이었습니다(시험 삼아 3건/PR로 고정하여 운용 중입니다).
역할을 명시적으로 나눔으로써 관점이 분리될 뿐만 아니라, 프롬프트의 책임도 작아져 작성하기 쉬워진다. 반자동 개발에서의 품질 확보 근간은 모델 성능이 아니라 이 "2역 분할"에 두었습니다.
6개의 라벨을 공유 메모리로 사용
에이전트끼리는 직접 통신시키지 않고, GitHub의 라벨만으로 상태를 동기화하는 구조로 만들었습니다.
| 종류 | 라벨 | 부여 / 제거 책임 주체 |
|---|---|---|
| Issue | needs-user-review | Claude Code가 이슈 생성 시 부여, 내가 트리아지 (Triage) 시 제거 |
| Issue | needs-codex-refinement | Claude Code가 이슈 생성 시 부여, Codex가 상세화 완료 시 제거 |
| Issue | ready-for-cc-implementation | Codex가 상세화 완료 시 부여, Claude Code가 작업 선택 시 제거 |
| Issue | cc-implementing | Claude Code가 작업 선택 시 부여, 머지 (Merge) 시 자동 종료로 소멸 |
| PR | needs-codex-review | Claude Code가 PR 생성·수정 완료 시 부여, Codex가 리뷰 시 제거 |
| PR | ready-for-cc-revision | Codex가 리뷰 NG 시 부여, Claude Code가 수정 완료 시 제거 |
각 배치 (Batch)는 "자신이 담당하는 라벨이 붙은 Issue / PR이 존재하는가"만을 보고 작업 여부를 판단합니다. 라벨이 붙어 있지 않으면 아무것도 하지 않고 종료하는 단순한 구조입니다.
에이전트끼리 직접 API를 호출하여 상태를 전달하는 것이 아니라, GitHub의 라벨을 매개로 비동기적으로 상태를 읽고 쓰는 방식입니다. 이 구조를 통해 배치 간의 시간적·구현적 의존 관계가 사라지고, 각 배치가 독립적이고 안전하게 동작할 수 있게 되었습니다. 하나의 배치가 중단되어도 다른 배치에 영향을 주지 않는, 이른바 느슨한 결합 (Loosely Coupled) 설계입니다.
4시간 사이클을 1시간씩 어긋나게 하여 파이프라인화하기
사이클의 실행 시각은 4개의 배치를 1시간씩 차이를 두었습니다.
- 00:00 / 04:00 / 08:00 / 12:00 / 16:00 / 20:00: Codex Issue 상세화 배치 -
- 01:00 / 05:00 / 09:00 / 13:00 / 17:00 / 21:00: Codex PR 리뷰 배치 -
- 02:00 / 06:00 / 10:00 / 14:00 / 18:00 / 22:00: Claude Code PR 수정 배치 -
- 03:00 / 07:00 / 11:00 / 15:00 / 19:00: Claude Code Issue 구현 배치 -
- 23:00: Claude Code E2E 스모크 테스트 실행 배치 (1일 1회)
각 배치의 "입력 라벨 → 처리 → 출력 라벨" 대응 관계는 다음과 같습니다.
| 배치 | 입력 (찾는 라벨) | 처리 | 출력 (교체하는 라벨) |
|---|---|---|---|
| Codex Issue 상세화 | Issue: needs-codex-refinement | 요구사항·수락 조건·의존 관계를 코멘트로 추가 | Issue: ready-for-cc-implementation |
| Claude Code Issue 구현 | Issue: ready-for-cc-implementation | 최대 3건을 선택하여 1개의 PR로 묶어 구현 | Issue: cc-implementing / PR: needs-codex-review |
| Codex PR 리뷰 | PR: needs-codex-review | 리뷰 결과를 코멘트로 추가. OK 이고 CI Green 이면 gh pr merge로 머지 | OK 시: PR 종료 + Issue 자동 종료 / NG 시: PR ready-for-cc-revision |
| Claude Code PR 수정 | PR: ready-for-cc-revision | 동일 브랜치에 추가 커밋 | PR: needs-codex-review |
| Claude Code E2E 스모크 실행 | (라벨 참조 없음, pnpm e2e 실행) | 스모크 테스트 실행 + 실패 시 Issue 자동 생성 | Issue: needs-codex-refinement (실패 시에만) |
실행 순서를 1시간씩 어긋나게 한 이유는 상세화 → 리뷰 → 수정 → 구현의 파이프라인을 동일 사이클 내에서 완결시키기 위함입니다. 예를 들어 00:00의 상세화로 ready-for-cc-implementation
로 전환된 Issue는 03:00의 구현 배치(Implementation Batch)에서 포착할 수 있습니다. 다음 사이클(04:00)을 기다릴 필요가 없는 구조로 되어 있습니다.
동일한 시각에 여러 배치를 병렬로 실행시키지 않은 이유는, 경합(Contention)이나 예기치 않은 간섭이 발생할 가능성을 배제하고 싶었기 때문입니다. Claude Code와 Codex는 동일한 로컬 머신(저의 Mac) 상에서 동작하고 있기 때문에, 병렬 실행은 실행 환경을 두고 다투는 리스크도 있었습니다.
Issue / PR 본문을 불변으로 유지하는 코멘트 추가 방식
Codex의 상세화 결과나 리뷰 결과는 Issue / PR의 본문에 작성하지 않습니다. 모두 코멘트(Comment)로 추가하며, 서두에 반드시 다음과 같은 마커(Marker) 행을 배치합니다.
## [Codex 상세화 (2026-05-22)]
## [Codex 리뷰 OK (2026-05-23)]
## [Codex 리뷰 수정 필요 (2026-05-23)]
Claude Code는 이 마커를 검색하여 최신 Codex 코멘트를 기계적으로 추출하고, 상세화 결과나 리뷰 지적 사항을 읽어들입니다.
본문을 불변으로 유지하는 이유는 두 가지입니다. 첫 번째는, 처음에 작성한 요구 사양이나 Issue 개요가 에이전트(Agent) 측의 상호작용으로 인해 덮어씌워져 사라지는 것을 방지하기 위해서입니다.
두 번째는, 에이전트 간의 대화 이력을 코멘트 시계열로서 남기기 위해서입니다. 나중에 다시 읽었을 때 "어떤 논의를 거쳐 구현에 이르렀는가"를 추적할 수 있도록 하고 싶기 때문입니다.
재상세화 또는 재리뷰가 발생한 경우에도 기존 코멘트는 편집하지 않고, 신규 코멘트로 추가합니다. 오래된 상세화 결과도 시계열로서 남기 때문에, Claude Code는 마커 행의 날짜를 통해 최신 것을 식별하는 메커니즘을 가집니다.
1 PR = 3 Issue 집약과 merge commit의 의도
Claude Code의 구현 배치는 ready-for-cc-implementation 상태인 Issue에서 최대 3개를 선택하여, 하나의 PR에 모아서 구현합니다. 선택 조건으로는 사양 상세화 시 Codex가 코멘트에 남기는 **"의존 대상(blocked-by / 부모 Issue)이 모두 Closed 상태일 것"**을 필수 사항으로 했습니다. 의존 관계가 해결되지 않은 Issue를 미리 가져가면, 다른 Issue의 구현 과정에서 전제 조건이 무너져 재작업(Rework)이 발생하기 때문입니다.
3개를 '별도 브랜치·별도 PR'이 아닌 '동일 브랜치·동일 PR'로 묶은 이유는, 병렬 구현 시 발생하는 머지 컨플릭트(Merge Conflict)를 구조적으로 배제하기 위해서입니다. 별도 브랜치에서 진행하면 동일한 파일을 수정했을 때 충돌 해결을 위한 추가 비용이 발생합니다. 동일한 브랜치에 3개 분량의 커밋을 쌓으면, PR 간의 충돌은 애초에 발생하지 않습니다.
머지 방식은 merge commit으로 고정하였으며, squash / rebase는 비활성화했습니다. 이는 PR 단위의 OK / NG 판정과 Issue 단위의 커밋 이력 유지를 양립시키기 위한 판단입니다.
squash를 하면 1 Issue = 1 커밋이라는 입도(Granularity)가 상실되어, 나중에 git log로 Issue 유래의 변경 사항을 추적할 수 없게 됩니다. 커밋 메시지는 [#<issue>] <summary> 형식으로 통일하고 있으므로, merge commit 방식을 사용하면 Issue별 이력이 그대로 히스토리 트리(History Tree)에 남습니다.
신규 Issue 생성 원칙적 금지 및 2가지 특례 제한
에이전트 측에서의 신규 Issue 생성은 원칙적으로 금지했습니다. 구현 중에 발견한 과제나 추가 요구사항은 모두 해당 PR의 description 또는 PR 코멘트에 남기며, Issue화 여부는 제가 수동으로 판단합니다.
이유는 단순합니다. 자동 에이전트가 신규 Issue를 무조건적으로 계속 생성하면, 완료 판정(Issue / PR의 잔여 건수 0건)이 파괴되어 루프(Loop)가 수렴하지 않게 되기 때문입니다.
다만, 여기에 두 가지 특례를 두었습니다.
특례 1: E2E 스모크 실행 배치에 의한 자동 생성
첫 번째는 E2E 스모크 실행 배치(23:00 JST / 1일 1회)에 의한 E2E 실패 Issue의 자동 생성입니다. 매일의 자동 회귀 테스트 탐지 및 수정 사이클을 성립시키기 위한 메커니즘으로, 템플릿 e2e-failure.yml을 통해서만 생성을 허용합니다.
남용을 피하기 위해, 동일 증상의 기존 open Issue가 있다면 신규 생성을 하지 않고, 기존 Issue에 코멘트를 추가하여 재현 보고를 남기도록 하는 제약도 함께 부여했습니다.
특례 2: 사용자 인터뷰 기반의 이슈 생성 (수동 트리거)
두 번째는 사용자 인터뷰 (User Hearing) 기반의 Issue 생성입니다. 제가 수동으로 조작한 앱의 사용감을 Codex가 인터뷰 시트 (Hearing Sheet)에 기록합니다. Claude Code는 저의 명시적인 지시에 따라 해당 시트에서 인사이트를 추출하여 Issue를 생성합니다.
생성 시의 라벨은 needs-user-review로만 설정하며, Codex 상세화 루프 (Codex Detail Loop)로 멋대로 흘러가지 않도록 했습니다. 반드시 저의 트리아지 (Triage) 과정을 거치도록 구조화했습니다.
프롬프트는 git으로 버전 관리한다
Claude Code Scheduled Task와 Codex Automations의 프롬프트는 docs/claude-code-scheduled/와 docs/codex-automations/에 Markdown 형식으로 보관하며, 리포지토리 (Repository)에 커밋하고 있습니다. 배치 (Batch)의 동작을 바꾸고 싶을 때는 프롬프트를 수정하여 git에 올리면, 다음 스케줄 실행 시 새로운 프롬프트가 로드됩니다.
이는 프롬프트 자체를 워크플로우의 구성 요소로서 버전 관리하기 위한 결정입니다. 시행착오의 이력은 git log로 추적할 수 있으며, 설계 변경에 대한 의사결정 또한 커밋 메시지 (Commit Message)로 남습니다.
프롬프트를 관리 화면의 UI에 직접 작성하는 운영 방식과 비교했을 때, 수정 리뷰, 이력의 투명성, 롤백 (Rollback)의 용이성 측면에서 큰 차이가 있습니다. 반자동 개발 워크플로우 자체가 일종의 시스템이며, 그 동작을 결정하는 프롬프트는 코드와 동등하게 관리되어야 한다는 것이 운영을 통해 확인된 감각이었습니다.
루프의 수렴은 완료 판정으로 담보한다
Open 된 Issue와 PR이 모두 0건이 된 시점에서 본 프로젝트를 완료된 것으로 간주합니다.
무한 루프나 정체를 자동으로 감지하는 가드레일 (Guardrail)은 설정하지 않고, 저의 매일 육안 확인으로 대응하는 운영 방식을 택했습니다. 이는 가드레일을 늘릴수록 운영 규칙이 복잡해지고, 또 다른 파탄 리스크가 발생한다는 판단에 따른 것입니다.
1일 6 사이클 × 4 배치 + E2E 배치 + 인터뷰 기반 구성은 6종의 라벨과 마커 행 (Marker Line), 그리고 2개의 특례만으로 충분히 폐쇄적인 구조를 유지했습니다. 설계가 폐쇄적이라면 인간이 확인해야 할 것은 "예상치 못한 동작이 일어나고 있지 않은가"뿐입니다.
반자동 개발을 실용 영역으로 끌어올리기 위한 마지막 퍼즐 조각은, 인간의 개입 포인트를 사양 책정, 예외 대응, 사용자 인터뷰 / 트리아지의 3가지로 압축하는 것이었습니다. 이는 메인 기사에서 작성한 "7일간의 운영에서 보인 것"과 동일한 결론에 설계 측면에서 도달한 형태이기도 합니다.
지금까지 기술한 설계가 처음부터 이 형태였던 것은 아닙니다. GitHub Free 플랜의 제약, gh CLI로의 통일, worktree 모드의 브랜치 명명 규칙 등 설계 당시에는 보이지 않았던 벽을 여러 번 마주하며 현재의 형태에 이르렀습니다.
그 과정은 별도 기사인 『Claude Code와 Codex의 반자동 개발에서 빠졌던 6가지 함정』에 기술해 두었습니다. 메커니즘을 재현하고 싶은 분들은 이 글과 함께 참조하시기 바랍니다.
Discussion

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