개발자
류준열
하네스 만들기 1탄

작년에 바이브코딩으로 만들었던 캘린다이어리에 하네스를 달고 있다.
CLAUDE.md 경량화 가이드 문서
https://www.humanlayer.dev/blog/writing-a-good-claude-md 를 클로드한테 읽으라했다. 참고하였다.
요약하면 다음과 같다.
CLAUDE.md에 다 때려박지 마라- 프로젝트의 목적(WHY),내용(WHAT),방법(HOW)을 정의하라
150~200개의 지시가 적당하다
- 좋은 모델일수록 더 많은 지시에 주의를 기울이지만, 결국에 한계는 있다.
- 명령어 개수가 증가함에 따라 명령어 품질은 균일하게 저하된다.
- 따라서, 작업에 보편적으로 적용 가능한 지침만 포함하는것이 좋다. (비 보편적 내용이 많을수록 균일하게 품질 저하)
점진적 정보 공개
- 클로드가 필요할때만 지침을 볼 수 있도록 한다.
- 작업별 지침은 자체 설명적인 이름을 가진 별도 md에 저장하고 CLAUDE.md는 목차 역할을 하도록 한다. (복사본 보다는 포인터 사용)
agent_docs/
|- building_the_project.md
|- running_tests.md
|- code_conventions.md
|- service_architecture.md
|- database_schema.md
|- service_communication_patterns.md
- 예시 코드를 남길때는 코드조각대신 file:line을 남겨라. 코드조각은 작업시 동기화되지 않아 구식 정보가 될 수 있다.
클로드는 린터가 아니다.
- 문서 기반 규칙은 실패 확률이 내재되어있다.
CLAUDE.md에 컨벤션을 추가하지 말고 린터, 허스키 등으로 강제하라. (LLM은 비결정적으로 작업을 이행한다.)
자동생성 하지마라
/init을 사용하면 대규칙CLAUDE.md 에 다 때려박지 마라에 위배되는CLAUDE.md가 생성된다.CLAUDE.md는 하네스에서 가장 효과가 큰 부분이므로 최상의 결과를 얻으려면 신중히 작성해야 한다.
실제 작업 내용
CLADUE.md 경량화
CLAUDE.md에서 페르소나(ex: 당신은 시니어 개발자다), 코드예시, 안티패턴 목록을 제거했다.agent_docs/5개 파일로 상세 규칙 분리
**Core Business Rules**
- **Single Friend Model**: 사용자당 친구 1명 제한. 이미 친구가 있는 사용자는 검색 결과에서 제외.
- **Calendar Entry**: 날짜 + userId 조합으로 하루 하나 제한. 이미지 최대 10장.
- **State Management**: React Query = 서버 상태, Zustand = 전역 클라이언트, useState = 로컬 UI.
**Detailed Conventions (Progressive Disclosure)**
상세 컨벤션과 패턴은 `agent_docs/` 참조:
- `agent_docs/code-convention.md` — 네이밍/스타일 규칙
- `agent_docs/react-query-convention.md` — 캐시 전략, query key 관리
- `agent_docs/frontend-patterns.md` — FE 컴포넌트/라우팅/상태관리 패턴
- `agent_docs/backend-patterns.md` — BE 아키텍처/인증/에러처리/S3 패턴
- `agent_docs/mobile-patterns.md` — Mobile MVVM/Service/Orval/Expo 패턴
**Git Rules**
- 커밋 메시지에 `Co-Authored-By` 등 광고성 서명을 붙이지 않는다.
PretoolUse, 린터, 허스키, prettier로 규칙 강제
CLAUDE.md 에게 '이렇게 코딩해라' 라고 적어두면 AI든, 사람이든 비결정적으로 이행한다.
바쁘면 무시하고 모르면 못지킨다.
문서 기반 규칙은 실패 확률이 내재되어있다.
PretoolUse이용한 시크릿 접근 차단
PretoolUse 는 Read, Edit, Write, Bash 등 도구 실행 직전에 발동되는 훅이다.
.claude/setting.json 세팅
{
"hooks": {
"PreToolUse": [
{
"matcher": "Read|Edit|Write|Bash",
"hooks": [
{
"type": "command",
"command": "bash ~/.claude/hooks/block-secrets.sh"
}
]
}
]
},
...
}
스크립트
.env, api key 등에 접근을 방지하는 스크립트를 만들어달라고 하면 아래 스크립트가 생성된다.
# block-secrets.sh
#!/bin/bash
# Block access to sensitive files (.env, API keys, secrets, credentials)
# Used as a Claude Code PreToolUse hook
set -euo pipefail
INPUT=$(cat)
TOOL_NAME="${CLAUDE_TOOL_NAME:-}"
# Sensitive file patterns (case-insensitive matching)
SENSITIVE_PATTERNS=(
'\.env'
'\.env\.'
'apikey'
'api_key'
'secret'
'credential'
'private.key'
'\.pem$'
'\.key$'
'token'
'password'
'\.secrets'
)
# Build combined regex
REGEX=""
for pattern in "${SENSITIVE_PATTERNS[@]}"; do
if [ -z "$REGEX" ]; then
REGEX="$pattern"
else
REGEX="$REGEX|$pattern"
fi
done
check_path() {
local path="$1"
if echo "$path" | grep -iEq "($REGEX)"; then
echo '{"decision":"block","reason":"🚫 민감 파일 접근 차단: .env, API key, secret, credential 등 민감 정보가 포함된 파일에 대한 접근이 금지되어 있습니다."}'
exit 0
fi
}
case "$TOOL_NAME" in
Read|Edit|Write)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
if [ -n "$FILE_PATH" ]; then
check_path "$FILE_PATH"
fi
;;
Bash)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
if [ -n "$COMMAND" ]; then
# Check if the command references sensitive files
if echo "$COMMAND" | grep -iEq "($REGEX)"; then
echo '{"decision":"block","reason":"🚫 민감 파일 접근 차단: .env, API key, secret, credential 등 민감 정보가 포함된 파일을 참조하는 명령어가 차단되었습니다."}'
exit 0
fi
fi
;;
esac
# Allow everything else
echo '{"decision":"allow"}'
prettier, lint, 허스키
prettier, ESLint, 허스키등으로 커밋마다 포매팅, 품질 강제
- 사람이 작업할때는 허스키가 로컬작업용 커밋을 막는 불편함이 있었지만, 똑똑한 AI이기 때문에 이런 상황을 겪지 않을것이라 가정하고 과감히 허스키를 넣어주었다.
- CI에서 체크하는건 push 후에 실패를 알게되기 때문에 피드백루프가 넘 느리다.
결과
- 커밋 시: Prettier 포멧 -> ESLint -> tsc 타입 체크
- 시크릿 노출: PreToolUse에
bash ~/.claude/hooks/block-secrets.sh넣어서 방지
다음은 테스트코드 넣기