Hands-on Lab / Chapter 5

CLI Reference, Claude Code를 파이프라인의 부품으로

Claude Code Deep Dive Workshop, Chapter 5 - CLI Reference 실습

이 랩에서는 Claude Code를 대화 도구에서 자동화 부품으로 바꿉니다. 헤드리스 호출 5패턴, JSON 파싱, 커밋 범위를 받는 로컬 리뷰 봇 스크립트, 다중 호출 데이터를 CSV와 HTML 대시보드로 만드는 파이프라인, 그리고 GitHub Actions 통합까지 40분에 완주합니다. Chapter 1에서 인증을 마친 상태를 전제합니다.

소요 시간 40분 내외 Task 준비 + 4개 기준 버전 Claude Code 2.1.x Update 2026.07
TASK 00

사전 준비 확인

2분

헤드리스 호출은 실제 API를 사용하므로 인증 상태를 먼저 확인하고, 리뷰 대상이 될 커밋 2개짜리 실습 저장소를 만듭니다.

1인증 확인과 실습 저장소 생성
Terminal, 전체 복사
claude auth status || echo "로그인 필요: claude 실행 후 인증 (Chapter 1 참고)"
jq --version

mkdir -p ~/claude-lab/ch5/src && cd ~/claude-lab/ch5

cat > package.json << 'EOF'
{
  "name": "cli-lab",
  "version": "1.0.0",
  "dependencies": { "express": "4.17.1", "lodash": "4.17.20" }
}
EOF

cat > src/pay.js << 'EOF'
export function charge(amount) {
  return { ok: true, amount };
}
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: cli lab scaffold"

cat > src/pay.js << 'EOF'
export function charge(amount) {
  // TODO: 입력 검증 없이 그대로 청구
  return { ok: true, amount, currency: "KRW" };
}
EOF
git commit -qam "feat: add currency to charge"
git log --oneline
CHECKPOINT
TASK 01

헤드리스 5패턴, 자동화의 어휘

10분

앞으로 모든 자동화에서 반복될 5가지 기본 패턴을 손에 익힙니다. 각 명령을 실행하고 출력 구조를 관찰하세요.

1패턴 1, 단순 호출
Terminal
claude -p "리스트와 튜플의 차이를 정확히 3줄로"
2패턴 2, JSON 출력과 result 추출
Terminal
claude -p "정렬 알고리즘 3가지 이름만" --output-format json | jq -r '.result'
3패턴 3, 토큰과 비용 추적
Terminal
claude -p "OK 한 단어만" --output-format json | \
  jq '{in: .usage.input_tokens, out: .usage.output_tokens, usd: .total_cost_usd, ms: .duration_ms}'
출력 예시
{ "in": 4213, "out": 5, "usd": 0.013, "ms": 2841 }
4패턴 4, 파이프 입력
Terminal
cat package.json | claude -p "이 의존성 목록에서 눈에 띄는 위험 하나만 한 줄로"
5패턴 5, 세션 이어가기
Terminal, 전체 복사
S=$(claude -p "정렬 알고리즘 3가지 이름만" --output-format json | jq -r '.session_id')
echo "session: $S"
claude -p --resume "$S" "그 중 첫 번째 것만 파이썬 코드로" --output-format json | jq -r '.result'
구자료 주의, 세션 지정은 --resume입니다 구버전 자료의 claude --continue "$SESSION_ID"는 현행과 다릅니다. -c / --continueID 없이 현재 디렉토리의 최근 대화를 잇고, 특정 세션을 ID나 이름으로 지정할 때는 -r / --resume을 씁니다. 분기해서 실험하고 싶으면 --resume "$S" --fork-session으로 새 세션 ID를 만듭니다.
스크립트 가속, --bare 훅, 스킬, MCP, CLAUDE.md 탐색이 필요 없는 순수 텍스트 작업이라면 claude --bare -p "..."로 시작 오버헤드를 줄일 수 있습니다. 반복 호출 파이프라인에서 체감이 큽니다.
CHECKPOINT
TASK 02

자동화 스크립트, 로컬 리뷰 봇

10분

커밋 범위를 인자로 받아 diff를 리뷰하고, 결과를 파일로 남기며, 심각도에 따라 exit code로 신호하는 스크립트를 만듭니다. 이 exit code가 Task 4에서 CI 게이트가 됩니다.

1my-review.sh 작성
Terminal, 전체 복사
cd ~/claude-lab/ch5
cat > my-review.sh << 'EOF'
#!/bin/bash
# my-review.sh <커밋범위> - 로컬 코드 리뷰 봇
set -euo pipefail
RANGE="${1:?Usage: ./my-review.sh <commit-range>  예: HEAD~1..HEAD}"

echo "1) diff 수집: $RANGE"
DIFF=$(git diff "$RANGE")
[ -z "$DIFF" ] && { echo "diff 없음"; exit 0; }

