요즘 Claude Code로 개발을 하면서 계속 걸리던 게 있었다. 작업 하나를 시작할 때마다 "이걸 어디서부터 어떻게 잡지"부터 매번 새로 고민한다는 점이었다. 티켓을 읽고, 스코프를 정하고, 계획을 세우고, 구현하고, 리뷰하고, 배포하는 흐름이 머릿속에만 있으니 세션이 바뀌면 그때그때 다르게 굴러갔다.
그래서 이 흐름 전체를 하나의 파이프라인으로 고정하는 나만의 하네스(harness)를 새로 짰다. 이 글은 그 신규 하네스를 실제로 적용해본 기록이다.
왜 하네스를 다시 짰나
기존 방식의 문제는 대략 세 가지였다.
- 작업 컨텍스트가 매번 휘발된다. 어제 정리한 스코프를 오늘 세션은 모른다.
- 계획 없이 바로 구현에 들어가서 스코프가 중간에 계속 흔들린다.
- 리뷰와 배포가 결국 사람 기억에 의존한다. 빠뜨리면 그냥 빠진다.
결국 필요한 건 "작업 하나가 들어오면 배포까지 정해진 레일 위로 흐르게 만드는 것"이었다.
전체 파이프라인
먼저 완성된 흐름을 그림으로 그려봤다.

