[CVDv2] 무인 개발 파이프라인 1일차
개인 프로젝트를 AI 에이전트에게 맡기는 체제를 만들어 보기로 했다. 목표는 단순했다 — 이슈를 던지면 브랜치를 따고, 개발하고, PR을 올리는 것까지 알아서. 나는 리뷰와 머지만 한다.
하루 만에 세팅부터 첫 에이전트 PR까지 갔다. 그리고 같은 날 목표의 절반을 접었다. 그 접은 판단이 지금까지 이 프로젝트를 굴러가게 하고 있어서, 그 하루를 적어둔다.
1. 후보 넷을 비교했다
24시간 이슈 생성·브랜치·PR·리뷰 대응이 가능한 체제를 목표로 넷을 봤다.
| 성격 | |
|---|---|
| GitHub Copilot coding agent | 이슈 → PR에 특화 |
| Claude Code + GitHub Actions | 자유도가 가장 높다 |
| OpenClaw | 메신저로 관제 |
| Hermes Agent | 동종 경쟁 구현체 |
결론은 관제탑 = OpenClaw, 실행 엔진 = Claude Code.
그리고 가동 방식을 풀가동 루프가 아니라 이벤트 구동으로 정했다. 이슈를 던지면 작업하고, 머지는 사람이 한다. 이 결정이 나중에 계속 값을 한다.
2. Hermes는 하루 만에 접었다
설치는 잘 됐다. 웹 패널도 뜨고 메신저 봇 연결까지 성공했다.
막힌 건 인증이었다. 구독 계정의 setup-token으로 직접 API를 호출하면 400이 떨어졌다. 올바른 토큰으로도 같았다.
⚠️ OpenClaw가 되는 이유가 거기서 갈렸다 — OpenClaw는 CLI 런타임을 쓴다. 즉 "Claude Code로서" 호출한다. 같은 구독인데 어떤 경로로 부르느냐가 되고 안 되고를 갈랐다.
폐기. 아까웠지만 인증이 안 되면 나머지가 다 무의미하다.
3. 그리고 OpenClaw도 절반 접었다 ← 이게 그날의 진짜 결론
세팅을 다 해놓고 실제로 코딩 세션을 돌려봤더니 메시지당 컨텍스트 오버헤드가 컸다. 관제 계층을 한 겹 거치는 대가가 토큰으로 나온다.
메신저로 개발을 시키는 건, 전화로 요리를 하는 것과 비슷하다. 할 수는 있는데 매번 냉장고 안을 처음부터 설명해야 한다.
그래서 이렇게 갈랐다:
- 실작업은 메인 PC의 Claude Code를 직접 쓴다
- OpenClaw는 관제탑으로 다이어트 — 폰에서 상태 확인하고 알림 받는 용도. 기본 모델도 가벼운 쪽으로 내리고, 당분간 꺼둬도 무방한 수준으로
목표는 "24시간 무인"이었는데 하루 만에 "사람이 앉아서 지시하고 리뷰하는" 체제로 후퇴한 셈이다. 지금 돌아보면 그 후퇴가 이 프로젝트를 살렸다. 다만 그때는 이유를 몰랐다. 토큰이 아까워서 내린 결정이었지 구조를 알고 내린 게 아니다.
4. 코드베이스를 보고 재설계 방식을 정했다
이 프로젝트는 v1을 다른 개발자가 만들었고, 나는 v2.0.0부터 그 코드를 이어받아 개발했다. UI와 다운로드 로직이 출발점이었고, 거기에 다중 다운로드를 붙이면서 지금은 사실상 내 코드가 됐다.
인수 시점의 상태를 정리하면 이랬다.
- main — 3,265줄. 동작한다. 다만 Qt가 전 계층에 침투해 있고, 하위 계층이 UI를 역참조하고, 다운로드 구현이 중복돼 있고, 테스트가 0개였다
- 중단된 리팩토링 브랜치 — 작년에 손대다 만 스냅샷. 아이디어는 유효한데 미완이라 아이디어 광산으로만 쓰기로
- 로컬 UI 프로토타입 — 셸과 화면 골격만 있고 엔진 미연결. 시크릿 검사 후 별도 브랜치로 박제
전면 재작성 대신 점진 추출을 택했다. 동작하는 3,265줄을 버리는 건 쉽지만, 버리는 순간 "원래 되던 것"의 목록을 잃는다.
Phase 0(안전망) → 1(정지작업) → 2(core 이주) → 3(탈Qt) → 4(전략 통합) → 5(신기능·UI).
같이 정한 것들 — 유저 플러그인 시스템 삭제(내부 전략만 유지), 브랜치는 main + feature만 두고 버전은 태그로, 단일 데이터클래스화, 이벤트 버스 제거, threading + 콜백 유지(asyncio는 나중에).
5. 프롬프트를 자산으로 취급하기로 했다
에이전트에게 주는 규칙 문서(CLAUDE.md)와 설계 명세를 저장소에 커밋하지 않기로 했다. .gitignore 대상인 로컬 파일로 두고, 공개 커밋에는 빌드 설정·CI·템플릿만 올린다.
⚠️ 이 결정은 나중에 예상 못 한 대가를 치른다 — 에이전트가 스크래치 클론에서 작업하면 그 규칙 문서가 애초에 도착하지 않는다. "규칙을 어겼다"와 "규칙이 안 왔다"를 구분해야 한다는 걸 한참 뒤에 알았다. 그건 다른 글에서.
6. 개통
- 스캐폴딩 PR — 빌드 설정, CI, 이슈·PR 템플릿을 올리고 머지
- 브랜치 보호 룰셋을 켰다 — PR 필수, 상태 체크 통과 필수, 강제 푸시 차단
- 라벨 셋:
agent,approved,improvement - 첫 이슈 둘 등록 — 패키징 이관 + 린트 도입, 그리고 박제 테스트 1차
- 메인 PC에 Claude Code 네이티브 설치. ⚠️ 실행은 PowerShell로 — Git Bash는 raw mode를 지원하지 않는다
그리고 claude에 "첫 이슈만 작업해라"고 던졌다.
5분 36초 뒤에 PR이 올라왔다.
- 지정한 브랜치, 소스 무수정 원칙 준수
- 패키징 정합화(미사용 의존성 제거, 다만 릴리즈 워크플로가 쓰는 것은 사유를 명시하고 유지)
- 린트 위반 94건을 베이스라인으로 잡고 통과
- 테스트 단계는 "테스트 0개"로 실패 — 에이전트가 그 상황을 정확히 보고했다
마지막 줄이 제일 마음에 들었다. 초록불을 만들려고 애쓰는 대신 빨간불의 이유를 설명했다.
7. 첫날에 배운 것
① 되는 경로와 안 되는 경로는 문서에 안 적혀 있다. 같은 구독인데 호출 경로 하나로 갈렸다. 후보를 고르는 단계에서 가장 먼저 인증을 뚫어봐야 한다. 기능 비교는 그다음이다. Hermes는 웹 패널이 뜨고 봇이 붙는 데까지 갔다가 거기서 죽었다.
② 첫 PR에서 볼 것은 코드가 아니라 보고다. 테스트 단계가 빨간불이었는데, 에이전트가 그걸 "테스트가 0개라서"라고 정확히 말했다. 초록불을 만들려고 애쓰는 대신 빨간불의 이유를 설명한 것.
실패를 실패라고 말하는지 — 그게 안 되면 나머지는 전부 못 믿는다. 코드는 다시 보면 되지만 보고가 거짓이면 볼 지점을 못 찾는다.
이후 이 파이프라인으로 재설계를 Phase 5까지 진행 중이다. 중간에 겪은 것들은 따로 적을 예정 — 자동화를 어디까지 밀 수 있는가(첫날의 후퇴가 왜 옳았는지 한참 뒤에 알았다), 측정이 오염돼 있던 이야기, 그리고 게이트가 초록불을 내면서 아무것도 안 재고 있던 이야기.