사전 준비 확인
2분Chapter 1 실습 프로젝트가 커밋 2개 이상(초기 + 버그 수정) 상태인지 확인합니다. Task 1의 첫 리뷰 대상이 이 수정 커밋의 diff입니다.
~/claude-lab/ch1에서 그대로 이어집니다.
아래에 나오는 .claude/agents/ 같은 상대 경로도 전부 이 폴더 기준입니다.
시작 전에 cd ~/claude-lab/ch1로 위치를 맞추세요.
cd ~/claude-lab/ch1
npm test # 3개 모두 PASS 여야 합니다
git log --oneline # 커밋 2개 이상이어야 합니다
mkdir -p ~/claude-lab/ch1/src && cd ~/claude-lab/ch1
cat > package.json << 'EOF'
{
"name": "user-service-lab",
"version": "1.0.0",
"description": "Claude Code Workshop sample project",
"type": "module",
"scripts": { "test": "node test.js" }
}
EOF
cat > src/users.js << 'EOF'
// 사용자 데이터 저장소
// 주의: 일부 사용자는 profile 필드가 없음 (마이그레이션 미수행 상황)
export const users = [
{ id: 1, name: "Kim", profile: { email: "kim@example.com", plan: "pro" } },
{ id: 2, name: "Lee", profile: { email: "lee@example.com", plan: "free" } },
{ id: 3, name: "Park" }
];
EOF
cat > src/userService.js << 'EOF'
import { users } from "./users.js";
export function getUser(id) {
return users.find((u) => u.id === id);
}
export function getUserPlan(id) {
const user = getUser(id);
return user.profile.plan;
}
EOF
cat > test.js << 'EOF'
import { getUserPlan } from "./src/userService.js";
function check(name, fn, expected) {
const actual = fn();
console.log(`${name}: ${actual === expected ? "PASS" : `FAIL (got ${actual})`}`);
}
check("Test 1 - pro 플랜 사용자", () => getUserPlan(1), "pro");
check("Test 2 - free 플랜 사용자", () => getUserPlan(2), "free");
check("Test 3 - profile 없는 사용자", () => getUserPlan(3), "unknown");
EOF
git init -q
git config user.name >/dev/null 2>&1 || git config user.name "lab"
git config user.email >/dev/null 2>&1 || git config user.email "lab@example.com"
git add -A && git commit -q -m "chore: initial lab project (with bug)"
cat > src/userService.js << 'EOF'
import { users } from "./users.js";
export function getUser(id) {
return users.find((u) => u.id === id);
}
export function getUserPlan(id) {
const user = getUser(id);
return user?.profile?.plan ?? "unknown";
}
EOF
git add -A && git commit -q -m "fix: handle users without profile"
npm test && git log --oneline
Task 5의 헤드리스 통합에서 JSON 출력 파싱에 jq를 사용합니다.
없으면 한 줄로 설치하세요.
jq --version || sudo dnf install -y jq
jq-1.7.1
첫 Subagent, code-reviewer 만들기
8분
.claude/agents/에 code-reviewer를 정의하고 등록을 확인한 뒤,
Chapter 1의 버그 수정 커밋을 첫 리뷰 대상으로 호출합니다.
정의 파일은 YAML frontmatter 핵심 4필드(name / description / tools / model, 필수는 name과 description)와 시스템 프롬프트 본문으로 구성됩니다. 프로젝트 루트에서 아래 블록을 실행하세요.
cd ~/claude-lab/ch1
mkdir -p .claude/agents
cat > .claude/agents/code-reviewer.md << 'EOF'
---
name: code-reviewer
description: |
PR diff를 검토하여 가독성, 안전성, 성능, 테스트 커버리지 관점에서
개선 사항을 제안하는 시니어 코드 리뷰어. 사용 시점: 코드 리뷰가
필요하다고 사용자가 요청하거나 git diff 검토가 필요한 경우.
tools: Read, Grep, Glob, Bash(git diff:*), Bash(git log:*)
model: sonnet
---
당신은 10년 경력의 시니어 소프트웨어 엔지니어입니다.
# 검토 우선순위
1. 안전성: null 참조, race condition, 입력 검증 누락
2. 가독성: 명명, 함수 크기, 주석 필요성
3. 성능: 알고리즘 복잡도, 불필요한 I/O
4. 테스트: 새 코드의 테스트 커버리지
# 출력 형식
- Severity: high | medium | low
- 파일:라인, 문제 설명, 권장 수정안
EOF
| 필드 | 역할 | 이 예시의 선택 |
|---|---|---|
name | 고유 식별자, kebab-case 영문 소문자 | code-reviewer |
description | 자동 디스패치의 판단 기준, 사용 시점까지 명시 | 리뷰 요청 / git diff 검토 시 |
tools | 도구 화이트리스트, Bash는 명령 패턴으로 제한 | 읽기 전용 + git diff / log만 |
model | 별칭 sonnet / opus / haiku, 전체 모델 ID, 또는 inherit. 생략 시 inherit(메인 모델 상속) | sonnet, 일상 리뷰의 표준 |
claude
/agents는 이제 안내 문구만 출력합니다.
에이전트 관리 자체가 파일 기반으로 바뀐 것은 아니며(파일 위치와 frontmatter는 동일),
확인은 @ 멘션 typeahead 또는 Claude에게 질문으로, 생성/수정은 파일 편집 또는 Claude에게 요청으로 합니다.
입력창에 @를 입력하면 파일 멘션과 함께 code-reviewer (agent)가
typeahead 목록에 나타납니다(Esc로 닫기). 또는 아래처럼 직접 물어봐도 됩니다.
현재 이 세션에서 사용할 수 있는 서브에이전트 목록을 알려주세요
사용 가능한 서브에이전트:
- code-reviewer : PR diff 검토 (프로젝트, .claude/agents/)
- Explore, Plan, general-purpose : 내장 에이전트
code-reviewer 에이전트를 사용해서 최근 커밋의 변경분(git diff HEAD~1)을 검토해 주세요
[메인] code-reviewer 에이전트를 호출합니다.
→ Agent(code-reviewer, "Review git diff HEAD~1")
[reviewer] Bash git diff HEAD~1
[reviewer] Read src/userService.js
[메인] 결과 요약:
- low src/userService.js:9, 옵셔널 체이닝 적용 적절
- medium test.js, 존재하지 않는 id 케이스 테스트 부재 ...
결과를 받으면 출력 형식이 시스템 프롬프트에서 지정한 Severity 구조를 따르는지, 우선순위 4개 관점이 반영되었는지 확인하세요.
도구 권한 격리 체험
6분읽기 전용 에이전트에 일부러 권한 밖 요청을 보내 거부 동작을 관찰하고, tools 필드에 권한을 명시적으로 추가한 뒤 새 위임으로 차이를 체험합니다. 최소 권한 원칙과 정의 갱신 타이밍의 실습입니다.
tools 필드는 그 에이전트가 쓸 수 있는 손발의 목록입니다.
Read(파일 읽기), Grep/Glob(검색),
Edit/Write(수정과 생성), Bash(명령 실행)처럼
하나하나가 구체적 능력이고, 목록에 없는 도구는 시도 자체가 차단됩니다.
이 Task는 그 울타리를 일부러 밟아 보며 최소 권한이 실제로 동작하는지 확인하는 실험입니다.
cat > .claude/agents/dangerous-test.md << 'EOF'
---
name: dangerous-test
description: 의도적 권한 테스트용 에이전트. 사용 시점: 사용자가 이름으로 직접 지정할 때만.
tools: Read, Grep
model: haiku
---
당신은 테스트 에이전트입니다.
파일을 분석하고 결과를 보고하세요.
EOF
tools에 Edit이 없는 상태에서 파일 수정을 요청합니다. Claude Code가 .claude/agents/를 감시하므로 파일 저장 후 몇 초 안에 자동 인식됩니다(Task 1에서 디렉토리를 만든 뒤 세션을 시작했기 때문에 재시작 불필요).
dangerous-test 에이전트를 사용해서 src/users.js의 Park 사용자에게 profile 필드를 추가해 주세요
[dangerous-test] Read src/users.js
[dangerous-test] 파일 수정이 필요하지만 Edit 도구 권한이 없습니다.
분석 결과만 보고합니다: Park(id 3)에 profile 필드가 없습니다.
→ 수정은 Edit 권한이 있는 에이전트 또는 메인에서 수행해야 합니다.
disallowedTools: Write, Edit처럼 거부 목록을 쓸 수 있습니다.
sed -i.bak 's/^tools: Read, Grep$/tools: Read, Grep, Edit/' .claude/agents/dangerous-test.md
grep '^tools:' .claude/agents/dangerous-test.md # tools: Read, Grep, Edit 확인
/exit로 세션을 완전히 나갔다가 claude로 다시 들어오세요. 갱신된 정의로 새 인스턴스가 뜹니다(같은 세션에서 /clear로 맥락만 비워도 동일 효과).
/exit
claude
dangerous-test 에이전트를 사용해서 src/users.js의 Park 사용자에게 profile 필드를 추가해 주세요
[dangerous-test] Read src/users.js
[dangerous-test] Edit src/users.js # 이번에는 Edit 도구 사용 (승인 요청 표시)
Park(id 3)에 profile 필드를 추가했습니다.
이것이 의도적 권한 부여와 무분별한 전체 권한의 차이입니다.
동시에, 서브에이전트의 도구 권한이 인스턴스 스폰 시점에 고정된다는 점과
메인의 대화 맥락이 재위임을 가로막을 수 있다는 점, 그리고 /exit 재진입(또는 /clear)이
이런 상황의 실전 해결책이라는 점까지 함께 체득한 것입니다.
git checkout -- src/users.js
rm -f .claude/agents/dangerous-test.md .claude/agents/dangerous-test.md.bak
에이전트 3종 완성, test-writer와 docs-writer 추가
7분Task 4의 디스패치 실습을 위해 test-writer(테스트 작성)와 docs-writer(문서 작성)를 추가합니다. 두 에이전트의 description이 서로 영역이 겹치지 않게 작성된 점에 주목하세요.
cat > .claude/agents/test-writer.md << 'EOF'
---
name: test-writer
description: |
기존 코드의 테스트 커버리지를 분석하고 누락된 엣지 케이스, 분기,
예외 경로에 대한 테스트를 작성. 사용 시점: 커버리지 부족이 확인되거나
새 함수에 테스트가 필요한 경우.
tools: Read, Grep, Glob, Edit, Write, Bash(npm test:*)
model: sonnet
---
당신은 테스트 자동화 전문가입니다.
# 작업 절차
1. 대상 함수의 시그니처와 분기 구조 분석
2. 기존 테스트 파일이 있다면 스타일 일치
3. 정상 케이스, 엣지 케이스, 예외 케이스 모두 커버
4. 테스트 작성 후 실제로 실행하여 통과 확인
# 작성 원칙
- 테스트 하나가 한 가지만 검증
- 의미 있는 테스트 이름
- AAA 패턴 (Arrange Act Assert)
EOF
cat > .claude/agents/docs-writer.md << 'EOF'
---
name: docs-writer
description: |
README, API 문서, 아키텍처 결정 문서(ADR)를 코드와 일치하도록 작성하거나
업데이트. 사용 시점: 신규 기능 추가 후 문서 작성이 필요하거나 기존 문서가
코드와 불일치할 때.
tools: Read, Grep, Glob, Edit, Write, Bash(git log:*)
model: sonnet
---
당신은 기술 문서 작성가입니다.
# 문서 종류별 가이드
- README: 프로젝트 개요, 설치, 사용법, 예시
- API 문서: 함수 시그니처, 파라미터, 반환값, 예시
- ADR: Context, Decision, Consequences 형식
# 작성 원칙
- 코드와 실제 동작이 일치해야 함
- 예시는 실제로 실행 가능한 것
- 한국어와 영어 혼용 가능, 일관성 유지
EOF
ls .claude/agents/
세션 입력창에 @를 입력해 typeahead에 3종 모두 (agent)로 표시되는지 확인하세요.
직접 @agent-test-writer처럼 입력해도 멘션이 인식됩니다. 또는 아래처럼 물어봐도 됩니다.
사용 가능한 서브에이전트를 모두 알려주세요
프로젝트 서브에이전트 (.claude/agents/):
- code-reviewer : PR diff 검토
- test-writer : 테스트 커버리지 확장
- docs-writer : 문서 작성과 동기화
.claude/agents/는 프로젝트 단위(팀 공유, Git 커밋 대상),
~/.claude/agents/는 개인 전역(모든 프로젝트에서 사용)입니다.
지금 만든 3종을 커밋해 두면 팀 전체가 동일한 에이전트를 사용합니다.
Task 디스패치 3패턴
10분
같은 에이전트들을 자동 디스패치, 명시적 호출, 병렬 호출 3가지 방식으로 부려 보고,
/cost로 에이전트별 비용을 비교합니다. 각 패턴 사이에 /exit로 나갔다 들어오거나 /clear로 컨텍스트를 정리하면 관찰이 깨끗해집니다.
/tasks에서 확인하고, 권한 요청은 메인 세션에 표시되며, Ctrl + B로 실행 중 작업을 백그라운드로 보낼 수 있습니다.
에이전트를 지정하지 않고 요청합니다. 메인이 description을 대조해 스스로 code-reviewer를 선택하는지 관찰하세요.
이 프로젝트의 최근 변경 사항을 코드 리뷰해 주세요
[메인] 코드 리뷰 요청으로 판단, code-reviewer를 호출합니다.
→ Agent(code-reviewer, "Review recent changes")
# 사용자가 지정하지 않아도 description 매칭으로 선택됨
이름으로 직접 지정하면 메인은 다른 에이전트를 검토하지 않고 예측 가능하게 해당 에이전트를 호출합니다.
test-writer 에이전트를 사용해서 src/userService.js의 테스트 커버리지를 분석하고, 존재하지 않는 사용자 id 같은 누락된 엣지 케이스 테스트를 추가해 주세요
test-writer가 테스트를 추가하고 npm test를 직접 실행해 통과를 확인하는지 지켜보세요(시스템 프롬프트의 작업 절차 4번).
특정 에이전트 실행을 보장하고 싶다면 자연어 대신 @를 입력해 typeahead에서
test-writer (agent)를 선택하는 @-멘션 방식을 쓸 수 있습니다.
독립적인 3개 작업을 한 번에 요청합니다. 메인이 3개의 Task를 동시에 발행하고, 총 시간은 합산이 아니라 가장 오래 걸린 작업 기준(max)이 됩니다.
이 코드베이스를 종합 점검해 주세요. 다음 세 가지를 병렬로 진행해 주세요.
1) 코드 품질 리뷰
2) 테스트 커버리지 분석
3) README 문서 초안 작성
[메인] 3개의 Subagent를 병렬로 호출합니다.
→ Agent(code-reviewer, ...)
→ Agent(test-writer, ...)
→ Agent(docs-writer, ...)
[reviewer] 분석 중... 이슈 2건
[tester ] 분석 중... 엣지 케이스 1건 보강
[docs ] README.md 초안 작성 중...
[메인] 결과 종합: 코드 이슈 2건, 테스트 1건 추가, README 초안 완료.
현재 버전에서 /cost는 /usage의 별칭입니다. 세션 사용량과 어떤 서브에이전트가 한도를 소비했는지 확인할 수 있습니다.
/cost
Current session cost: $0.42
Breakdown:
Main agent (Sonnet): $0.09
code-reviewer (Sonnet): $0.11
test-writer (Sonnet): $0.13
docs-writer (Sonnet): $0.09
model: haiku로 지정해 비용을 조절하고, Opus는 심층 분석에만 사용하세요.
Headless 통합과 CI 맛보기
7분서브에이전트를 대화 없이 스크립트에서 호출하고 JSON으로 후처리합니다. 마지막으로 같은 패턴이 GitHub Actions에서 어떻게 동작하는지 확인합니다. 세션 밖 터미널에서 실행하세요.
git diff HEAD~1 | claude -p \
"code-reviewer 에이전트로 이 diff를 검토해 주세요" \
--output-format json > review-result.json
head -c 400 review-result.json
# jq가 있다면: 요약과 high severity만 추출
jq '.summary' review-result.json
jq '.issues | map(select(.severity == "high"))' review-result.json 2>/dev/null
# jq가 없다면
python3 -m json.tool review-result.json | head -30
같은 명령을 GitHub Actions에 넣으면 PR마다 자동 리뷰가 됩니다. 아래는 강의에서 다룬 직렬(리뷰) + 병렬(테스트와 보안) 복합 패턴의 워크플로입니다. GitHub 저장소가 있다면 push해서 실험해 보세요. 선택 과제입니다.
name: PR Check with Subagents
on: pull_request
jobs:
comprehensive-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }
- run: npm install -g @anthropic-ai/claude-code
# 직렬: code-reviewer 먼저 실행 후 결과 보고
- name: Code Review
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
claude -p "code-reviewer 에이전트로 git diff origin/main..HEAD를 검토해 주세요" \
--output-format text > review.md
# 병렬 요청: 테스트와 보안을 한 번에
- name: Tests + Security
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
claude -p "다음을 모두 점검해 주세요: 1) 테스트 커버리지 부족 2) 보안 이슈" \
--output-format json > result.json
# 결과를 PR 코멘트로 게시
- uses: peter-evans/create-pr-comment@v1
with: { body-path: review.md }
--allowed-tools "Read,Grep,Glob"으로 도구를 제한하세요.
Chapter 5(CLI Reference)에서 권한 플래그와 파이프라인 패턴을 심화합니다.
마무리, 학습 목표 체크리스트
Chapter 2의 학습 목표를 스스로 점검하세요. 미달성 항목은 강의 자료의 해당 Part를 다시 확인하거나 Slack 채널에 질문을 남기세요.
| 목표 | 확인 질문 | 관련 |
|---|---|---|
| Concept | Context Isolation과 위임의 가치를 설명할 수 있는가 | 강의 Part 1 |
| Define | YAML frontmatter 4필드로 에이전트를 정의했는가 | Task 1 |
| Least Privilege | tools 화이트리스트로 권한 거부와 부여를 체험했는가 | Task 2 |
| Description | 자동 디스패치가 description 기반임을 확인했는가 | Task 3, 4 |
| Dispatch | 자동 / 명시 / 병렬 3패턴을 모두 실행했는가 | Task 4 |
| Cost | /cost로 에이전트별 비용과 병렬 트레이드오프를 확인했는가 | Task 4 |
| Automation | 헤드리스 + JSON으로 CI 통합 패턴을 실행했는가 | Task 5 |