하네스 엔지니어링 기초

모델을 바꾸는 대신 모델이 일하는 환경을 설계합니다. 컨텍스트·권한·검증·피드백 네 축으로 Claude Code 하네스를 세우는 법과 훅·settings 실전 예시.

18분 갱신

같은 모델, 같은 요금제인데 어떤 팀은 매일 자동화가 돌아가고 어떤 팀은 데모에서 멈춥니다. 60회 넘는 스터디 세션에서 본 차이는 모델이 아니라 하네스였습니다. 이 글은 실전 코스의 첫 페이지로, 우리 교육연합의 집안 원칙인 하네스 엔지니어링을 네 축으로 풀고 Claude Code의 훅·settings·CLAUDE.md로 직접 세우는 방법을 다룹니다. 읽고 나면 다음 글 Skills 셋업에서 만드는 스킬을 어디에 얹어야 할지 보입니다.

핵심 요약

  • 프롬프트는 부탁이고 하네스는 강제입니다. 지켜야 할 규칙은 말로 당부하지 말고 훅에서 차단합니다.
  • 성공은 조용히, 실패만 시끄럽게. 통과한 검사는 출력이 없고, 실패만 exit 2로 화면에 뜹니다.
  • 실수는 규칙이 됩니다. 같은 실수가 두 번 보이면 그날 CLAUDE.md나 훅에 올립니다.
  • 투자 순서는 컨텍스트 → 검증 → 권한 → 피드백입니다. 모델 교체는 맨 뒤입니다.

하네스란

하네스는 모델을 감싸는 실행 환경 전체입니다. 무엇을 보여주는지(CLAUDE.md), 무엇을 허용하는지(permissions), 끝을 누가 판정하는지(훅), 실패 시 어떤 메시지를 돌려주는지(stderr)가 전부 하네스입니다. 공식 문서도 CLAUDE.md는 "강제된 구성이 아닌 컨텍스트"이며 작업을 막으려면 PreToolUse 훅을 쓰라고 못 박습니다. 우리 표현으로는 "프롬프트는 부탁, 하네스는 강제"입니다.

하네스 설계의 네 축

1. 컨텍스트: 무엇을 보여줄 것인가

Claude Code는 시작 시 ~/.claude/CLAUDE.md(개인) → ./CLAUDE.md 또는 ./.claude/CLAUDE.md(프로젝트) → ./CLAUDE.local.md(개인·gitignore) 순으로 읽어 이어 붙입니다. 파일당 200줄 이하를 권장하고, 특정 폴더에서만 필요한 규칙은 .claude/rules/ 아래 paths frontmatter로 범위를 좁힙니다. 검증 가능한 문장만 씁니다. "코드를 깔끔하게"가 아니라 "커밋 전 pnpm test 실행"처럼 씁니다.

---
paths:
  - "app/api/**/*.ts"
---
# 결제 API 규칙
- 금액은 서버가 정한다. 클라이언트가 보낸 금액을 신뢰하는 코드 금지.

2. 권한: 무엇을 허용할 것인가

settings는 관리(managed) > 명령줄 > .claude/settings.local.json > .claude/settings.json > ~/.claude/settings.json 순으로 우선합니다. 팀 규칙은 프로젝트 settings.json에 커밋하고, 개인 예외는 local에 둡니다. 우리 CRM 프로젝트의 "운영 DB는 성역" 원칙은 이렇게 파일이 됩니다.

{
  "permissions": {
    "allow": ["Bash(pnpm test *)", "Bash(git status *)"],
    "deny": ["Read(./.env)", "Read(./secrets/**)", "Bash(rm -rf *)"],
    "ask": ["Bash(git push *)"],
    "defaultMode": "acceptEdits"
  }
}

모드는 default, acceptEdits, plan, bypassPermissions, dontAsk, auto 여섯 가지이며 Shift+Tab으로 순환합니다. disableBypassPermissionsMode를 켜면 우회 모드 자체를 잠급니다.

3. 검증: 성공을 어떻게 판정할 것인가