크게 보면 이렇게 흐른다. Asana에서 작업을 가져와서(pull) GitHub 이슈와 매칭하고, grilling으로 스코프를 집요하게 확정한 뒤, planner가 상세 계획을 세운다. 여기서 hotfix인지 정규 작업인지 갈리고, 다시 변경 규모에 따라 경량/중량 트랙으로 나뉜다. 마지막은 review-gate 리뷰를 거쳐 release로 배포된다.
계획 단계(planner)에서는 영향 범위 분석, 테스트 계획, 수정 파일 체크, 도메인 수 판정, 트랙 분류를 거쳐 tmp/TODO.md라는 실행 계획서를 뽑아낸다. 이후 모든 실행은 이 파일을 기준으로 움직인다.
두 개의 트랙
변경 규모에 따라 작업 방식을 둘로 나눴다.
경량 트랙은 단일 도메인, 소규모 변경일 때다. red → green → refactor 순서로 TDD를 지키고, 테스트 실행은 pre-commit 훅에 맡긴다. 한 세션 안에서 수직으로 끝낸다.
중량 트랙은 여러 도메인에 걸친 대규모 변경일 때다. 도메인별로 서브에이전트를 띄우고, 각자 격리된 worktree에서 병렬로 작업한 다음, 마지막에 결과를 종합한다.
작업 인테이크 — asana-task
파이프라인의 입구다. Asana 티켓 하나를 pull해서 구체화하고, GitHub 이슈에 연결하고, 스코프를 grilling한 뒤 planner에게 넘기는 것까지가 이 스킬의 역할이다. 프로젝트마다 Asana 프로젝트명과 GitHub 레포 두 값만 주입하면 asana-task-init이 찍어낸다.
동작은 이렇다.
- 태스크 선택. 지목하면 해당 태스크를, 아니면 내 미완료 목록을 가져온다. 태스크 id는 런타임에 해석하고 하드코딩하지 않는다.
- 전체 읽기. 설명뿐 아니라 모든 코멘트를 읽는다. 실제 스코프 맥락은 설명보다 코멘트에 있는 경우가 많았다.
- GitHub 이슈 연결. 기존 이슈를 찾아 매칭하고, 없으면 요약과 역링크를 붙여 새로 만든다. 본문은 반드시 확인 후 생성한다.
- 스코프 grilling. 계획 전에 스코프를 확정하는 단계다. 확정된 용어와 결정은
CONTEXT.md에 기록한다. - 핸드오프. grilling한 스코프와 링크, 건드릴 파일 노트를 planner에게 넘긴다. 여기서는 계획도 구현도 하지 않는다.
핵심은 4단계 grilling이다. 계획에 들어가기 전에 스코프를 못 박아두는 게 이 스킬이 존재하는 이유다.
계획 — planner
모든 구현 작업의 계획을 전담한다. 규칙상 메인은 직접 계획하지 않고 반드시 planner에게 위임한다.
planner가 가장 먼저 하는 일은 트랙 판별이다. 신규와 수정 파일을 전부 나열해서 6개 이상이면 중량, 5개 이하라도 독립 병렬 그룹이 2개 이상이면 중량, 애매하면 경량으로 잡는다.
그다음 요구 분석 → 아키텍처 리뷰 → 스텝 분해 → 구현 순서를 거쳐 tmp/TODO.md를 생성한다. 이 파일 생성은 생략할 수 없다. 경량이면 파일 목록과 브랜치, 태스크 체크리스트가 담기고, 중량이면 그룹과 의존성, 병렬 worktree 지정, 통합 계획까지 들어간다.
실행 — dev-workflow
계획이 끝난 뒤의 실행 절차다. tmp/TODO.md의 트랙 값을 읽고 그에 맞게 움직인다.
경량 트랙은 feature 브랜치를 만들고, 구현을 fork 서브에이전트에 위임한다. fork는 대화 맥락을 그대로 상속하기 때문에 grilling한 스코프나 컨벤션을 다시 브리핑할 필요가 없다. 항목별로 TDD를 돌려 커밋하고, review-gate 리뷰를 거쳐 통합 브랜치에 머지한 뒤 tmp/TODO.md를 지운다.
중량 트랙은 조금 더 복잡하다. 먼저 공통 타입 같은 선행 작업을 한 그룹이 단독으로 커밋하고, 그다음 독립 그룹들이 각자 worktree에서 병렬로 작업한다. 마지막에 변경량이 적은 순서로 머지하면서 충돌은 양쪽 의도를 보존하는 방향으로 정리하고, 타입체크와 전체 테스트를 돌린다.
모델은 작업 성격에 따라 나눠 쓴다. 단순 기계 작업은 저가 모델의 새 서브에이전트에, 메인 개발과 오케스트레이션은 중간 모델에, 아키텍처 판단은 최상위 모델에 맡긴다.
Git 규칙
모든 프로젝트에 전역으로 적용되는 규칙도 정리했다.
- 브랜치는
feature/,fix/,refactor/,hotfix/,chore/로 나눈다. - 버전은 프로덕션 릴리즈 단위로만 올린다. 일상 커밋에서는
package.json의 버전을 건드리지 않고, bump은 release 스킬이 담당한다. - 커밋 메시지는
<type>: <description>형식을 지킨다. - PR은 전체 커밋 히스토리와 diff를 분석해 요약과 테스트 플랜을 붙인다.
리뷰 — review-gate
머지 전에 두 번의 리뷰를 거친다. 순서를 고정한 게 포인트다. 정확성이 먼저고, 군살 제거가 그다음이다.
1차는 정확성, 보안, 품질 리뷰다. 여기서 나온 치명적/높음 이슈는 반드시 고치고, 이걸 남긴 채로는 2차로 넘어가지 않는다. 2차는 오버엔지니어링 정리다. 굳이 다시 만든 표준 기능, 불필요한 의존성과 추상화, 쓰지도 않는 유연성을 걷어낸다. 단, 명시적으로 요구된 것과 검증/보안 관련 코드는 그대로 둔다.
배포 — release
배포는 프로젝트마다 다르기 때문에 하나로 못 박지 않고 release-init이 프로젝트 전용 release 스킬을 만들어내게 했다.
먼저 CI/CD 설정, 스크립트, 브랜치 구조, 기존 문서를 조사한다. 묻기 전에 먼저 찾는 게 원칙이다. 그다음 staging, production, hotfix 같은 경로별로 조사 결과를 추천안으로 제시하면서 하나씩 확정한다. 마지막으로 실제 명령과 브랜치명, CI 잡 이름을 그대로 박아 스킬을 작성한다. 일반론으로 얼버무리거나 없는 절차를 지어내지 않는다.
새 프로젝트 붙이기 — project-init
새 프로젝트를 이 흐름에 태우는 조립기다. 전역 플로우는 건드리지 않고 프로젝트별 조각만 채운다.
이미 초기화된 프로젝트면 상태만 보고하고 끝낸다. 처음이면 그래프를 빌드하고, CONTEXT.md에 상위 용어를 시딩하고, asana-task-init과 release-init을 붙인 뒤 프로젝트 CLAUDE.md에 진입점을 문서화한다. .claude/나 CONTEXT.md 같은 파일은 .gitignore에 등록해둔다.
전역과 프로젝트별의 경계
마지막으로 무엇을 고정하고 무엇을 프로젝트마다 새로 채울지 선을 그었다.
- 전역으로 고정: 개발 플로우, planner, dev-workflow, review-gate, Git 규칙. 라이프사이클 그 자체다.
- 프로젝트별로 채움: asana-task, release, 그래프,
CONTEXT.md, 필요할 때만 도메인 에이전트.
적용해보고
정리하고 나니 확실히 "다음에 뭘 하지"를 고민하는 시간이 줄었다. 작업이 들어오면 어디쯤 서 있는지가 파이프라인 위에서 바로 보인다. 특히 계획을 planner에 강제로 위임하게 만든 것과, 스코프를 grilling으로 못 박고 시작하는 것 두 개가 체감상 가장 컸다.
아직 다듬을 곳은 많다. 중량 트랙의 병렬 통합은 여전히 손이 가고, release 자동화도 프로젝트마다 편차가 있다. 그래도 흐름 자체를 레일로 만들어두니, 개선할 지점이 명확하게 보인다는 것만으로도 짜둔 값은 했다고 생각한다.