본문으로 건너뛰기

© 2026 Molayo

Zenn헤드라인2026. 06. 02. 22:57

Claude Code의 agents / skills / hooks를 어떻게 구분해서 사용할까? 실제 제품 개발에서 도출한 운영 규칙

요약

Claude Code의 핵심 구성 요소인 agents, skills, hooks를 실제 제품 개발 과정에서 어떻게 구분하고 운영해야 하는지에 대한 실무 가이드를 제공합니다. CLAUDE.md의 한계를 극복하고 효율적인 개발 플로우를 구축하기 위한 운영 규칙을 다룹니다.

핵심 포인트

  • CLAUDE.md는 항상 적용되지만 얕은 규칙을 정의함
  • skills는 호출 시에만 동작하며 깊은 문맥을 처리함
  • agents와 hooks를 활용해 복잡한 개발 절차를 구조화함
  • 실제 제품 개발(Flutter/Supabase) 경험을 바탕으로 한 실무적 접근

Claude Code의 운영 규칙을 정리한 기록입니다. 마찬가지로 "편리한 기능이 있다는 것은 알겠지만, 결국 어떻게 구분해서 사용해야 할지 모르겠다"라고 고민하고 계신 분들에게 참고가 되었으면 하는 마음으로 해설 기사로 정리했습니다. 아울러, 제가 나중에 다시 보기 위한 비망록 역할도 겸하고 있습니다.

전제: 무엇을 만들면서 테스트했는가

저는 현재 마음챙김 명상 앱을 개발하고 있습니다. 스트레스, 집중력 부족, 수면 문제를 겪는 20~40대 비즈니스맨을 대상으로, 음성 메서드를 통해 일상의 컨디션을 조절하는 것을 목적으로 하는 앱입니다.

이미 테스트 버전을 공개했습니다. 아래의 QR 코드 또는 다음 링크를 통해 설치할 수 있습니다.

インストール用QRコード

설치 시 몇 가지 전제가 있습니다.

  • 테스트 버전이며, 무료로 공개하고 있습니다.
  • Android 단말기에서는 설치 시 "출처를 알 수 없는 앱 허용" 설정이 필요합니다.
  • 기간 한정 공개입니다.
  • 앱 내에 문의 기능이 있습니다. 궁금한 점이 있다면 편하게 보내주세요.

이 기사에서 소개하는 내용은, 해당 앱을 실제로 개발하면서 Claude Code의 운영을 어떻게 구성해야 개발이 빠르고 안정적일지 시행착오를 거친 결과입니다. 이론적인 정리가 아니라, 명상 앱이라는 실제 제품(Product)의 개발 플로우에 편입시켜 사용해 본 후의 판단임을 전제로 작성합니다. 기술 스택은 Flutter (Clean Architecture + Riverpod)와 Supabase입니다.

계기: 평가가 높은 하네스(Harness)를 본보기로 삼다

Claude Code를 깊게 사용하다 보면 곧 이 벽에 부딪히게 됩니다.

  • CLAUDE.md (항상 읽히는 공통 규칙)에 너무 많은 내용을 써서, 정작 중요한 규칙이 지켜지지 않는다.
  • 편리하다고 알려진 skills / agents / hooks가 있지만, 어떤 것을 어떻게 구분해서 사용해야 할지 모르겠다.
  • 평가가 높은 사람의 설정 세트(하네스)를 모방하려고 해도, 각 부품이 밀접하게 얽혀 있어 자신의 프로젝트에 이식할 수 없다.

그래서 공개되어 있는 평가가 높은 하네스 엔지니어링 사례(affaan-m/ecc)를 본보기로 삼아, 자신의 운영에 도입할 수 있는 부분이 없는지 찾아보았습니다. 지금까지 저는 CLAUDE.md와 skills 정도만 사용해 왔기에, 아직 사용하지 못한 agents와 hooks를 이해하고 도입한다면 성장 가능성이 있다고 생각했기 때문입니다.

