ZIP
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.267 Update 2026.09
TASK FLOW

이 챕터의 진행 흐름

개요

다섯 Task가 하나의 파이프라인입니다: 어휘를 익히고, 봇을 만들고, 출력을 파싱해, CI에 올립니다.
진행 중 위치가 헷갈리면 이 흐름도로 돌아오세요.

상세 흐름도 펼쳐 보기
TASK FLOW, 자동화 파이프라인 T0 사전 준비 환경 확인 T1 헤드리스 5패턴 자동화의 어휘 T2 리뷰 봇 로컬 스크립트 T3 파싱 파이프라인 JSON, 대시보드 T4 CI 통합 GitHub Actions
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 / --continue는 ID 없이 현재 디렉토리의 최근 대화를 잇고, 특정 세션을 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으로 중앙 관리하는 것이 회전에 유리합니다.
4무인 실행 하드닝, --restricted와 --permission-prompts none (v2.1.248+ / 259+)

CI처럼 사람이 응답할 수 없는 환경을 위한 스위치가 추가되었습니다. --permission-prompts none은 프롬프트가 필요한 요청을 자동 거부하고(permission mode의 판단은 유지), --restricted는 명령 실행 도구와 WebFetch를 제거하고 파일 도구를 작업 디렉토리로 가두며 사용자/프로젝트 설정 파일을 무시합니다. 리뷰 봇처럼 읽기만 하면 되는 파이프라인의 안전벨트입니다.

Terminal, CI 스니펫
claude -p "이 diff를 리뷰하고 JSON으로 결과를 출력해 주세요" \\
  --restricted --permission-prompts none \\
  --output-format json
파이프라인 출력 한도 조절 (v2.1.261+) bashOutputMaxChars, taskOutputMaxChars 설정으로 명령과 백그라운드 작업의 인라인 출력 한도를 최대 128K자까지 올릴 수 있습니다. 긴 테스트 로그를 파일로 우회하지 않고 바로 파싱 파이프라인에 태울 때 유용합니다.
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로 옮겨, 멀티턴 제어, 커스텀 도구, 프로덕션 에이전트 서비스까지 확장합니다.

Claude Code Deep Dive Workshop, Chapter 5 Hands-on Lab
기준: Claude Code 2.1.267, 2026.09 / 비용과 출력 값은 모델과 환경에 따라 다릅니다

READING CHECK

이 페이지를 읽으셨나요?

읽음 표시는 실습 체크포인트와 별도로 관리됩니다. 아직 읽지 않음

이 페이지에서맨 위로 ↑