Claude Code CLI vs SDK
— 에이전트 워크플로우 비교
이 실습이 끝나면 같은 작업(논문 작성 워크플로우)을 CLI 대화, subprocess 자동화, API 직접 호출의 세 가지 방식으로 구현하고, 상황에 맞는 방식을 스스로 고를 수 있게 된다. 순서는 CLI → SDK(CLI 호출) → SDK(API)다.
세 가지 방식, 한눈 비교
핵심 차이는 "누가 에이전트인가"다. ①은 Claude가, ②는 CLI가 에이전트이고 코드는 오케스트레이터, ③은 내가 에이전트 루프를 설계한다.
비교표: 본질 · 도구 · 비용 · 제어
Claude Code CLI와 Anthropic SDK로 에이전트를 구성하는 방식은 크게 세 가지다. 아래 표가 이 페이지 전체의 지도다.
| 구분 | ① CLI 직접 | ② SDK에서 CLI 호출 | ③ SDK API 직접 호출 |
|---|---|---|---|
| 본질 | 터미널 대화형 지시 | Python이 CLI를 서브프로세스 실행 | Python이 Claude API 직접 호출 |
| 에이전트 | Claude 자체가 에이전트 | CLI가 에이전트, 코드가 오케스트레이터 | 내가 에이전트 루프를 설계 |
| 도구(파일/실행) | 내장 자동 | CLI 내장 도구 자동 | 직접 정의·구현 |
| 코드량 | 없음 | 적음(subprocess) | 많음(tool 정의 등) |
| 자동화 | 셸 스크립트 수준 | Python 완전 자동화 | Python 완전 자동화 |
| 비용 | Claude Code 구독 | Claude Code 구독 | API 토큰 종량 과금 |
| 제어 | 프롬프트 간접 | 프롬프트+코드 분기 | 완전한 코드 제어 |
| 적합 | 탐색·일회성 | CLI 장점+자동화 | 프로덕션·고도 커스텀 |
이 페이지의 실습은 하나의 시나리오를 세 방식으로 반복한다. LaTeX 논문 작성 워크플로우 — 문헌 분석, Related Work 수정, Figure 생성, 전체 리뷰, 커밋. 같은 작업이 방식에 따라 어떻게 달라지는지 비교하며 따라가면 된다.
CLI로 논문 작업 — Claude 자체가 에이전트
사람은 '무엇을'만 말하고, Claude가 '어떻게'(도구 선택·실행 순서)를 결정한다. 자연어 한마디가 곧 오케스트레이션이다.
설치와 CLAUDE.md
설치는 npm 한 줄, 실행은 프로젝트 폴더에서 claude 한 단어다. 프로젝트 루트에 CLAUDE.md를 두면 Claude가 자동으로 읽고 규칙을 따른다.
npm install -g @anthropic-ai/claude-code cd my-paper # 프로젝트 폴더로 이동 claude # 대화 시작
CLAUDE.md 예시 — 프로젝트 개요 · 구조 · 작업 규칙
# CLAUDE.md ## 프로젝트 개요 LaTeX로 작성하는 학술 논문 프로젝트다. ## 구조 - paper/main.tex : 논문 본문 - paper/refs.bib : 참고문헌 - scripts/plot.py : Figure 생성 스크립트 - results/ : 실험 결과 데이터 ## 작업 규칙 - .tex 수정 후에는 pdflatex 컴파일이 되는지 확인한다 - Figure는 scripts/plot.py를 실행해 생성한다 - 커밋 메시지는 한국어로 쓴다
- 프로젝트 폴더에서
claude실행 시 CLAUDE.md를 읽었다는 표시가 나오는가 - 이후 모든 대화에서 CLAUDE.md의 작업 규칙이 자동으로 적용되는가
대화형 워크플로우 5단계
코드 없이 자연어 다섯 마디로 논문 작업 전체가 돌아간다. 각 단계에서 Claude는 스스로 파일을 읽고, 수정하고, 스크립트를 실행하고, 커밋한다.
- 문헌 분석 — refs.bib를 읽고 연구 흐름을 정리시킨다.
refs.bib에서 주요 논문을 읽고 연구 흐름을 시간순으로 분류해줘
- 섹션 업데이트 — 방금의 분석을 이어받아 Related Work를 고친다.
방금 분석한 내용을 바탕으로 Related Work 섹션을 업데이트해줘. 기존 내용은 유지하고 빠진 분류만 추가해줘
- Figure 생성 — 결과 폴더를 분석해 시각화 코드를 추가하고 실행까지 시킨다.
results/ 폴더를 분석해서 plot.py에 시각화 함수를 추가하고 실행해줘
- 전체 리뷰 — 문법·논리·인용을 한 번에 점검한다.
main.tex 전체를 리뷰해줘. 문법 오류, 논리 전개, 인용 누락을 확인해줘
- 커밋 — 변경사항을 의미 단위로 나눠 커밋시킨다.
변경사항을 의미 단위로 나눠서 커밋해줘
사람은 '무엇을'만 말한다. '어떻게'(어떤 파일을 읽을지, 어떤 도구를 쓸지, 어떤 순서로 실행할지)는 Claude가 결정한다. 자연어 한마디가 곧 오케스트레이션이다.
이 5단계를 매주 반복해야 한다면 어떨까. 매번 터미널을 열고 같은 다섯 마디를 입력하는 것은 곧 지겨워진다. 이 반복을 코드로 옮기는 것이 다음 파트다.
subprocess로 CLI를 코드에 넣기
CLI가 에이전트 역할을 그대로 하고, Python 코드는 오케스트레이터가 된다. API 키 없이 구독만으로 완전 자동화가 가능하다.
claude -p 를 subprocess로 실행한다
claude -p "프롬프트"는 대화 없이 한 번 실행하고 결과를 출력하는 비대화 모드다. 이것을 subprocess로 감싸면 CLI가 곧 함수가 된다.
import subprocess
def claude_cli(prompt: str, cwd: str = ".") -> str:
result = subprocess.run(["claude", "-p", prompt], cwd=cwd,
capture_output=True, text=True, timeout=300)
return result.stdout
review = claude_cli("main.tex를 읽고 문법·논리 오류를 찾아줘", cwd="paper")
출력을 구조화해서 받기
--output-format json 옵션을 주면 결과가 JSON으로 나와, 코드에서 파싱해 다음 단계에 넘기기 좋다.
import subprocess, json
def claude_cli_json(prompt: str, cwd: str = ".") -> str:
r = subprocess.run(
["claude", "-p", prompt, "--output-format", "json"],
cwd=cwd, capture_output=True, text=True, timeout=300)
return json.loads(r.stdout)["result"]
멀티 단계 파이프라인: CLI 호출을 코드로 연결
Part 1의 대화 5단계가 그대로 함수 호출의 연쇄가 된다. 앞 단계의 결과를 다음 단계 프롬프트에 주입하는 것이 핵심이다.
# paper_pipeline.py — 문헌 분석 → 섹션 업데이트 → Figure → 리뷰
# 1) 문헌 분석
analysis = claude_cli(
"refs.bib에서 주요 논문을 읽고 연구 흐름을 시간순으로 분류해줘",
cwd="paper")
# 2) 섹션 업데이트 — 분석 결과를 프롬프트에 주입
claude_cli(
"다음 문헌 분석을 바탕으로 Related Work 섹션을 업데이트해줘. "
"기존 내용은 유지하고 빠진 분류만 추가해줘.\n\n" + analysis,
cwd="paper")
# 3) Figure 생성
claude_cli(
"results/ 폴더를 분석해서 plot.py에 시각화 함수를 추가하고 실행해줘",
cwd="paper")
# 4) 전체 리뷰
review = claude_cli(
"main.tex 전체를 리뷰해줘. 문법 오류, 논리 전개, 인용 누락을 확인해줘",
cwd="paper")
print(review)
python paper_pipeline.py한 번으로 4단계가 사람 개입 없이 순서대로 실행되는가- 2단계 프롬프트에 1단계의 분석 결과가 실제로 포함되어 전달되는가
이 방식으로 대부분의 자동화가 가능하다. 그런데 각 단계에서 도구 자체를 내 마음대로 정의하고 싶다면, 혹은 대화 맥락 없이 역할별로 완전히 독립된 에이전트를 여럿 돌리고 싶다면? 그것이 다음 파트다.
내가 에이전트 루프를 설계한다
도구 정의, 실행, 루프, 역할 분리까지 전부 내 코드다. 코드량은 가장 많지만 제어는 완전하다. 과금은 API 토큰 종량제다.
anthropic SDK 설치와 첫 호출
SDK를 설치하고 API 키를 환경변수로 등록하면, Claude 호출은 client.messages.create 한 번이다.
pip install anthropic export ANTHROPIC_API_KEY=sk-ant-... # 발급받은 API 키
from anthropic import Anthropic
client = Anthropic() # ANTHROPIC_API_KEY 환경변수를 자동으로 읽는다
response = client.messages.create(
model="claude-opus-5",
max_tokens=4096,
system="당신은 LaTeX 논문 작성을 돕는 조교다.",
messages=[{"role": "user",
"content": "main.tex의 다음 문단에서 문법 오류를 찾아줘:\n" + paragraph}],
)
print(response.content[0].text)
여기까지는 단순한 질의응답이다. 파일을 읽거나 명령을 실행하는 능력은 아직 없다. 그 능력을 주는 것이 Tool Use다.
도구를 직접 정의한다 — read_file / write_file / run_command
CLI에서는 내장이던 도구를 여기서는 input_schema로 직접 정의한다. Claude가 도구를 호출하면 실제 실행은 내 코드가 한다.
import subprocess
tools = [
{
"name": "read_file",
"description": "지정한 경로의 텍스트 파일을 읽어 내용을 돌려준다",
"input_schema": {
"type": "object",
"properties": {"path": {"type": "string", "description": "파일 경로"}},
"required": ["path"],
},
},
{
"name": "write_file",
"description": "지정한 경로에 내용을 저장한다",
"input_schema": {
"type": "object",
"properties": {"path": {"type": "string"},
"content": {"type": "string"}},
"required": ["path", "content"],
},
},
{
"name": "run_command",
"description": "셸 명령을 실행하고 출력을 돌려준다 (예: pdflatex, python)",
"input_schema": {
"type": "object",
"properties": {"command": {"type": "string"}},
"required": ["command"],
},
},
]
def execute_tool(name: str, args: dict) -> str:
if name == "read_file":
return open(args["path"], encoding="utf-8").read()
if name == "write_file":
with open(args["path"], "w", encoding="utf-8") as f:
f.write(args["content"])
return "saved"
if name == "run_command":
r = subprocess.run(args["command"], shell=True,
capture_output=True, text=True, timeout=120)
return r.stdout + r.stderr
while True — 에이전트의 심장
Claude가 도구를 요청하면 실행해서 결과를 돌려주고, 다시 호출한다. stop_reason이 end_turn이 될 때까지 반복하는 이 루프가 에이전트의 전부다.
def agent_loop(task: str) -> str:
messages = [{"role": "user", "content": task}]
while True:
response = client.messages.create(
model="claude-opus-5", max_tokens=4096,
tools=tools, messages=messages)
if response.stop_reason == "end_turn": # 작업 완료
return response.content[0].text
if response.stop_reason == "tool_use": # 도구 호출 요청
messages.append({"role": "assistant", "content": response.content})
results = []
for block in response.content:
if block.type == "tool_use":
output = execute_tool(block.name, block.input)
results.append({"type": "tool_result",
"tool_use_id": block.id,
"content": str(output)})
messages.append({"role": "user", "content": results})
- 도구 호출 → 실행 → 결과 전달 → 재호출의 순환이 코드에서 보이는가
- CLI가 내부에서 해 주던 일이 정확히 이 루프였다는 것이 납득되는가
역할별 에이전트 4개로 파이프라인 구성
각 에이전트에 전용 시스템 프롬프트와 깨끗한 컨텍스트를 준다. 문헌 분석 → 작성 → Figure → 리뷰가 서로 독립된 전문가로 이어진다.
def run_agent(system: str, task: str, use_tools: bool = False) -> str:
"""전용 시스템 프롬프트 + 독립 컨텍스트로 에이전트 1개 실행"""
messages = [{"role": "user", "content": task}]
while True:
response = client.messages.create(
model="claude-opus-5", max_tokens=4096, system=system,
tools=tools if use_tools else [], messages=messages)
if response.stop_reason != "tool_use":
return response.content[0].text
messages.append({"role": "assistant", "content": response.content})
results = [{"type": "tool_result", "tool_use_id": b.id,
"content": str(execute_tool(b.name, b.input))}
for b in response.content if b.type == "tool_use"]
messages.append({"role": "user", "content": results})
# 파이프라인: 문헌 분석 → 작성 → Figure → 리뷰
literature = run_agent(
"당신은 문헌 분석 전문가다.",
"refs.bib의 논문들을 읽고 연구 흐름을 시간순으로 분류하라",
use_tools=True) # read_file
draft = run_agent(
"당신은 LaTeX 논문 작성 전문가다.",
"다음 문헌 분석을 반영해 Related Work 섹션을 수정하라:\n" + literature,
use_tools=True) # read_file / write_file
figures = run_agent(
"당신은 matplotlib 시각화 전문가다.",
"results/를 분석해 plot.py에 시각화 함수를 추가하고 실행하라",
use_tools=True) # run_command
review = run_agent(
"당신은 엄격한 논문 리뷰어다.",
"main.tex를 리뷰하고 심각한 문제를 우선순위 순으로 지적하라",
use_tools=True)
print(review)
같은 파이프라인을 Part 2에서는 CLI 호출 네 줄로 만들었다. 여기서는 코드가 훨씬 길다. 그런데도 이 방식을 쓰는 이유가 뭘까. 다음 섹션이 그 답이다 — 핵심 하나만 미리 말하면, 위 코드의 리뷰어는 앞 단계의 대화를 전혀 모른다. 그래서 더 엄격하다.
"대화로 하면 되는데 왜 코드로?" — SDK 장점 8가지
결론부터: 일회성 작업이면 대화가 낫다. 반복·병렬·무인 실행·시스템 통합이 필요한 순간부터 코드가 이긴다.
격리 · 분기 · 병렬 · 재현성
for i in range(3): 리뷰 → 심각 이슈 없으면 break, 있으면 수정 — 사람이 없어도 리뷰→수정→재리뷰가 자동으로 돈다.asyncio.gather로 챕터 5개를 동시에 리뷰 — 시간이 1/5로 준다.로깅 · 스케줄링 · 에러 처리 · 시스템 통합
CLI = "나 대신 해줘" (일회성 위임) / SDK = "이 프로세스를 시스템으로" (자동화 구축).
언제 무엇을 쓰나 — 선택 가이드
대부분의 자동화 니즈는 ② SDK+CLI로 충분하다. ③은 프로덕션·고도 커스텀이 필요할 때만 전환한다.
이 상황이면 CLI로 충분, 저 상황이면 SDK
| 상황 | 판단 | 이유 |
|---|---|---|
| 논문 한 번 리뷰 | CLI 충분 | 일회성 작업은 대화가 가장 빠르다 |
| 1개 작업 · 혼자 · 단순 수정 | CLI 충분 | 자동화 비용이 이득보다 크다 |
| 매주 반복 실행 | SDK | 스케줄링(cron) — 사람 없이 돌아야 한다 |
| 10개 문서 배치 처리 | SDK | 병렬 실행으로 시간 단축 |
| 팀과 공유 | SDK | 대화는 공유가 안 되고 코드는 된다 |
| 리뷰→수정→재리뷰 자동 루프 | SDK | 조건 분기를 코드가 판단 |
| Notion·GitHub·DB 등 시스템 연결 | SDK | 출력 후처리·통합은 코드의 영역 |
세 방식 각각의 적합 영역
| 방식 | 적합한 상황 |
|---|---|
| ① CLI | 탐색적 작업, 일회성 복잡 작업, 빠른 반복 |
| ② SDK+CLI | 반복 자동화, CLI 기능+자동화, API 키 없이 — 대부분의 자동화 니즈는 이걸로 충분 |
| ③ SDK API | 프로덕션 서비스, 커스텀 도구, 토큰·비용·형식 세밀 제어, DB·외부 API 통합 |
①에서 시작해 필요할 때만 ③으로
- CLI로 "이게 되네!" 확인 — 먼저 대화로 작업이 가능한지, 품질이 나오는지 탐색한다.
- subprocess로 자동화 — 반복이 확인되면 그 대화를
claude -p파이프라인으로 옮긴다. - 필요할 때만 API 전환 — 프로덕션 서비스화, 커스텀 도구, 세밀한 비용·형식 제어가 필요해진 시점에 ③으로 간다.
실습 과제 4개
15분짜리 CLI 실습에서 45분짜리 멀티에이전트 구현까지, 이 페이지의 세 방식을 순서대로 직접 만들어 본다.
CLI → 자동 리뷰 → 파이프라인 → 멀티에이전트
- 과제 1: CLAUDE.md의 규칙이 교정·커밋에 실제로 반영되었는가
- 과제 2: review_output.md가 생성되고, .tex 여러 개에 대해 루프가 도는가
- 과제 3: 사람 개입 없이 4단계가 끝까지 실행되는가
- 과제 4: 에이전트 4개가 각자 독립 컨텍스트로 실행되는가 / (도전) 피드백 루프가 도는가
핵심 정리
세 방식의 본질과 실무 경로를 한 번 더 눌러 둔다.
세 문장으로 남기는 결론
하나. ① CLI = Claude가 에이전트. 자연어로 위임하는 방식이며, 탐색과 일회성 작업에서 가장 빠르다.
둘. ② SDK+CLI = CLI를 코드로 자동화. API 키 없이 구독만으로 반복·파이프라인이 돌아가는, 가장 실용적인 방식이다.
셋. ③ SDK API = 내가 에이전트를 설계. 도구 정의부터 루프까지 완전한 제어가 필요할 때 쓴다. 대부분은 ①→②로 충분하고, ③은 프로덕션으로 갈 때 전환한다.
| 핵심 용어 | 의미 |
|---|---|
| CLAUDE.md | 프로젝트 루트에 두는 지침 파일. CLI가 자동으로 읽고 작업 규칙으로 따른다 |
| claude -p | CLI의 비대화 모드. 프롬프트 한 번 실행 후 결과를 출력해 subprocess 자동화에 쓴다 |
| Tool Use | 도구를 input_schema로 정의해 Claude가 호출하게 하는 API 기능. 실행은 내 코드가 담당 |
| 에이전트 루프 | stop_reason이 tool_use인 동안 도구 실행→결과 전달을 반복하는 while 루프 |
| 컨텍스트 격리 | 에이전트마다 깨끗한 대화 상태와 전용 시스템 프롬프트를 주어 역할 품질을 높이는 것 |
출처 원본 노션 페이지: Claude Code CLI vs SDK — 에이전트 워크플로우 비교, indecisive-pyramid-af1.notion.site
이 자료는 단일 HTML 파일로 배포되는 실습 가이드다. 코드 블록은 원문 그대로이며, 프롬프트 블록은 우측 상단 버튼으로 복사할 수 있다.