"됐습니다"라는 문장은 증거가 아닙니다. 우리 정지 규칙은 실행 화면과 로그입니다. 훅은 이 규칙을 기계로 옮깁니다. PreToolUse 훅이 exit 2로 끝나면 도구 호출이 차단되고 stderr가 Claude에게 전달됩니다. 아래는 결제 파일 수정 시 테스트를 먼저 강제하는 프로젝트 훅입니다(.claude/settings.json).

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/guard-billing.sh",
            "timeout": 60
          }
        ]
      }
    ]
  }
}
#!/bin/bash
# guard-billing.sh: lib/billing 아래 수정이면 테스트 통과를 먼저 요구
file=$(jq -r '.tool_input.file_path // empty')
case "$file" in
  */lib/billing/*)
    pnpm test --silent >/dev/null 2>&1 && exit 0
    echo "billing 테스트 실패 상태에서는 수정 금지. pnpm test 먼저." >&2
    exit 2 ;;
esac
exit 0

Windows는 훅 항목에 "shell": "powershell"을 지정하면 PowerShell로 실행됩니다.

4. 피드백: 실패가 얼마나 친절한가

exit 2의 stderr는 Claude가 다음 행동을 정하는 유일한 단서입니다. "실패"만 적으면 같은 시도를 반복합니다. 무엇이 왜 막혔고 무엇을 하면 풀리는지 한 줄로 적습니다. 반대로 통과한 검사는 아무 말도 하지 않게 둡니다. 성공 메시지가 쌓이면 실패가 묻힙니다.

실전 체크리스트

  1. CLAUDE.md의 모든 문장이 검증 가능한가(명령·경로·숫자).
  2. deny에 .env와 운영 접속 정보가 있는가.
  3. 되돌리기 어려운 행동(push·배포·삭제)이 ask나 훅에 걸리는가.
  4. 실패 훅의 stderr에 해결 방법이 적혀 있는가.
  5. 지난주 반복된 실수가 규칙 파일에 올라갔는가.

흔한 오해

"CLAUDE.md에 굵게 쓰면 지킨다"는 오해가 가장 흔합니다. 공식 문서 기준으로 CLAUDE.md는 시스템 프롬프트가 아니라 사용자 메시지로 전달되며 엄격한 준수를 보장하지 않습니다. 반드시 지켜야 하면 훅입니다. 두 번째 오해는 "훅을 많이 걸수록 안전하다"입니다. 통과 시에도 출력을 뿜는 훅은 컨텍스트만 태웁니다.

투자 순서

컨텍스트 정리(하루) → 검증 훅 한 개(반나절) → 권한 파일(한 시간) → 피드백 문구 다듬기(지속) 순입니다. 모델 상향은 이 네 가지가 끝난 뒤에야 효과가 보입니다.

다음 레슨

반복 지시를 파일로 굳히는 Skills 셋업으로 이어집니다. 하네스가 울타리라면 스킬은 그 안에서 쓰는 도구입니다.

정리

  • 하네스는 컨텍스트·권한·검증·피드백 네 축입니다.
  • 강제는 훅(exit 2)과 permissions로, 안내는 CLAUDE.md로 나눕니다.
  • 실패만 소리 나게, 실수는 그날 규칙으로 올립니다.

자주 묻는 질문

훅 스크립트는 어디에 두나요?

프로젝트 .claude/hooks/ 폴더에 두고 ${CLAUDE_PROJECT_DIR}로 참조하면 팀원 누가 열어도 같은 경로로 풀립니다. 실행 권한(chmod +x)을 잊지 마세요.

비개발자도 훅을 쓸 수 있나요?

네. 우리 초급 8주 6주차에서 "이름만 알아두라"고 했던 그 부품입니다. 처음에는 .env 읽기 차단 한 줄짜리 deny 규칙부터 시작하면 충분합니다.

훅이 자꾸 막아서 답답합니다.

막힌 이유가 stderr에 없으면 훅의 잘못이니 문구부터 고칩니다. 정말 예외라면 settings.local.json에서 개인만 풀고 팀 파일은 그대로 둡니다.

모델을 올리면 하네스가 덜 필요해지나요?

아닙니다. 강한 모델일수록 행동 범위가 넓어지므로 권한과 검증이 먼저입니다. 모델 종속 없이 원리 중심으로 가르치는 이유입니다.

하네스hookssettingsCLAUDE.md권한검증 게이트

팀에 클로드코드를 도입하려면 실제 업무에 맞춘 설계가 필요합니다. 무료 상담 신청 →