~/khan

Claude Code 하네스를 직접 엔지니어링한 이야기 (3) — 어떤 절차로 업무를 시작하나

· 17 min read · by Khan
#Claude Code#AI#하네스 엔지니어링#워크플로우#절차#회고

1편은 하네스의 부품, 2편은 그 부품이 왜 그 모양인지였습니다. 3편은 가장 실용적인 질문입니다 — 그래서 작업을 시킬 때 실제로 무슨 순서로 흘러가나? 이 글은 비자명한 작업 한 건이 세션이 열리는 순간부터 닫히는 순간까지 제 하네스를 통과하는 절차를 따라가 본 기록입니다. 앞선 두 편과 마찬가지로 제가 개인 프로젝트로 혼자 꾸린 환경이고, 회사가 정한 작업 절차가 아니라 제 개인 작업 절차라는 점을 먼저 적어 둡니다. 3부작의 마지막입니다.

1. 작업 한 건의 생애주기

먼저 전체 그림부터 펼쳐 두겠습니다. 비자명한 작업(기능 추가·버그 수정·리팩터링) 한 건은 대략 이 흐름을 탑니다.

세션 열림
   │  지난 핸드오프 문서가 있으면 먼저 확인

[작업 요청]


① 플랜 작성       요구·가정·영향범위·성공기준·단계 + 셀프체크


② 사전 핑퐁 게이트   외부 모델 교차검토 (최대 3라운드)
   │              라운드 사이 플랜 자동 수정

③ 사용자 승인  ◀── 유일한 허들


④ 구현            Surgical — 건드릴 것만


⑤ 테스트 검수      신규 분기 커버리지·회귀 4항목 자기검수


⑥ 커밋 직전 핑퐁    외부 모델 교차검토 (코드 대상)


⑦ 최종 승인 → git add (commit 은 직접)


세션 닫힘
      writing-handoff-doc 스킬 → 핸드오프 저장

핵심은 사람이 멈추는 자리가 단 두 곳(③, ⑦) 이라는 점입니다. 나머지 검증은 게이트가 알아서 돕니다. 이제 한 칸씩 보겠습니다.

2. 0단계 — 세션이 열릴 때

작업 요청을 하기 전에, 저는 먼저 지난 핸드오프가 있는지 확인합니다.

지난 세션이 컨텍스트 압축이나 종료로 끝났다면, 그때 무엇을 하고 있었는지가 5섹션 요약(목표 / 내려진 결정 / 진행 중 작업 / 다음 액션 / 관련 파일)으로 .claude/handoffs/ 에 남아 있습니다. 그 최신 문서를 읽고 "어제 어디까지 했지?" 를 묻지 않고 바로 이어 갑니다.

문서 정리 규칙도 같이 둡니다. 브랜치의 작업 키가 바뀌면 이전 작업의 핸드오프는 archive/ 로 내리고, 현재 작업의 문서만 책상 위에 남깁니다. (한때는 이 복원·정리를 SessionStart 훅으로 자동화했는데, 지금은 핸드오프를 스킬로 다루면서 세션 초입에 직접 확인하는 방식으로 바뀌었습니다.)

3. 1단계 — 코드를 짜기 전에 플랜부터

비자명한 작업 요청이 들어오면, 코드를 건드리기 전에 플랜 스킬이 먼저 깨어납니다. 플랜에는 정확히 다섯 섹션이 들어갑니다.

1. 요구 이해   한 문장 요약 + 입출력 예시(실제 값) + 엣지/반례
2. 가정        검증 못 한 추론은 전부 "가정:" 라벨로 표기
3. 영향 범위   수정 예상 파일 (가능하면 path:line) + 같이 흔들릴 지점
4. 성공 기준   구체적 검증 명령. "동작한다" 같은 약한 기준 금지
5. 단계별 실행  각 단계마다 → 검증 방법을 붙임

2편에서 말한 "추론 최소화" 가 여기서 강제됩니다. 플랜을 다 쓴 직후 셀프체크 세 가지를 통과해야 플랜이 "완성" 으로 인정됩니다.

  1. 요구 커버리지 — 요청의 각 항목을 책임지는 단계가 플랜에 있는가?
  2. 모호 표현 스캔 — "유효성 검사 추가", "예외 처리", TODO 같은 회피성 표현이 본문에 남았는가?
  3. 이름·타입 일관성 — 1단계에서 정한 함수·필드 이름이 5단계에서도 같게 쓰였는가?