echo "2) Claude 리뷰 실행..."
RESULT=$(claude -p "$(cat <<PROMPT
다음 diff를 리뷰하세요.
관점: 1) 버그 위험 2) 보안 3) 테스트 필요성
각 지적은 "- [심각도] 파일: 내용" 형식, 심각도는 CRITICAL/WARN/INFO 중 하나.
심각한 문제가 없으면 "- [INFO] 특이사항 없음" 한 줄만.

$DIFF
PROMPT
)" --output-format json --max-turns 5 \
  --allowed-tools "Read" "Grep" "Glob")

echo "$RESULT" | jq -r '.result' > review.md
COST=$(echo "$RESULT" | jq -r '.total_cost_usd')
echo "3) 저장: review.md (비용: \$$COST)"

if grep -q "CRITICAL" review.md; then
  echo "4) CRITICAL 발견 → exit 1 (게이트 차단 신호)"
  exit 1
fi
echo "4) 통과"
EOF
chmod +x my-review.sh
bash -n my-review.sh && echo "문법 OK"
2실행과 exit code 확인
Terminal
./my-review.sh HEAD~1..HEAD; echo "exit code: $?"
cat review.md
출력 예시
1) diff 수집: HEAD~1..HEAD
2) Claude 리뷰 실행...
3) 저장: review.md (비용: $0.021)
4) 통과
exit code: 0
- [WARN] src/pay.js: amount 입력 검증 부재, 음수/비숫자 방어 필요
- [INFO] 테스트 파일 부재 ...
스크립트에 넣은 안전장치 3가지 set -euo pipefail은 중간 실패를 즉시 드러내고, --max-turns 5는 폭주를 막고, --allowed-tools "Read" "Grep" "Glob"은 읽기 전용으로 제한합니다(공백 구분 다중 인자 형식). 예산 상한이 필요하면 --max-budget-usd 0.50을 더하세요.
GitHub PR 버전으로 확장 (참고) gh CLI가 있다면 diff 소스를 gh pr diff "$PR_NUM"으로 바꾸고, 마지막에 gh pr comment "$PR_NUM" --body-file review.md를 붙이면 그대로 PR 리뷰 봇이 됩니다. 사람 확인 후 게시하도록 read 프롬프트를 두는 것이 강의에서 다룬 안전 패턴입니다.
CHECKPOINT
TASK 03

파싱 파이프라인, JSON에서 대시보드까지

10분

여러 호출의 JSON을 모아 CSV로 변환하고 통계를 집계한 뒤 HTML 대시보드로 만듭니다. 조직의 사용량/비용 리포트 자동화가 이 구조의 확장판입니다.

1데이터 수집, 3회 호출

비용 절약을 위해 --model haiku로 수집합니다.

Terminal, 전체 복사
cd ~/claude-lab/ch5 && mkdir -p data
for topic in Python Go Rust; do
  echo "수집: $topic"
  claude -p "$topic 언어의 장점을 정확히 2가지, 각 한 줄로" \
    --model haiku --output-format json > "data/$topic.json"
