Skip to content
CP
Writing
13 분 읽기#code

나만의 Claude Code 하네스 만들기 — 매 세션 길들이지 말고, 저장소에 새겨라

전문가는 매번 Claude를 처음부터 길들이지 않습니다. 자기 작업 방식을 .claude/ 디렉토리에 새겨두죠. 메모리·명령·에이전트·훅을 엮어 — 반복 작업을 통째로 자동화하는 하네스 만드는 법.

지난 글(Claude Code 전문가처럼 쓰기)에서 — 컨텍스트, 권한, 검증 루프라는 세 손잡이와 그걸 다루는 기술 열 개를 봤습니다.

그런데 — 매 세션 그 열 개를 손으로 다시 세팅하고 있다면, 뭔가 잘못된 겁니다. 같은 컨벤션을 또 설명하고, 같은 명령을 또 타이핑하고, "리뷰해줘"를 또 부탁하고. 이건 — 매일 아침 .zshrc를 처음부터 다시 쓰는 것과 같습니다.

전문가는 그러지 않습니다. 그들은 자기 작업 방식을 한 번 새겨두고, 계속 재사용합니다. 그 새겨둔 것 — 모델을 감싸는 골격 일체를 **하네스(harness)**라고 부릅니다.

이 글은 — 흩어진 기술 열 개를 하나의 시스템으로 굳히는 법입니다. 결과물은 추상적인 게 아닙니다 — 저장소 안의 .claude/ 디렉토리, 즉 버전 관리되는 코드입니다.

멘탈 모델 — 하네스는 4개의 질문에 답한다

좋은 하네스는 — Claude에게 매 작업마다 자동으로 4개의 질문에 답해줍니다. 그리고 각 답은 — 저장소 안의 특정 파일/폴더에 삽니다.

무엇을 항상 아는가?      →  CLAUDE.md                  (메모리)
어떤 절차를 실행하나?    →  .claude/commands/          (명령)
누구에게 맡기나?         →  .claude/agents/            (전문가)
무엇을 어기면 안 되나?   →  .claude/settings.json + 훅  (법)

전체 모습은 이렇습니다:

프로젝트/
├── CLAUDE.md                 # 매 세션 자동으로 읽히는 메모리
└── .claude/
    ├── settings.json         # 권한, 훅, 환경변수 — 제어판
    ├── commands/             # /명령 — 재사용 가능한 절차
    │   ├── ship.md
    │   └── fix-issue.md
    ├── agents/               # 서브에이전트 — 전문가 명단
    │   ├── explorer.md
    │   └── code-reviewer.md
    └── hooks/                # 훅 스크립트 — 어길 수 없는 규칙
        ├── format.sh
        └── guard.sh

핵심 성질 하나만 기억하세요 — 하네스는 코드다. 손으로 매번 길들이는 대신, 한 번 짜서 커밋해두면 — 모든 미래의 작업이, 모든 동료가, 1년 뒤의 당신이 그 위에서 시작합니다. 복리로 쌓입니다.

1. 통증에서 시작하라 — 처음부터 다 짓지 말 것

가장 흔한 실패 — 거창한 하네스를 미리 다 설계하려는 것입니다. 에이전트 20개, 명령 30개를 만들어놓고 — 절반은 안 씁니다.

반대로 가세요. 빼기가 아니라, 마찰에서 키우기. 규칙은 단순합니다:

같은 방식으로 Claude를 두 번 고쳐줬다면 — 그건 하네스로 굳힐 신호다.

  • "또 console.log 남겼네" → CLAUDE.md에 규칙 한 줄
  • "또 테스트 먼저 짜라고 설명했네" → /tdd 명령으로
  • "또 포맷 안 맞췄네" → PostToolUse 훅으로
  • "또 코드베이스 전체를 뒤지느라 컨텍스트 날렸네" → explorer 에이전트로