영향 범위가 넓어 플랜을 짜기 전에 코드 탐색부터 필요하면, 메인 세션에서 직접 grep 을 돌리지 않고 읽기 전용 탐색 서브에이전트에 구체적인 질문을 던집니다. 영역이 여러 개(컨트롤러·서비스·저장소·테스트…)면 영역별 에이전트를 한 번에 병렬로 보냅니다. 메인 컨텍스트는 결론만 돌려받고, 광역 탐색의 부산물은 서브에이전트 쪽에 남습니다.

한 줄 오타 수정이나 "이 파일 어디 있죠?" 같은 자명한 요청에는 이 단계 전체를 건너뜁니다. 절차는 비자명한 작업을 위한 것이지, 모든 입력에 무겁게 거는 게 아닙니다.

4. 2단계 — 사전 핑퐁 게이트

플랜이 완성되면, 코드를 한 줄도 짜기 전에 사전(pre-implementation) 핑퐁 게이트가 자동으로 열립니다. 2편에서 말한 외부 모델 교차검토를, 이번엔 코드가 아니라 플랜 에 겁니다.

플랜 본문 + 영향 파일 목록

        ├──▶ 외부 모델: [위험]/[경고]/[안전] 라벨로 검토
        └──▶ 내 쪽 자체 평가 (외부 응답 보기 전에 먼저 작성)


        양쪽 다 [안전]?  ──YES──▶ 게이트 통과

                 NO → 플랜 자동 수정 → 다음 라운드 (최대 3R)

이 시점에 외부 모델이 잡아 주길 기대하는 건 누락된 영향 분석, 잘못된 전제, 범위가 슬그머니 커지는 것 입니다. 라운드 사이의 플랜 수정은 저한테 일일이 안 묻고 자동 적용됩니다(2편 4절의 "명시적 예외"). 3라운드 안에 합의가 안 되면 게이트가 스스로 저에게 결정을 넘깁니다.

플랜이 아직 코드가 아니라 글일 때 이걸 거는 이유는 단순합니다. 잘못된 전제는 글일 때 고치는 게 코드일 때 고치는 것보다 압도적으로 쌉니다.

5. 3단계 — 유일한 허들, 사용자 승인

핑퐁이 끝나면 다듬어진 최종 플랜의 핵심 요약이 저에게 옵니다 — 핑퐁으로 보강된 항목과 5섹션 요약. 그리고 묻습니다.

"이 플랜으로 진행할까요? (승인 / 수정 요청 / 중단)"

작업 전 국면에서 사람이 멈추는 자리는 여기 한 곳뿐입니다. 앞의 셀프체크와 핑퐁은 전부 이 한 번의 승인을 잘 받기 위한 준비였던 셈입니다. 승인 전까지는 코드·설정을 한 줄도 바꾸지 않습니다.

6. 4단계 — 구현

승인이 떨어지면 그제야 코드를 짭니다. 이 단계를 지배하는 원칙은 CLAUDE.mdSurgical Changes 입니다 — 플랜의 영향 범위 안에서만, 건드려야 하는 줄만 바꿉니다. 옆의 멀쩡한 코드를 "개선" 하지 않습니다.

구현 중 Java 파일을 고치면, 다음 단계로 넘어가기 전에 컴파일·타입 진단부터 확인합니다. (예전엔 이걸 PostToolUse 훅으로 자동 강제했는데, 지금은 그 훅은 빼고 에디터 진단으로 챙깁니다. 목적은 같습니다 — 깨진 채로 다음 단계로 넘어가지 않는 것.)

7. 5단계 — 테스트 검수

구현이 끝났다고 작업이 끝난 게 아닙니다. git add 를 권하기 직전, 테스트 검수 스킬이 네 가지를 자기검수합니다.

1. 신규/변경 분기 커버리지
   이번에 만든 분기마다 대응되는 테스트가 있는가?
   "활성/탈퇴", "성공/실패" 같은 짝 분기는 각각 별도 케이스인가?
2. 기존 테스트 영향
   시그니처·위치를 바꿨다면 그걸 쓰던 기존 테스트가 다 갱신됐는가?
3. 위치·네이밍 일관성
   새 테스트가 컨벤션을 따르고, 이름이 무엇을 검증하는지 드러나는가?
4. 회귀 실행
   도메인 한정 회귀 테스트를 실제로 돌려 green을 확인

가장 자주 걸리는 건 1번입니다. 한쪽 분기는 테스트가 있는데 짝이 되는 다른 분기 테스트가 빠진 경우 — 분기별로 1:1 매핑을 짚으면 바로 드러납니다. 누락이 발견되면 "다음 PR에서" 같은 약속으로 넘기지 않고, 그 자리에서 케이스를 채우고 회귀를 다시 돌립니다. 네 항목이 다 통과하지 않으면 git add 흐름 자체가 보류됩니다.