다만, 본보기 세트를 그대로 가져오는 것은 성공적이지 않았습니다. 각 skill / agent / hook가 서로 의존하고 있기 때문에, 실행해도 무엇이 일어나고 있는지 추적할 수 없고, 나온 결과물이 올바른지도 판단할 수 없기 때문입니다. 본보기에서는 구조와 사고방식만을 빌려오고, 내용은 자신의 앱에 맞춰 다시 만드는 방식으로 진행했습니다.

3가지 메커니즘을 간단히 해설

구분해서 사용하는 법에 들어가기 전에, agents / skills / hooks가 "언제·어떻게 발화(Trigger)하는가"와 "어떤 문맥(Context)에서 동작하는가"에 대해 해설하겠습니다. 구분하는 판단 기준은 결국 이 두 가지로 집약되기 때문입니다.

메커니즘실체언제 발화하는가문맥 (Context)
CLAUDE.md항상 읽히는 규칙 문서항상 (매 턴 읽힘)메인 대화와 공유
...

파악해 두어야 할 점은 다음 두 가지입니다.

  • CLAUDE.md는 "항상 적용되지만 얕고", skill은 "호출되었을 때만 적용되지만 깊다"는 관계에 있습니다. 무거운 절차를 전부 CLAUDE.md에 적으면 매 턴의 문맥을 압박하여 중요한 지시가 흐려집니다. 반대로 "반드시 지켜줬으면 하는 발화 조건"을 skill에만 적으면, 그 skill이 호출되지 않는 한 적용되지 않습니다.
  • 서브 에이전트(Sub-agent)만은 문맥이 독립되어 있습니다. 메인 대화의 정보를 이어받지 않는 대신, 메인 문맥을 더럽히지 않습니다. 그 대신, 사용자에게 질문하는 것(AskUserQuestion)이나 다른 에이전트를 기동하는 것은 불가능하다는 제약이 있습니다.

이 "발화 타이밍"과 "문맥이 공유되는가 독립적인가"라는 두 축이 그대로 구분해서 사용하는 판단 기준이 됩니다.

구분법 1: agents는 "역할"을 분리하는 것

서브 에이전트는 계획하기, 설계하기, 구현하기, 리뷰하기와 같이 하나의 커다란 태스크를 완수하는 것을 목표로 설정하는 단위입니다. 문맥이 독립되어 있다는 성질 덕분에, 분리하는 기준은 자연스럽게 결정됩니다.

첫째로, 문맥(Context)을 오염시키고 싶지 않거나 불필요한 문맥을 가져오고 싶지 않은 작업에 적합합니다. 예를 들어 구현(Implementation)은 PRD와 설계 정보만 있으면 진행할 수 있는 작업이므로, 대화의 자잘한 경위는 필요하지 않습니다. 리뷰(Review)는 오히려 반대입니다. 구현 중의 "이렇게 수정했다"라는 경위를 알고 있으면, 그에 휩쓸려 판단이 느슨해질 수 있습니다. 선입견 없는 눈으로 보여주고 싶으므로, 독립된 문맥으로 움직이는 서브 에이전트(Sub-agent)가 적합합니다.

둘째로, 다른 역할과 의존하지 않고 정의할 수 있다면 병렬로 기동할 수 있어 효율이 올라갑니다. 예를 들어 코드 품질 리뷰와 보안 리뷰는 서로 독립적이므로 동시에 실행할 수 있습니다.

솔직히 말하면, 에이전트(agents)는 도입하는 순간 극적으로 변하는 종류의 것이 아닙니다. 다만, 위의 기준(독립된 문맥이 필요한 경우, 병렬 처리가 가능한 경우)으로 분리할 수 있는 작업을 찾아 역할로 정의해 나가면 확실히 효과를 보게 됩니다.

서브 에이전트의 제약 사항 대응

서브 에이전트는 사용자에게 직접 질문할 수 없습니다. 반면, 명상 앱의 개발 플로우에는 "사용자의 승인을 얻은 후 다음으로 진행한다"라는 게이트(Gate)를 많이 설정해 두었습니다. 이 두 가지는 충돌합니다.

