서브 에이전트, 훅(Hooks), 스킬(Skills): 오케스트레이션 레이어
요약
본 글은 Claude Code 기반 에이전트 시스템에서 복잡한 자동화 패턴을 구현하는 오케스트레이션 레이어인 서브 에이전트, 훅(Hooks), 스킬에 대해 설명합니다. 서브 에이전트는 작업 분해 및 상태 격리화가 필요할 때 사용하며, 인라인 도구는 낮은 지연 시간과 공유 상태가 중요할 때 적합합니다. 훅은 사전/사후 가드레일 역할을 하여 시스템의 안전성과 예측 가능성을 높입니다.
핵심 포인트
- 서브 에이전트는 독립적이고 격리된 하위 작업에 유용하며, 병렬 실행 및 전문 지식 로딩에 강점.
- 인라인 도구는 낮은 지연 시간과 공유 상태가 필수적인 단순하고 선형적인 작업에 최적화되어 있습니다.
- 사전 훅은 입력 유효성 검사, 권한 확인 등 시스템의 안전장치(Guardrail) 역할을 수행합니다.
- 사후 훅은 결과 유효성 검사, 데이터 변환, 로깅 등을 통해 워크플로우의 품질을 보증합니다.
서브 에이전트, 훅, 그리고 스킬은 Claude Code의 비밀스러운 오케스트레이션 레이어입니다. 통제 불가능한 토큰 비용 없이 다단계 자동화 패턴을 구현할 수 있습니다.
서브 에이전트(Sub-Agents): 컨텍스트 분기 vs 인라인 도구 사용 시점 이해하기
효율적인 에이전트 설계를 위해서는 언제 서브 에이전트를 생성하고 언제 직접 도구를 사용하는지 아는 것이 기본입니다:
서브 에이전트를 사용해야 할 때:
- 작업 분해가 격리화의 이점을 얻을 때: 독립적인 하위 문제로 깔끔하게 나눌 수 있는 복잡한 문제
- 다른 도구 세트가 필요할 때: 하위 작업이 메인 에이전트는 접근해서는 안 되는(또는 그 반대) 도구에 접근해야 할 때
- 상태 격리화가 가치 있을 때: 하위 작업의 오염이 메인 컨텍스트에 영향을 미치는 것을 원하지 않을 때 (예: 실험적 접근 방식)
- 병렬 실행이 가능할 때: 성능 향상을 위해 하위 작업을 동시에 실행할 수 있을 때
- 특화된 전문 지식이 필요할 때: 서브 에이전트에 도메인별 스킬이나 지식을 미리 로드할 수 있을 때
- 재시도 의미론(Retry semantics)이 다를 때: 하위 작업이 부모와 다른 오류 처리 또는 재시도 정책을 필요로 할 때
인라인 도구 사용(Inline Tool Use)을 사용해야 할 때:
- 메인 컨텍스트와의 긴밀한 결합: 하위 작업이 현재 상태나 변수에 자주 접근해야 할 때
- 낮은 지연 시간(Low latency)이 중요할 때: 분기 오버헤드가 사용자 경험에 영향을 미칠 수 있을 때
- 단순하고 선형적인 작업: 가지치기 복잡성이 없는 간단한 순서들
- 자원 보존: 추가 에이전트 인스턴스의 오버헤드를 피할 때
- 공유 상태가 필수적일 때: 여러 단계가 동일한 변수를 읽거나 쓸 필요가 있을 때
- 최소한의 컨텍스트 이탈(Minimal contextual divergence): 하위 작업이 현저하게 다른 시스템 프롬프트나 도구를 필요로 하지 않을 때
// 예시: 서브 에이전트를 사용할 때
// GOOD: 독립적인 연구 과제
const researchSubagent = await agent(
...
훅(Hooks): 사전/사후 도구 가드, 포맷팅, 정책 강제 적용
훅은 에이전트 시스템을 안전하고 예측 가능하게 만드는 눈에 보이지 않는 가드레일입니다:
훅의 유형 및 사용 시점:
사전 도구 훅(Pre-Tool Hooks) (가드 레일)
- 입력 유효성 검사 (Input validation): 실행 전 매개변수 확인
- 권한 확인 (Permission checking): 사용자/역할이 권한을 가지고 있는지 검증
- 속도 제한 (Rate limiting): 오용 또는 과도한 사용 방지
- 컨텍스트 풍부화 (Context enrichment): 처리 전에 관련 정보 추가
- 정책 적용 (Policy enforcement): 기업 지침을 위반하는 행동 차단
- 변환 (Transformation): 입력을 예상 형식으로 정규화
도구 후크 (Post-Tool Hooks) (품질 보증)
- 결과 유효성 검사 (Result validation): 출력이 기대치를 충족하는지 확인
- 오류 처리 (Error handling): 실패를 실행 가능한 피드백으로 변환
- 데이터 변환 (Data transformation): 출력을 필요한 형식으로 변환
- 로깅/감사 (Logging/auditing): 규정 준수를 위해 발생한 일을 기록
- 상태 업데이트 (State updates): 결과에 따라 에이전트의 내부 상태 수정
- 트리거 체이닝 (Trigger chaining): 워크플로우의 다음 단계를 자동으로 시작
특화된 후크 유형 (Specialized Hook Types):
- 형식 지정 후크 (Formatting hooks): 코드 스타일 자동 적용 (Prettier, ESLint fixes)
- 보안 스캐닝 후크 (Security scanning hooks): 생성된 코드를 취약점 검사
- 성능 분석 후크 (Performance analysis hooks): 비효율적인 알고리즘이나 패턴 플래그 지정
- 규정 준수 확인 후크 (Compliance checking hooks): 출력이 규제 요구 사항을 충족하는지 확인 (SOX, GDPR 등)
- 테스트 후크 (Testing hooks): 생성된 코드에 대한 테스트 자동 생성 또는 실행
// 예시: SAP ABAP 개발을 위한 포괄적인 후크
const abapHooks = {
// 프로덕션과 유사한 환경에서 위험한 작업 방지
...
스킬 (Skills): SAP, Cloudflare, NAS를 위한 재사용 가능한 도메인 팩
스킬은 전문 지식, 도구 및 패턴을 공유 가능한 단위로 패키징합니다:
좋은 스킬의 조건:
- 도메인 중심적 (Domain-focused): 명확한 경계 설정 (SAP ABAP, Cloudflare Workers, TrueNAS 관리 등)
- 도구 큐레이션 (Tool-curated): 해당 도메인에 필요한 정확한 도구만 포함 — 더 적거나 부족하지 않음
- 사전 구성됨 (Pre-configured): 합리적인 기본값(defaults), 템플릿, 예시가 제공됨
- 문서화됨 (Documented): 명확한 사용 지침과 일반적인 패턴이 있음
- 버전 관리됨 (Versioned): 개선 사항 및 호환성 깨짐 변경점(breaking changes)을 추적함
- 조합 가능함 (Composable): 다른 스킬들과 잘 작동함 (UNIX 철학을 에이전트에 적용)
예시: SAP ABAP 스킬 구성 요소
핵심 도구 (Core Tools)
- read_abap_source
- write_abap_source
- activate_transport
- run_abap_unit_test
- check_syntax
- execute_function_module
- read_table_sap
초기화된 상태 (Initialized State)
- 일반적인 명명 규칙 (Z
/Y) - 트랜스포트 레이어 구성
- 표준 권한 객체(authorization objects)
- 선호되는 ABAP 버전 플래그
- 일반적인 시스템 매개변수 (클라이언트, 언어)
프롬프트 템플릿 (Prompt Templates)
- "주니어 개발자를 위해 이 ABAP 코드를 설명해 주세요"
- "이 클래스/메서드에 대한 단위 테스트를 생성해 주세요"
- "이 SELECT 문에 대한 성능 개선 사항을 제안해 주세요"
- "이 절차적 코드(procedural code)를 객체 지향(object-oriented)으로 변환해 주세요"
- "이 리포트에서 잠재적인 보안 문제를 찾아주세요"
워크플로우 패턴 (Workflow Patterns)
- 테스트 주도 개발 주기 (Test-driven development cycle)
- 빠른 수정 구현 프로세스 (Quick fix implementation process)
- 트랜스포트 요청 생성 및 관리
- 성능 분석 및 최적화 루틴
- 보안 검토 체크리스트
스킬을 찾고 공유하는 곳:
- 공식 레지스트리: Claude Skills Marketway, Cursor Community
- 내부 저장소: 회사 전체의 스킬 라이브러리
- 오픈 소스: 도메인 전문 지식을 공유하는 GitHub 조직
- 벤더 제공: SAP, Cloudflare 등에서 제공하는 공식 스킬
- 피어 공유: 전문가 네트워크 간의 비공식 교환
전문가 팁: 가장 자주 사용하는 도메인 스킬들을 결합한 '메타 스킬(meta-skill)'을 만들어 보세요. 예를 들면:
- SASTechnician = SAP ABAP Skill + 보안 테스트 스킬 (Security Testing Skill) + 성능 최적화 스킬 (Performance Optimization Skill)
- CloudDevOps = Cloudflare Workers 스킬 + 코드형 인프라 (Infrastructure as Code) 스킬 + 모니터링 및 경고 (Monitoring & Alerting) 스킬
- FullStackDeveloper = 프론트엔드 스킬 (Frontend Skill) + 백엔드 스킬 (Backend Skill) + 데이터베이스 스킬 (Database Skill) + 데브옵스 스킬 (DevOps Skill)
n8n/Ollama 홈랩(Homelab)에서의 오케스트레이션 비교
Claude Code의 접근 방식이 익숙한 오케스트레이션 도구와 어떻게 비교되는지:
Claude Code 네이티브 오케스트레이션 (Native Orchestration)
- 세분성 (Granularity): 툴 호출(tool-call) 수준에서 세밀한 제어 가능
- 컨텍스트 공유 (Context sharing): 단계 간 풍부하고 구조화된 상태 유지
- 실패 처리 (Failure handling): 정교한 재시도/회로 차단기 패턴 (retry/circuit breaker patterns)
- 디버깅 (Debugging): 에이전트 추론 과정을 단계별 검사 가능
- 언어 (Language): 자연어 + 코드
- 지연 시간 (Latency): 높음 (LLM 추론 시간)
- 최적의 사용처 (Best for): 판단과 적응이 필요한 인지 작업(Cognitive tasks)
n8n/Ollama 홈랩 접근 방식 (Homelab Approach)
- 세분성 (Granularity): 거친 수준 (노드 대 노드, node-to-node)
- 컨텍스트 공유 (Context sharing): 제한적 (일반적으로 JSON 페이로드)
- 실패 처리 (Failure handling): 기본적인 재시도 메커니즘
- 디버깅 (Debugging): 시각적인 실행 추적(Visual execution tracing)
- 언어 (Language): 시각적 워크플로우 + 코드 노드
- 지연 시간 (Latency): 낮음 (결정론적 실행, deterministic execution)
- 최적의 사용처 (Best for): 신뢰할 수 있고 반복적인 자동화 워크플로우
하이브리드 최적 지점 (The Hybrid Sweet Spot):
가장 정교한 구현체들은 두 가지 접근 방식을 결합합니다:
- 판단이 필요한 '스마트' 부분(계획, 해석, 예외 처리)에는 Claude Code를 사용합니다.
- '신뢰성'이 필요한 부분(데이터 이동, 알림, 예약 작업)에는 n8n/Ollama 워크플로우를 사용합니다.
- 웹훅(webhooks), 메시지 큐(message queues) 또는 공유 데이터베이스를 통해 연결합니다.
- 각 시스템이 가장 잘하는 일을 하도록 합니다.
토큰 예산 및 에이전트 체인에 대한 '막혔을 때 규칙' (If Stuck Rule)
이러한 실용적인 제약 조건으로 무분별하게 비용이 발생하는 것을 방지합니다:
턴당 토큰 예산 (Per-Turn Token Budgets):
- 에이전트 상호작용당 최대 토큰 수 설정 (프롬프트와 완료(completion) 모두 포함)
- 일반적인 값: 단순 작업의 경우 2K-4K, 복잡한 추론의 경우 8K-16K
- 위반 사항을 조기에 감지하기 위해 MCP/클라이언트 레벨에서 구현
- 한계에 접근했을 때 우아한 저하(graceful degradation) 제공 (요약하거나 명확히 하는 질문 요청)
- 용량 계획을 위해 근접 제한 이벤트를 기록
대화 수준의 한계(Conversation-Level Limits):
- 강제 재설정 전 대화당 최대 턴 수(turns)
- 연속 실패 제한 (예: 3회 연속 도구(tool) 실패 후 중지)
- 시간 기반 만료 (N시간 후 대화 자동 종료)
- 비용 기반 상한선 (예상 비용이 임계값을 초과하면 중지)
- 합법적인 장기 실행 작업을 위한 사용자 시작 지속 옵션
"막힘 규칙(The 'If Stuck Rule')" - 프로덕션 환경에 필수적:
에스컬레이션(escalate) 또는 중단 시점을 결정하는 실용적인 휴리스틱(heuristic):
- 사용 사례에 있어 "막힘(stuck)"이 무엇을 의미하는지 정의 (진행 없음, 루핑, 오류 등)
- 임계값 설정 (예: 의미 있는 진전 없이 3회 시도)
- 트리거 발생 시:
- 인간 감독자에게 에스컬레이션(escalate)
- 더 단순하고 결정론적인 접근 방식으로 폴백(fallback)
- 명확한 제한 사항과 함께 부분 결과 반환
- 중단하고 진단 정보가 포함된 오류 반환
// "막힘 규칙"의 예시 구현
class AgentWithStuckDetection {
constructor(maxAttempts = 3) {
...
보안: 서브 에이전트가 절대 접근해서는 안 되는 것
어떤 에이전트도 넘어서는 안 될 하드 경계(hard boundaries)를 정의합니다:
절대적 경계 (절대 넘지 말 것):
- 운영 환경 자격 증명 (Production credentials): 평문(plaintext) 운영 비밀번호, 키 또는 인증서를 저장하거나 전송하지 마십시오.
- 제한 없는 시스템 접근 (Unrestricted system access): 명시적인 정당화 없이는 어떠한 에이전트도 sudo/root에 상응하는 권한을 가져서는 안 됩니다.
- 고객 PII: 개인 식별 정보(Personally identifiable information)는 특별한 처리와 동의가 필요합니다.
- 영업 비밀 (Trade secrets): 추가적인 보호가 필요한 명확하게 정의된 지적 재산(IP)입니다.
- 승인되지 않은 네트워크 (Unauthorized networks): 승인되지 않은 네트워크 세그먼트로 이동하거나 스캔을 시도하는 행위
- 정책 위반 (Policy violations): 허용 가능한 사용 정책에 의해 명시적으로 금지된 행동들
조건부 경계 (Conditional Boundaries) (맥락 의존적):
- 개발 환경 대 운영 환경 (Development vs production): 접근 권한은 환경 간에 현저하게 달라야 합니다.
- 데이터 분류 수준 (Data classification levels): 공개(Public), 내부(internal), 기밀(confidential), 제한됨(restricted) 등 각각 다른 처리가 필요합니다.
- 시간 기반 접근 (Time-based access): 특정 작업은 유지보수 기간 동안에만 허용됩니다.
- 지리적 제한 (Geographic restrictions): 데이터 주권 요구사항이 처리가 발생하는 위치를 제한할 수 있습니다.
- 2인 승인 (Dual-person approval): 고위험 작업의 경우 두 명의 권한 있는 개인이 필요합니다.
방어 심층화 구현 (Implementing Defense in Depth):
- 네트워크 분할 (Network segmentation): 에이전트는 격리된 VLAN 또는 보안 그룹 내에서 작동해야 합니다.
- 최소 권한 원칙 (Principle of least privilege): 권한이 없는 상태에서 시작하여 필요한 것만 부여합니다.
- 정기적인 권한 검토 (Regular permission reviews): 에이전트 접근 권한에 대한 분기별 감사를 실시합니다.
- 자동화된 이상 징후 탐지 (Automated anomaly detection): 정상적인 에이전트 행동에 대한 ML 기반 프로파일링을 수행합니다.
- 불변 감사 로그 (Immutable audit logs): 모든 에이전트 활동에 대해 암호학적으로 서명되고 추가만 가능한 기록을 유지합니다.
- 비상 절차 (Break-glass procedures): 명확하게 문서화된 비상 접근 방법을 마련해야 합니다.
- 정기적인 침투 테스트 (Regular penetration testing): 에이전트 시스템을 레드/블루 팀 훈련에 포함시켜야 합니다.
기억하십시오: 세상에서 가장 정교한 에이전트라도 보안 사고를 일으킨다면 가치가 없습니다. 보안은 기능(feature)이 아니라 모든 것이 구축되는 기반입니다.
템플릿: ayraix 콘텐츠 파이프라인을 위한 단일 Hooks 파일
실제 콘텐츠 파이프라인에 거버넌스(governance)를 구현하는 구체적인 예시입니다:
// .ayraix-content-hooks.js
// ayraix.com의 AI 지원 콘텐츠 생성을 관리합니다 (Governs AI-assisted content creation for ayraix.com)
const crypto = require('crypto');
/**
* 감사 추적(audit tracking)을 위한 결정론적 콘텐츠 ID를 생성합니다.
*/
function generateContentId(title, author) {
const hash = crypto.createHash('sha256');
hash.update(`${title}|${author}|${new Date().toISOString().slice(0,10)}`);
return hash.digest('hex').substring(0, 12);
}
/**
* Pre-hook: 콘텐츠 생성 요청을 검증합니다.
*/
async function preContentCreationHook(request) {
const { type, title, author, metadata = {} } = request;
// 1. 인증 확인 (Authentication check)
if (!await validateUserPermissions(author, 'content:create')) {
throw new Error(`사용자 ${author}는 콘텐츠 생성 권한이 없습니다`);
}
// 2. 입력값 검증 (Input validation)
if (!title || title.trim().length < 3) {
throw new Error('제목은 최소 3글자여야 합니다');
}
if (title.length > 100) {
throw new Error('제목이 최대 길이인 100자를 초과했습니다');
}
// 3. 중복 방지 (Duplicate prevention, basic)
if (await titleExistsRecently(title, author)) {
throw new Error('해당 저자가 최근 사용한 유사 제목입니다 - 변형을 고려하십시오');
}
// 4. 콘텐츠 유형 검증 (Content type validation)
const validTypes = ['article', 'tutorial', 'case_study', 'news', 'reference'];
if (!validTypes.includes(type)) {
throw new Error(`유효하지 않은 콘텐츠 유형: ${type}. 다음 중 하나여야 합니다: ${validTypes.join(', ')}`);
}
// 5. 추적 메타데이터 추가 (Add tracking metadata)
return {
...request,
contentId: generateContentId(title, author),
timestamp: new Date().toISOString(),
version: 1
};
}
/**
* Post-hook: 생성된 콘텐츠를 검증하고 처리합니다.
*/
async function postContentGenerationHook(result) {
const { content, metadata, contentId } = result;
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기