8. 6단계 — 커밋 직전 핑퐁

테스트 검수를 통과하면, 이번엔 커밋 직전(commit-direct) 핑퐁 게이트가 열립니다. 2단계와 같은 외부 모델 교차검토인데, 대상이 플랜이 아니라 실제 코드 변경분(diff) 입니다.

여기엔 중복을 피하는 장치가 하나 있습니다. 직전에 사전 핑퐁(2단계)을 통과했고 구현 diff가 플랜의 영향 범위 안에 그대로 머물렀다면, 같은 변경을 두 번 검토할 이유가 없으므로 이 게이트는 자동으로 건너뜁니다. 반대로 구현 중에 범위가 플랜 밖으로 새어 나갔다면(스코프 크리프), 게이트는 정상적으로 열려 그 새어 나간 부분을 잡습니다.

9. 7단계 — 최종 승인과 커밋

커밋 직전 핑퐁이 합의에 이르면, 변경 파일 목록과 핵심 diff 요약이 저에게 옵니다. 그리고 두 번째이자 마지막 허들입니다.

"이대로 git add 를 진행할까요?"

승인하면 명시한 경로만 git add 하고, staged 결과를 한 줄로 보고한 뒤 커밋 메시지 초안을 제시합니다. git commit 자체는 권한 설정에서 deny 라, 실제 커밋 버튼은 항상 제가 직접 누릅니다. 비가역적인 마지막 한 걸음은 사람 손에 남겨 둔다 — 2편 6절의 원칙이 절차의 끝에서 다시 한 번 작동하는 자리입니다.

10. 세션이 닫힐 때

작업이 한 사이클을 다 돌았든 중간에 멈췄든, 세션을 정리할 때 writing-handoff-doc 스킬로 핸드오프를 남깁니다. 그리고 그 문서는 다음 세션의 0단계(2절)에서 다시 책상 위로 올라옵니다.

   ⑦ 커밋 ──▶ 세션 정리 ──▶ 핸드오프 저장(스킬)

                                  └──▶ 다음 세션 0단계에서 확인

절차가 하나의 고리 라는 게 여기서 드러납니다. 한 세션의 끝이 다음 세션의 시작과 핸드오프로 이어져서, 작업이 여러 세션에 걸쳐도 맥락이 끊기지 않습니다.

11. 이 절차가 막는 것, 그리고 그 비용

솔직하게 적자면, 이 절차는 느립니다. 플랜을 쓰고, 핑퐁을 돌리고, 검수를 하면 "그냥 바로 짜는 것" 보다 분명히 단계가 많습니다. 그래서 자명한 작업 — 한 줄 수정, 오타, 포맷팅, 단순 질의 — 에는 플랜도 핑퐁도 검수도 전부 건너뜁니다. 무거운 절차를 모든 입력에 거는 건 그 자체로 나쁜 설계라고 봤습니다.

대신 비자명한 작업에서 이 절차가 막아 주는 것은 분명합니다.

  • 모호한 요구를 추측으로 메우는 것 → 플랜의 구체 예시 강제가 막습니다.
  • 잘못된 전제로 코드를 다 짜 버리는 것 → 사전 핑퐁이 글 단계에서 잡습니다.
  • 분기를 만들고 테스트를 빠뜨리는 것 → 검수 1번 항목이 잡습니다.
  • 비가역적인 git 사고 → deny 권한과 force-push 훅이 막습니다.
  • 세션이 끊겨 맥락을 잃는 것 → 핸드오프가 잇습니다.

마무리

3부작을 끝내며 남는 한 줄은 이것이었습니다.

하네스 엔지니어링은 "AI를 더 똑똑하게" 가 아니라, "AI가 일하는 절차를 내가 신뢰할 수 있게" 만드는 일이었다.

모델은 제가 못 바꿉니다. 하지만 작업이 플랜에서 출발하도록, 코드를 짜기 전에 한 번 검토받도록, 커밋 직전에 다시 한 번 검토받도록, 세션이 끊겨도 맥락이 이어지도록 — 그 절차는 제가 ~/.claude/ 아래에 코드처럼 쌓을 수 있었습니다.

이 세 편은 완성된 설계도가 아니라 자라는 중인 자산의 현재 단면입니다. 다음에 또 같은 실수를 두 번째로 마주치면, 아마 부품이 한 조각 더 늘어 있을 겁니다. 그때 다음의 저에게 다시 적어 두겠습니다.