대응책으로서, 승인이 필요한 작업을 맡기는 에이전트에는 본문에 "승인을 대행하지 않고, 결과물과 승인 요청을 위임처로 반환한다"라는 전달 규칙을 명시했습니다. 실제로 테스트 주도 구현(TDD Implementation)을 담당하는 에이전트에는 다음과 같이 작성되어 있습니다.

## 위임처와의 전달 계약 (중요)
당신은 서브 에이전트이므로, AskUserQuestion을 호출할 수 없으며, 다른 에이전트도 기동할 수 없다.
tdd-workflow 스킬이 "사용자 승인을 얻은 후 다음으로 진행"할 것을 요구하는 게이트 (E2E 테스트 케이스
...

이와 같이 계약을 명문화해 두면, 서브 에이전트의 제약과 "승인 필수"라는 규칙을 양립할 수 있습니다.

구분법 2: skill은 "워크플로우"를 고정하는 것

스킬(skill)은 세부적이고 실시 빈도가 높으며, 방치하면 방식이 흔들리기 쉬운 태스크의 절차와 규칙을 정의하여 재현성 높게 실행할 수 있는 상태를 만드는 단위입니다.

명상 앱 개발에서는 기능 개발의 흐름 그 자체를 skill로 만들었습니다. 서두에 역할을 다음과 같이 선언하고 있습니다.

이 스킬은 PRD 참조부터 구현 완료까지의 개발 워크플로우를 총괄한다.
각 페이즈의 구체적인 작업(설계·구현 계획·테스트 주도 구현)은 전용 에이전트·스킬에
위임하며, 이 스킬은 워크플로우의 진행 관리와 코어 규칙(Core Rule)의 철저한 준수에 집중한다.

포인트는 skill 자체가 절차를 실행하지 않고, 각 페이즈의 실제 작업(설계·구현·리뷰)은 각각 전용 에이전트에게 위임하고 있다는 점입니다. skill은 흐름의 관리와, 모든 페이즈에서 지켜야 할 코어 규칙(테스트 주도·보안 우선·실행 전 계획·계획 업데이트)의 철저한 준수만을 담당합니다. "무거운 절차는 skill, 가벼운 상시 규칙은 CLAUDE.md"라는 구분법이 그대로 효과를 발휘합니다.

구분법 3: hook은 "결정론적인 강제"를 거는 것

훅(hook)은 필요한 타이밍에 100% 동일한 처리를 재현하고 싶을 때 사용합니다. 정적 분석(Static Analysis)이나 명령어로 작성할 수 있는 처리가 대상입니다.

이 부분이 이번에 가장 효과적이었습니다. 매번 반드시 거쳐야 하는 결정론적인 처리를 모델의 절차 준수(잊어버릴 여지가 있음)에 의존하는 것은 좋지 않은 방법입니다. hook에 맡기면 하네스(Harness)가 반드시 실행하므로 잊어버리지 않습니다.

명상 앱에서는 정적 분석을 hook으로 옮겼습니다. 등록 설정은 다음과 같습니다. 편집할 때마다 포맷팅하고, 턴(Turn) 종료 시에 분석하는 2단계 구조입니다.

{
"hooks": {
"PostToolUse": [
...

PostToolUse (도구 실행 후)에 등록한 포맷팅 훅은, 편집된 .dart 파일만을 dart format으로 포맷팅합니다. 가벼운 처리이므로 편집할 때마다 실행합니다. 중요한 점은 여기서 "이 세션에서 .dart를 변경했다"라는 표식(Marker) 파일을 남겨둔다는 점입니다.

# 이 세션에서 .dart를 변경했다는 표식을 남긴다 (Stop 훅이 이를 보고 분석한다)
SID=$(printf '%s' "$INPUT" | hook_session_id)
touch "$(hook_pending_marker "$SID")" 2>/dev/null || true
...

반면, Stop (턴 종료 시)에 등록한 분석 훅은 해당 표식이 있는 경우에만 무거운 정적 분석을 실행합니다. flutter analyze의 에러인지, custom_lint...

(Riverpod의 오용 검출)이 발견되면, exit 2로 턴을 차단하여 수정을 유도합니다.

# 이 세션에서 .dart를 편집하지 않았다면 분석하지 않음
[ -f "$MARKER" ] || exit 0
...
...

flutter analyze는 분석 서버를 구동하는 데 몇 초가 소요되기 때문에, 편집할 때마다 실행하면 무거워집니다. 그래서 가벼운 포맷팅(Formatting)은 편집할 때마다, 무거운 분석은 1턴에 1번으로 역할을 나누고 있습니다.

이 hook의 배분을 늘려갈수록 모델의 편차(Variance)에 의존하는 부분이 줄어들고 품질이 상향 평준화됩니다. 하네스(Harness) 설계의 핵심은 바로 이 지점에 있다고 느꼈습니다.

참고가 된 hook: 도구 호출 횟수를 세어 다른 행동을 유도하기

모범 사례(ECC) 중에 hook의 방어 범위가 얼마나 넓은지를 보여주는 흥미로운 예시가 있었습니다. suggest-compact.js라는 hook으로, 도구 호출 횟수를 세어서 임계값(Threshold)에 도달하면 /compact (문맥 압축)를 제안하는 것입니다. 포맷팅이나 lint와 같이 "처리를 실행하는" hook과는 성격이 다릅니다.

메커니즘은 다음과 같습니다. Claude Code는 도구를 사용할 때마다 hook으로 정보를 전달합니다. 이 hook은 그 정보를 받아 세션별 카운터 파일을 하나씩 증가시킵니다.

const counterFile = path.join(getTempDir(), `claude-tool-count-${sessionId}`);
const threshold = parseInt(process.env.COMPACT_THRESHOLD || '50', 10);
// 기존 카운트를 읽어 +1, 없으면 1부터 시작

그리고 카운트가 임계값(기본 50회)에 도달했을 때, 표준 출력(Standard Output)으로 정해진 형식의 JSON을 반환합니다.

if (count === threshold) {
const msg = `${threshold} tool calls reached - consider /compact if transitioning phases`;
output({ hookSpecificOutput: { hookEventName: 'PreToolUse', additionalContext: msg } });
...

additionalContext가 다음 모델의 턴에 "보충 정보"로서 삽입됩니다. 도구 실행 자체를 차단하지 않고, 제안만을 살며시 주입하는 구조입니다. 50회를 초과한 후에도 25회마다 동일한 제안을 하도록 되어 있습니다.

왜 자동 압축이 아니라 수동 제안인지에 대해 말하자면, 자동 압축은 작업 도중과 같이 어중간한 시점에 발생하기 쉬워 문맥(Context)이 깨질 수 있기 때문입니다. 반면 이 hook은 탐색이 일단락되었거나 마일스톤을 마쳤을 때와 같은 구분점에서 압축을 유도하는 것을 목표로 합니다.

여기서 배울 수 있는 점은, hook이 단지 "포맷팅을 하거나" "lint를 적용하는" 것만이 아니라는 사실입니다. 결정론적(Deterministic)으로 상태(여기서는 도구 호출 횟수)를 관측하고, 임계값에 따라 다른 워크플로우를 유도하는 운영의 자동 조종(Autopilot) 용도로도 사용할 수 있습니다.

한꺼번에 모두 도입하지 않기: 단계적으로 키우기

ECC와 같이 완성된 하네스를 보면 전부 도입하고 싶어지지만, 이는 피하는 것이 좋다고 생각합니다. 밀접하게 얽힌 설정을 갑자기 가져오면, 각 부품이 무엇을 하고 있는지, 나온 결과물이 올바른지 스스로 판단할 수 없기 때문입니다.

추천하는 방법은 가려운 부분이나 효과가 높다고 느껴지는 부분부터 순차적으로 키워나가는 것입니다. 저는 다음 순서로 진행했습니다.

  • CLAUDE.md로 공통 규칙을 언어화한다 (먼저 횡단 규칙을 문장으로 작성)
  • 반복되는 절차를 skill로 만든다 (재현성을 높임)
  • 역할을 agents로 분리한다 (문맥을 나누고 병렬화함)
  • 결정론적인 강제를 hook으로 만든다 (편차를 제거함)

이 순서라면 각 단계에서 무엇이 변했는지 스스로 확인하며 진행할 수 있으므로 길을 잃지 않습니다. 갑자기 4번부터 시작하는 것보다 1번부터 쌓아 올리는 것이 최종 구성에 대해서도 스스로 설명할 수 있는 결과물이 됩니다.

AI를 어디까지 신뢰할 것인가: 리뷰 범위를 메커니즘에 심기

AI에게 어디까지 맡겨도 될지는 논의로 결정하기보다, 실제로 시도해 보며 선을 긋는 것이 타당하다고 생각합니다. 직접 해본 뒤에 어디까지는 맡겨도 문제가 없는지, 반대로 어느 부분은 가중치를 두어 사람이 확실히 리뷰할지를 정의합니다.

중요한 것은, 사람이 리뷰하는 범위를 단순히 "주의하자"라는 마음가짐에 두지 않고, 기존의 skill이나 agent 내부에 승인 게이트(Approval Gate)로서 심어두는 것입니다. 시스템으로서 승인 요청이 날아오는 상태를 만들어 둡니다.

명상 앱 개발은 PRD 작성 → 설계 → 테스트 주도 개발 (TDD) → 리뷰라는 흐름으로 진행하고 있습니다. 이 과정에서 저만의 고집을 다음과 같이 반영했습니다.

먼저, 무엇을 문서로 남길지를 결정했습니다. 횡단적으로 항상 참조하는 공통 설계와, 설계의 방침·이유·의도를 남기기 위한 개별 설계서를 분리하여, 나중에 "왜 이렇게 했는가"를 추적할 수 있도록 했습니다.

다음으로, 어디를 사람의 리뷰 대상으로 할지를 결정하고, 그곳에서 승인 요청이 날아오도록 했습니다. 구체적으로는 설계가 확정된 타이밍에 한 번 리뷰를 거치는 것, E2E 테스트 케이스가 PRD와 일치하는지 리뷰하는 것, 마지막으로 E2E를 직접 손으로 확인하는 것, 이 세 가지 포인트입니다.

반면, 코드 품질과 보안에 대한 기계적인 검사는 전용 리뷰 에이전트(Review Agent) 2종에 맡기고 있습니다. 여기서 중요한 것은, 구현한 에이전트 스스로가 "완료"를 자기 판단하게 하지 않는 것입니다. skill에는 다음과 같이 작성되어 있습니다.

구현 및 테스트가 완료되면, 구현한 에이전트 자신의 자기 판단으로 완료 처리하지 말고, 별도의 리뷰 전문 에이전트에게 검사를 의뢰한다. 의존성이 없으므로 2개의 에이전트를 병렬로 기동한다.
1. code-reviewer 에이전트 → 품질·Clean Architecture/Riverpod 규약·테스트 커버리지 검사
...

즉, AI의 1차 검사를 거친 후 사람이 최종 확인하는 2단계 구조로 만들었습니다. 설계나 PRD와의 정합성 같은 "의도의 올바름"은 사람이 보고, 코드와 보안의 기계적인 검사는 에이전트로 상향 평준화하는 식의 역할 분담입니다.

워크플로우를 재정리하기: 트리아지 (Triage)로 임기응변 능력 확보하기

운영을 하다 보면 당초의 워크플로우에 별로 좋지 않은 규칙이 발견되기도 하고, 아주 작은 수정에 대해서까지 매번 풀 플랜(Full Plan)을 짜려고 하느라 무거워지기도 했습니다. "빠르게 고치고 싶다"와 "품질을 지키고 싶다"가 양립하지 못하는 것이 과제였습니다.

그래서 개발의 입구에 트리아지 (Triage)를 마련하여 두 가지 트랙으로 나누었습니다. Full은 설계부터 리뷰까지 풀 코스로 돌리는 트랙, Light는 최소한의 기준만 지키며 빠르게 돌리는 트랙입니다. skill에는 이 판정표를 두었습니다.

| 항목 | Full | Light |
| :--- | :--- | : |
| 대상 | PRD가 명확한 신기능·규모가 큰 변경 | 소규모·국소적이며 저위험으로 판정된 변경 |
| 설계 | architect로 본격 설계, 설계서 작성/갱신 | 기존 설계서 반영 필요 여부만 판정 |
...

여기서 중요한 것은 AI가 멋대로 지름길을 택하게 하지 않는 것입니다. 트랙 판정은 "AI가 근거를 바탕으로 제안하고, 사람이 승인하는" 형태를 취하며, 추가로 다음의 고위험 조건 중 하나라도 해당하면 기계적으로 Full로 고정했습니다. AI의 재량은 저위험 영역에만 부여합니다.

#### 고위험 조건 (하나라도 해당 시 → 기계적으로 Full. AI에게 재량 없음)
- 보안과 관련된 사항 (RLS·인증·권한·입력 검증·프라이버시)
- 스키마 / 데이터 마이그레이션 / Edge Function의 변경
...

그리고 어떤 트랙에서도 양보할 수 없는 최소한의 기준을 정의했습니다.

#### 어떤 트랙에서도 양보하지 않는 최소 기준
- 보안과 관련된 사항은 무조건 Full
- 동작을 변경한다면 회귀 테스트(Regression Test)를 반드시 1개 작성 (Red→Green)
...

"워크플로우에는 포함시키되, 중요한 관점만은 무조건 지킨다"는 형식을 취함으로써 재현성과 임기응변 능력을 양립시켰습니다.

참고로, 이 트리아지 판정 로직 본체는 skill에 작성되어 있지만, skill은 호출되지 않으면 발화하지 않습니다. 그래서 "작은 변경이라도 멋대로 고치기 시작하지 않고, 먼저 트랙을 판정·제안한다"라는 발화 조건만은 상시 읽히는 CLAUDE.md에도 한 줄 적어두었습니다. skill이 호출되지 않은 상태에서도 효과를 발휘하기 위한 장치입니다.

요약

마지막으로, 구분 사용의 판단 축을 정리합니다.

  • 할당(Assignment)은 "언제 발화하고, 어떤 문맥에서 움직이는가"로 생각합니다. 기능을 어디에 적을지의 문제가 아닙니다.

  • agents는 역할입니다. 독립된 문맥이 필요하거나, 병렬로 처리할 수 있는 작업을 분리합니다.

  • skills는 워크플로우입니다. 빈도가 높고 흔들리기 쉬운 절차를 재현성 높게 고정합니다.

  • hooks는 결정론적인 강제입니다. 반드시 동일한 처리를 재현하고 싶은 것에 사용하며, 배분을 늘릴수록 품질이 안정됩니다.

  • 샘플은 구조를 빌려오되, 내용은 자신의 프로젝트에 맞춰 다시 만듭니다. 밀접하게 얽힌 하네스 (Harness)를 그대로 이식하지 않습니다.

  • 단계적으로 키워나갑니다.
    CLAUDE.md

→ skill → agent → hook 순서라면, 각 단계에서 효과를 확인하며 망설임 없이 진행할 수 있습니다. - 신뢰는 테스트를 통해 선을 긋습니다. 사람이 리뷰할 범위를 정의하고, 승인 게이트 (Approval gate)로서 skill 이나 agent 에 내장합니다. 감정이 아닌 시스템으로 만듭니다.

  • 트리아지 (Triage)를 통해 임기응변성을 보장합니다. 모든 것에 무거운 계획을 적용하지는 않되, 고위험 영역은 AI에게 재량을 주지 않고 기계적으로 Full 고정합니다.

하네스 (Harness) 설계는 한 번에 완성되는 것이 아닙니다. 가려운 곳부터 조금씩, 스스로 설명할 수 있는 범위 내에서 키워나가는 것이 결국 가장 빠르다고 느낍니다.

Discussion

AI 자동 생성 콘텐츠

본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0