done
ls -la data/
2JSON → CSV 변환
Terminal, 전체 복사
{
  echo "topic,duration_ms,input_tokens,output_tokens,cost_usd"
  jq -r '[
    (input_filename | sub("data/"; "") | sub("\\.json$"; "")),
    .duration_ms, .usage.input_tokens, .usage.output_tokens, .total_cost_usd
  ] | @csv' data/*.json
} > stats.csv
cat stats.csv
출력 예시
topic,duration_ms,input_tokens,output_tokens,cost_usd
"Go",2113,4188,42,0.0031
"Python",2410,4190,45,0.0032
"Rust",2287,4189,44,0.0031
구자료 주의, 슬러프(-s)와 input_filename은 함께 쓰면 안 됩니다 구버전 자료의 jq -rs '.[] | [(input_filename | ...)]' 패턴은 슬러프가 모든 파일을 먼저 읽어버려 모든 행에 마지막 파일명이 찍힙니다. 파일당 JSON이 하나라면 위처럼 -s 없이 파일별 처리가 정답입니다. 반대로 아래 통계 집계는 전체를 하나의 배열로 봐야 하므로 -s가 맞습니다.
3통계 집계
Terminal, 전체 복사
jq -rs '{
  total_calls: length,
  avg_duration_ms: ([.[].duration_ms] | add / length | floor),
  total_input: ([.[].usage.input_tokens] | add),
  total_output: ([.[].usage.output_tokens] | add),
  total_cost_usd: ([.[].total_cost_usd] | add)
}' data/*.json
4HTML 대시보드 생성
Terminal, 전체 복사
cat << HTML > dashboard.html
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>Claude Usage</title>
<style>
  body { font-family: sans-serif; max-width: 760px; margin: 40px auto; }
  table { border-collapse: collapse; width: 100%; }
  th, td { padding: 8px 10px; border-bottom: 1px solid #ddd; text-align: left; }
  th { background: #f0f0f0; }
</style></head><body>
<h1>Claude 호출 통계</h1>
<p>생성: $(date)</p>
$(awk -F, 'BEGIN{print "<table>"}
NR==1{printf "<tr>"; for(i=1;i<=NF;i++) printf "<th>%s</th>", $i; print "</tr>"; next}
{gsub(/"/,""); printf "<tr>"; for(i=1;i<=NF;i++) printf "<td>%s</td>", $i; print "</tr>"}
END{print "</table>"}' stats.csv)
</body></html>
HTML
echo "생성 완료: dashboard.html (브라우저로 열어 확인)"
실전으로 가는 확장 이 파이프라인의 topic 자리에 파일 목록이나 이슈 목록이 들어가면 대량 처리 패턴이 됩니다. 수백 건이라면 조직 관점에서는 Chapter 3의 OTel 텔레메트리가 이 수집을 대체하고, 개별 스크립트는 --max-budget-usd로 상한을 거는 것이 안전합니다. 스트리밍 이벤트 단위 처리가 필요하면 --output-format stream-json을 사용합니다.
CHECKPOINT
TASK 04

CI 통합, GitHub Actions 워크플로

8분

Task 2의 리뷰 봇 개념을 CI로 올립니다. 워크플로 작성과 문법 검증은 전원 진행하고, 실제 push 검증은 GitHub 저장소 보유자용 선택 트랙입니다.

1워크플로 작성
Terminal, 전체 복사
cd ~/claude-lab/ch5
mkdir -p .github/workflows
cat > .github/workflows/claude-check.yml << 'EOF'
name: Claude Check

on:
  pull_request:
    types: [opened, synchronize]
  workflow_dispatch:

permissions:
  contents: read

jobs:
  claude-check:
    runs-on: ubuntu-latest
    timeout-minutes: 5
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - name: Install Claude Code
        run: npm install -g @anthropic-ai/claude-code
      - name: Review diff
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
        run: |
          git diff origin/${{ github.base_ref }}...HEAD | \
            claude -p "이 diff에서 CRITICAL 수준 문제만 지적, 없으면 PASS 한 단어" \
            --output-format json --max-turns 3 --max-budget-usd 0.50 | \
            jq -r '.result' | tee check.md
          grep -q "CRITICAL" check.md && exit 1 || echo "게이트 통과"
EOF
python3 -c "import yaml; yaml.safe_load(open('.github/workflows/claude-check.yml')); print('YAML 문법 OK')"
2인증 준비, 3가지 경로
경로방법적합
API Key저장소 Settings → Secrets → ANTHROPIC_API_KEY 등록Console 계정 팀
구독 토큰로컬에서 claude setup-token으로 장수명 토큰 발급 후 Secret 등록Pro/Max 구독 CI
BedrockOIDC로 AWS 역할 Assume + CLAUDE_CODE_USE_BEDROCK=1키 없는 조직 표준 (Ch3)
3선택 트랙, 실제 실행 (GitHub 저장소 보유자)
Terminal, 선택
git checkout -b test-claude-ci
git add .github && git commit -m "ci: add claude check"
git push -u origin test-claude-ci
gh pr create --title "Test Claude CI" --body "Testing" --fill 2>/dev/null || true
gh run watch
CI 비용과 안전의 3중 잠금 timeout-minutes(작업 시간 상한), --max-turns(에이전트 턴 상한), --max-budget-usd(지출 상한)를 항상 함께 거세요. permissions는 최소로 시작하고(PR 코멘트가 필요할 때만 pull-requests: write 추가), 시크릿은 organization secret으로 중앙 관리하는 것이 회전에 유리합니다.
CHECKPOINT

마무리, 학습 목표 체크리스트

Chapter 5의 학습 목표를 스스로 점검하세요. 미달성 항목은 진행자에게 질문하거나 강의 자료의 해당 Part를 다시 확인합니다.

목표확인 질문관련
Headless-p / JSON / 파이프 / --resume 5패턴을 손으로 실행했는가Task 1
Scriptingdiff 주입, 도구 제한, exit code 게이트 스크립트를 만들었는가Task 2
Parsing다중 호출 JSON을 CSV와 대시보드로 집계했는가Task 3
CI/CD3중 잠금이 걸린 워크플로를 작성하고 검증했는가Task 4
M자동화 5패턴 지도, 오늘 골격이 꽂히는 곳
패턴구조오늘 만든 재료
1 PR 리뷰 봇diff 주입 → 리뷰 → 코멘트/게이트Task 2 + Task 4 그대로
2 이슈 트리아지이슈 본문 파이프 → 분류 JSON → 라벨링Task 1 패턴 4 + jq
3 코드 마이그레이션파일 루프 → 변환 → 실패 수집Task 3 루프 구조
4 보안 감사주기 실행 → CRITICAL 게이트 → 알림Task 2 exit code + cron
5 일일 보고서다중 수집 → 집계 → HTML 발행Task 3 파이프라인 그대로
NEXT CHAPTER

Chapter 6 - Agent SDK

CLI 파이프라인의 다음 단계는 코드입니다. 셸 스크립트로 엮던 것을 Python / TypeScript SDK로 옮겨, 멀티턴 제어, 커스텀 도구, 프로덕션 에이전트 서비스까지 확장합니다.