하네스는 — 진짜 겪은 마찰에서 자랍니다. 안 겪은 문제를 위한 설정은 — 그냥 짐입니다.

2. CLAUDE.md — 하네스의 척추

메모리 레이어. 매 세션 자동으로 읽히는 만큼 — 짧고 정확해야 합니다. 길어지면 컨텍스트만 잡아먹고 중요한 게 묻힙니다.

길어질 것 같으면 — 쪼개서 @로 불러오세요:

# CLAUDE.md
 
## 명령
- 빌드 `npm run build` · 테스트 `npm test` · 린트 `npm run lint`
 
## 핵심 규칙
- 객체 수정 금지 — 항상 새 객체 반환
- 파일 200~400줄, 800줄 최대
- 커밋 전 lint + test 통과 필수
 
## 상세 문서 (필요할 때만 펼침)
아키텍처: @docs/architecture.md
DB 스키마: @docs/db-schema.md

@docs/architecture.md처럼 적으면 — 그 파일이 필요한 맥락에서 끌려옵니다. CLAUDE.md 본문은 날씬하게 유지하면서, 깊은 내용은 따로 두는 패턴.

계층도 다시 기억하세요 — 전역(~/.claude/CLAUDE.md, 내 취향)과 프로젝트(CLAUDE.md, 팀 공유)는 합쳐서 읽힙니다. 개인 취향은 전역에, 팀 규칙은 프로젝트에.

3. 슬래시 명령 — 당신의 절차를 굳힌다

여러 단계로 된 작업을 매번 설명하고 있다면 — 명령으로 굳히세요. .claude/commands/ship.md:

---
description: 변경사항을 검증하고 커밋·푸시까지
argument-hint: [커밋 메시지]
allowed-tools: Bash(npm run *), Bash(git *)
---
 
지금까지의 변경을 마무리해줘:
 
1. `npm run lint``npm test` 실행 — 실패하면 멈추고 보고
2. `git diff` 로 의도치 않은 변경 없는지 확인
3. 변경 내용을 요약해 커밋 (메시지: $ARGUMENTS)
4. 현재 브랜치로 push

이제 — /ship "feat: 로그인 추가" 한 줄이면 검증→커밋→푸시가 통째로 돕니다. $ARGUMENTS에 메시지가 들어가고, allowed-tools로 이 명령이 쓸 수 있는 도구를 미리 못박아둡니다.

명령 안에서 — 다른 도구도 엮을 수 있습니다. !로 셸 명령 결과를 끼워 넣고, @로 파일 내용을 끌어옵니다:

---
description: GitHub 이슈를 받아서 고침
---
이슈 내용: !`gh issue view $1`
관련 컨벤션: @CLAUDE.md
 
위 이슈를 처리해줘 — 실패 테스트부터 짜고, 통과시킨 뒤, /ship 으로 마무리.

4. 서브에이전트 — 당신의 전문가 명단

명령이 "절차"라면, 에이전트는 "전문가"입니다. 각 에이전트는 — 격리된 컨텍스트 + 자기만의 도구 권한 + 모델 선택을 가집니다. 자주 쓰는 역할을 명단으로 만들어두세요.

읽기 전용 탐색가 — 컨텍스트를 더럽히지 않고 코드베이스를 뒤지는 용도:

<!-- .claude/agents/explorer.md -->
---
name: explorer
description: 코드베이스를 뒤져 "어디에 무엇이 있는지" 찾는다. 결론만 보고.
tools: Read, Grep, Glob
model: haiku
---
 
당신은 코드 탐색 전문가입니다. 요청받은 것을 찾되 — 파일을 수정하지
마세요. 찾은 위치(파일:줄)와 한 줄 요약만 간결하게 보고하세요.

여기서 두 가지 설계 포인트:

  • tools를 좁게 — explorer는 읽기만. 쓰기 권한을 안 주면, 사고 칠 수가 없습니다.
  • model을 작업에 맞게 — 단순 탐색은 haiku로 충분합니다. 빠르고 쌉니다. 깊은 추론이 필요한 리뷰어만 sonnet/opus로.

