클로드 스킬로 프로젝트 자동화해보기 #1
Soshy·

남이 리뷰하듯, 에이전트도 그렇게
코드 리뷰를 다른 사람이 해주는 이유는 무엇일까요? 내가 작성한 코드는 아무리 다시 봐도 개선점을 찾기가 어렵기 때문이라고 저는 생각합니다.
Claude Code로 개발을 시켜보다가 비슷한 생각이 들었습니다. 계획도 Claude가 세우고, 구현도 Claude가 하고, 마지막에 "잘 됐네요"까지 Claude가 합니다. 그럼 그 검증을 얼마나 믿을 수 있을까 싶었습니다.
미리 말해두자면, 저는 이 분야를 잘 아는 상태로 설계한 게 아닙니다. 오히려 잘 모르는 채로 Claude랑 같이 이것저것 맞춰가며 만든 쪽에 가깝습니다. 그래서 아래 내용도 "이게 정답"이라기보다 "이렇게 해봤고 아직 다듬는 중"인 기록으로 봐주시면 좋을 것 같습니다.
아무튼 방향을 정하는 쪽과 그걸 의심하는 쪽을 서로 다른 주체로 나눠봤습니다. 이번에 Claude Code 커스텀 스킬로 만든 걸 한 줄로 줄이면 이렇습니다.
Claude가 PM을 맡고, 검증은 따로 띄운 Codex가 합니다.
아이디어는 지인이 쓰던 세팅(이슈 하나를 계획부터 리뷰까지 도는 스킬)을 보고 시작했습니다. 거기선 Jira를 쓰길래 저는 GitHub 이슈로 바꾸고, 제 블로그 레포에 맞게 다시 짰습니다.
왜 굳이 다른 프로세스로 띄우나
역할을 나눈다고 해도, 같은 대화 안에서 "이제 너는 리뷰어야"라고 말하는 것만으로는 부족하다고 생각했습니다. 방금 자기가 세운 논리를 자기가 방어하게 되지 않을까 싶었거든요. 그래서 검증은 PM의 대화 맥락을 모르는 별도 Codex 프로세스로 띄워봤습니다. 맥락이 끊겨 있으면 눈치 볼 것 없이 지금 놓인 것만 보고 판단하지 않을까 하는 기대였습니다.
이걸 담당하는 게 spawn-agent.sh라는 얇은 스크립트입니다. 스킬 문서(SKILL.md)의 본문을 읽어 프롬프트로 조립하고 Codex를 비대화형으로 실행합니다.
# 예: 플랜 리뷰어를 독립 프로세스로 스폰
codex exec \
-C "$CD_DIR" \
--dangerously-bypass-approvals-and-sandbox \
-o "$OUT" \
"$PROMPT"
스폰되는 쪽 프롬프트 맨 앞에는 이런 안내를 넣어봤습니다. "너는 별도 프로세스로 떠 있고 오케스트레이터가 무슨 생각을 했는지 모른다. 전부 네 근거로 판단해라. 그리고 너는 다시 다른 에이전트를 스폰하지 마라(재귀가 돈다)." 이게 실제로 얼마나 효과가 있는지는 더 돌려봐야 알 것 같습니다.
Codex는 로컬에서 ChatGPT 구독 로그인으로 돌립니다. 쓴 만큼 요금이 붙는 API 키는 쓰지 않습니다. 처음엔 CI로 PR 리뷰를 자동화할까 싶었는데, 헤드리스 인증에 유료 키가 필요해서 이번엔 이미 내고 있는 구독 안에서 도는 로컬 실행에 집중했습니다.
전체 흐름은 2단으로 이어집니다.
요구사항
│
▼
lead-epic ──[review-decomposition]──▶ 마일스톤 + 이슈 DAG
│ 노드 하나
▼
lead-issue ──[review-plan]──▶ developer ──▶ PR ──[review-pr]──▶ 머지
위쪽 lead-epic이 요구사항을 이슈 그래프로 쪼개고, 아래쪽 lead-issue가 그중 이슈 하나를 잡아 머지까지 끌고 가는 그림입니다.
리뷰를 세 번 나눠봤습니다
처음엔 리뷰 게이트를 셋이나 둘 필요가 있나 싶었습니다. 그런데 만들다 보니 각 게이트가 잡아내려는 실수가 조금씩 다른 것 같아서 그대로 뒀습니다.
① review-decomposition → 이슈 만들기 전 (쪼개기가 맞나)
② review-plan → 코드 짜기 전 (방향이 맞나)
③ review-pr → 머지하기 전 (결과가 맞나)
이슈를 만들기 전에 도는 게 review-decomposition입니다. 에픽을 이슈 여러 개로 쪼갠 결과를 검사하게 해뒀습니다. 빠진 이슈는 없는지, 의존성에 사이클이나 잘못된 연결은 없는지, 두 이슈가 같은 영역을 서로 자기 것이라 여기며 겹치지는 않는지, 이슈 하나가 너무 크거나 작지는 않은지. 잘못 쪼갠 채로 이슈를 수십 개 만들면 되돌리기가 번거로울 것 같아서, 만들기 전에 한 번 걸러보려는 의도입니다.
코드를 짜기 전에 도는 게 review-plan입니다. 여기 깔아둔 전제가 저는 재미있었습니다. "Developer는 유능하니 어떻게는 알아서 찾는다. 다만 플랜의 방향이 틀렸는지는 스스로 보기 어렵다. 그걸 대신 봐줘라." 그래서 태도를 이렇게 잡아봤습니다. 코드베이스가 진실이고, 플랜이 검증받는 쪽이다. 플랜이 코드에 대해 뭔가 주장하면 실제 코드를 열어 사실인지 확인하고, 손대는 지점마다 바깥으로 연결을 따라가며 놓친 부분을 찾게 했습니다.
머지 전에 도는 게 review-pr입니다. PR을 세 관점으로 보게 했습니다. 정확성·보안, 성능·견고성, 그리고 빠진 것(테스트나 커버리지). 여기서 규칙을 하나 좀 세게 걸어봤는데, non-blocking이라는 등급을 없앴습니다. 리스트에 올라간 항목은 전부 blocking이고, 커밋으로 해결되거나 반박이 받아들여져야만 APPROVE가 나가게요. "사소하니 그냥 통과"가 잘 안 나오게 해보고 싶었습니다.
대신 지적을 하려면 "이 입력에서 이 순서로 호출하면 여기서 터진다" 정도의 구체적인 시나리오를 붙이도록 했습니다. 못 붙이는 지적은 지우게 했고요. "문제가 될 수도 있어요" 같은 막연한 코멘트를 줄여보려는 시도인데, 실제로 얼마나 걸러질지는 아직 많이 돌려보진 못했습니다.
나머지 자잘한 규칙들
큰 구조만큼이나 이런 세부가 결과를 좌우할 것 같아서 신경 써본 부분들입니다.
- 이슈마다 울타리(Scope Fence)를 칩니다. "반드시 할 것 / 건드리지 말 것 / 순서"를 적어두고, 울타리 밖 문제를 발견하면 슬쩍 끌어안지 않고 새 이슈로 빼게 했습니다.
- 플랜에는 무엇을·왜만 적게 했습니다. 라인 넘버나 코드 스니펫, 함수 시그니처는 넣지 못하게요. 어떻게는 Developer의 몫이라고 보고, PM이 거기까지 손대면 경계가 흐려질 것 같았습니다.
- 리뷰어가 맞으면 그대로 고치고, 틀렸다고 보면 반박을 쓰되 형식을 정해뒀습니다. 우려를 다시 짚고, 코드로 반증하고, 대안이 왜 더 나쁜지까지. 이 셋이 없으면 반박으로 안 쳐주게 했습니다.
- Developer는 구현을 마치면 리포트를 남깁니다. 특히 "이건 이래서 이렇게 했고 저 방법은 이래서 택하지 않았다"를 적는 칸을 뒀습니다. 나중에 리뷰가 부딪힐 때 이 리포트를 먼저 보게 하려고요.
만들면서 정한 것들
- CI 자동 리뷰는 이번엔 넣지 않았습니다. 유료 키가 필요해서, 로컬에서 구독으로 도는 쪽으로 방향을 잡았습니다.
- 문서는 마크다운으로 쓰고 HTML로도 뽑습니다. 마크다운이 원본이고, HTML은 블로그가 원래 쓰던 remark/rehype 스택을 재활용하는 스크립트로 렌더합니다. 새로 설치한 의존성은 없습니다. 기준은 하나였습니다. "이 대화 맥락을 전혀 모르는 다음 사람이 읽어도 이해되게 쓰자."
- 에픽은 GitHub 마일스톤으로 뒀습니다. 마일스톤이 없으면 단독 이슈로 처리합니다. 혼자 이슈 하나를 할 때 억지로 에픽을 만들지 않아도 되게요.
- 이슈마다 git worktree를 따로 팝니다. 그래야 이슈 여러 개가 서로 파일을 밟지 않을 것 같아서요.
지금 사용하고 있는 스킬 7개
| 스킬 | 도는 곳 | 하는 일 |
|---|---|---|
lead-epic | Claude | 요구사항을 마일스톤 + 이슈 DAG로 |
review-decomposition | Codex | 이슈 만들기 전 쪼개기 검사 |
lead-issue | Claude | 이슈 하나를 9단계로 머지까지 |
review-plan | Codex | 코드 짜기 전 플랜 검사 |
developer | Codex | worktree 안에서 실제 구현 |
review-pr | Codex | PR 리뷰(전부 blocking) |
workflow-guide | Claude | 위 스킬 설명을 자동으로 최신화 |
아직 남은 것
솔직히 지금은 틀 정도만 맞춰둔 단계라고 생각합니다. 스폰되고, 인증되고, 문서가 렌더되고, 리뷰가 PR에 붙는 경로까지는 확인했는데, 실제 요구사항 하나를 이 파이프라인에 통째로 흘려보내는 건 아직 안 해봤습니다. 그게 다음 차례입니다. 병렬 실행도, worktree로 코드는 갈라놨지만 공유하는 임시 파일 몇 개가 아직 이슈별로 나뉘어 있지 않아 당분간은 하나씩 순서대로 돌릴 생각입니다.
그래도 만들면서 가장 남은 건 도구 자체보다, 에이전트한테 일을 다 맡기지 말고 정하는 쪽과 의심하는 쪽을 갈라두면 어떨까 하는 생각이었습니다. 검증도 한곳에 몰지 않고 단계마다 나눠 걸어보고요. 물론 이게 맞는 방향인지는 좀 더 써봐야 알 것 같습니다.
이어서 실제로 이슈 하나를 이 파이프라인에 흘려보내면 어떻게 굴러가는지도 정리해볼까 합니다. 잘 굴러가든 삐걱대든, 그 과정을 추후에 글로 남겨보겠습니다 😎