자주 쓰는 명단 예시: explorer(탐색), test-writer(테스트 작성), code-reviewer(리뷰), security-reviewer(보안). 메인 세션은 — 이들에게 일을 시키고 결론만 받는 오케스트레이터가 됩니다.

5. 훅 — 어길 수 없는 법

CLAUDE.md의 규칙은 — Claude가 "지키려고 노력"하는 것입니다. 가끔 까먹습니다. 훅은 다릅니다 — 코드가 무조건 실행됩니다. 부탁이 아니라 법.

훅 로직은 스크립트로 빼두는 게 깔끔합니다. 파일 수정 후 자동 포맷, .claude/hooks/format.sh:

#!/usr/bin/env bash
# 수정된 파일 경로는 stdin의 JSON으로 들어온다
file=$(jq -r '.tool_input.file_path // empty')
[ -z "$file" ] && exit 0
case "$file" in
  *.ts|*.tsx|*.js|*.jsx|*.json|*.md) npx prettier --write "$file" ;;
esac

그리고 — 가장 강력한 패턴, 가드 훅. 위험한 행동을 아예 차단합니다. .claude/hooks/guard.sh:

#!/usr/bin/env bash
file=$(jq -r '.tool_input.file_path // empty')
case "$file" in
  *.env|*.env.*|*/secrets/*)
    echo "보호된 파일은 수정할 수 없습니다: $file" >&2
    exit 2 ;;   # PreToolUse에서 exit 2 → 행동을 차단하고 Claude에 사유 전달
esac
exit 0

settings.json에 시점별로 연결합니다:

// .claude/settings.json
{
  "hooks": {
    "PreToolUse": [
      { "matcher": "Edit|Write",
        "hooks": [{ "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/guard.sh" }] }
    ],
    "PostToolUse": [
      { "matcher": "Edit|Write",
        "hooks": [{ "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/format.sh" }] }
    ]
  }
}

훅이 하네스의 마지막 조각인 이유 — 훅이 있으면 자동 수락을 켤 수 있습니다. 가드 훅이 .env를, 포맷 훅이 스타일을, Stop 훅이 테스트를 지키면 — Claude가 무슨 짓을 해도 선을 넘지 못합니다. 그제서야 — 안심하고 속도를 낼 수 있습니다.

6. settings.json — 제어판

권한과 훅과 환경변수가 모이는 곳. 권한 부분은 — 명령·에이전트와 함께 보면 더 강력합니다:

{
  "permissions": {
    "allow": ["Bash(npm run test:*)", "Bash(npm run lint)", "Read", "Edit"],
    "deny": ["Read(./.env)", "Bash(rm -rf *)"]
  },
  "hooks": { /* 위와 같이 */ }
}

설정에도 계층이 있습니다 — 우선순위 순으로:

  • .claude/settings.local.json — 내 개인 설정, git에 안 올림 (.gitignore에 추가)
  • .claude/settings.json — 팀 공유 설정, git에 커밋
  • ~/.claude/settings.json — 모든 프로젝트 공통

팀 규칙은 settings.json에, 내 개인 취향은 settings.local.json에. 이 분리가 — 하네스를 공유 가능하게 만듭니다.

7. 하네스는 팀 자산이다 — 공유하고 재사용하라

.claude/를 저장소에 커밋하는 순간 — 하네스는 당신 것만이 아니게 됩니다.

  • 동료 — 저장소를 clone하면 같은 하네스를 그대로 물려받습니다. 신입이 첫날부터 팀의 컨벤션·명령·가드를 가진 Claude로 시작합니다.
  • CI — 헤드리스 모드로 같은 하네스를 돌립니다. claude -p "/ship"처럼 비대화식 실행이 가능해서, 야간 작업이나 PR 자동화에 그대로 씁니다.
  • 여러 프로젝트 — 프로젝트를 넘나드는 재사용은 플러그인/스킬로. 자주 쓰는 명령·에이전트 묶음을 플러그인으로 만들면, 어느 저장소에서든 불러옵니다. (어떤 걸 깔지는 설치할 만한 Claude Code 플러그인 참고.)

전부 엮으면 — 작업 하나의 흐름

하네스가 갖춰지면, 동료의 하루는 이렇게 흐릅니다. 명령 한 줄에서 시작합니다:

/fix-issue 128

그 뒤에 벌어지는 일 — 전부 자동으로:

1. 명령이 `gh issue view 128`로 이슈를 읽음        (commands/fix-issue.md)
2. explorer 에이전트가 관련 코드를 찾아 결론만 보고   (agents/explorer.md, haiku)
3. 실패 테스트 작성 → 구현 → npm test 초록불까지 반복  (검증 루프)
4. 파일 저장할 때마다 prettier 자동 실행            (hooks/format.sh)
5. .env 건드리려 하면 즉시 차단                     (hooks/guard.sh)
6. code-reviewer 에이전트가 변경을 리뷰              (agents/code-reviewer.md)
7. /ship 으로 lint·test·커밋·푸시                   (commands/ship.md)

동료는 — CLAUDE.md를 읽지도, 컨벤션을 외우지도, 도구를 일일이 허용하지도 않았습니다. 하네스가 다 알고 있으니까요. 이게 — 흩어진 기술 열 개를 시스템으로 굳힌다는 말의 뜻입니다.

흔한 함정 5가지

1. 처음부터 다 짓기 안 쓸 에이전트 20개. → 마찰에서 한 조각씩 키우기.

2. 하네스 부패(rot) 삭제된 파일을 가리키는 규칙, 사실과 다른 명령. 거짓말하는 하네스는 없느니만 못합니다. → 코드처럼 주기적으로 손보기.

3. CLAUDE.md 비대화 소설 같은 메모리가 컨텍스트를 잡아먹음. → 날씬하게, 깊은 건 @로.

4. 가드 없는 자동 수락 훅 없이 auto-accept만 켜면 — 안전망 없는 외줄타기. → 가드 훅 먼저, 그다음 속도.

5. .claude/ 안 올리기 (또는 비밀째로 올리기) 하네스가 안 퍼지거나, 키가 새거나. → 공유 설정은 커밋, 개인·비밀은 분리.

마무리 — 진짜 비밀

git, 그리고 Claude Code 기술 열 개를 지나 — 이 시리즈의 마지막 한 문장은 이겁니다.

AI를 잘 쓰는 엔지니어는 — 더 좋은 프롬프트를 쓰는 사람이 아니라, 더 좋은 하네스를 만드는 사람이다.

매 세션, 당신은 코드만 만드는 게 아닙니다 — 코드를 만드는 기계 자체를 다듬을 수 있습니다. 오늘 고친 규칙 한 줄, 추가한 가드 훅 하나가 — 앞으로의 모든 작업에서 복리로 돌아옵니다. 그래서 하네스는 — 부산물이 아니라 일급 산출물입니다. 리뷰하고, 리팩토링하고, 버전 관리하세요.

막힐 때 던질 질문은 이제 하나 더 늘었습니다 — "Claude가 충분히 아는가? 할 권한이 있는가? 확인할 방법이 있는가?" 그리고 — "이걸 두 번째 하고 있다면, 하네스에 새길 때 아닌가?"

다음 글에서는 — 하네스를 한 단계 더 밀어붙입니다. 사람이 매번 시작 버튼을 누르지 않아도 도는 — 자율 루프(autonomous loop)와 야간 에이전트 이야기. 하네스가 충분히 단단해지면, 에이전트는 — 잘 때도 일합니다.

관련 글