
에이전트 설계 및 오케스트레이션을 핸즈온으로 배우기
요약
Anthropic의 CCA-F 자격증 대비를 위한 에이전트 설계 및 오케스트레이션 핸즈온 가이드입니다. Claude Code 설치부터 API 과금 체계의 차이점, 그리고 4단계의 에이전트 패턴 구현 과정을 상세히 다룹니다.
핵심 포인트
- Claude Code(CLI)와 Messages API의 과금 체계 차이 숙지 필요
- 에이전트 설계의 4단계: 도구 호출, 루프, 병렬 실행, 멀티 에이전트
- Claude Pro 구독과 API 종량제 사용 환경의 구분 방법 안내
- 실제 Python SDK를 활용한 단계별 에이전트 패턴 구현
서론
Anthropic이 2026년 3월에 시작한 기술 인증 자격 「Claude Certified Architect(CCA-F)」에서는 **에이전트 설계 및 오케스트레이션 (Agent Design & Orchestration)**이 가장 비중이 높은 출제 영역으로 꼽힙니다. 이론만으로는 이해하기 어려운 분야이기에, 실제로 직접 움직이며 기초 패턴을 몸에 익히기로 했습니다.
이 기사에서는 환경 구축 과정에서 막혔던 부분부터 4단계의 핸즈온(단발성 도구 호출 → 에이전트 루프 → 병렬 도구 실행 → 멀티 에이전트 오케스트레이션)까지, 실제로 거친 절차 그대로를 해설합니다.
대상 독자:
- CCA-F 수험을 검토 중인 분
- Claude API로 에이전트를 구축하기 시작하고 싶은 분
- Claude Code를 이제 막 사용하려는 분
본 기사에서 사용한 코드는 아래 리포지토리에서 공개하고 있습니다.
환경 구축에서 막혔던 점
Claude Code 설치
Claude Code는 다음 명령어로 설치할 수 있습니다.
npm install -g @anthropic-ai/claude-code
보충: nodenv를 사용하는 분은 글로벌로 설치한 패키지의 심(shim)을 수동으로 재생성해야 합니다.
nodenv rehash
claude --version
# => 2.1.211 (Claude Code)
로그인 방법 선택하기
Claude Code에는 두 가지 인증 방법이 있습니다.
| 방법 | 대상 | 과금 |
|---|---|---|
| Claude.ai 로그인 (OAuth) | Pro/Max/Team/Enterprise 계약자 | 구독 내 |
| API 키 (Console) | 종량제를 사용하고 싶은 개발자 | pay-per-token |
중요한 주의사항: 시스템에 ANTHROPIC_API_KEY라는 환경 변수가 설정되어 있으면, Pro/Max 계약 중이라도 해당 설정이 우선되어 의도치 않게 API 과금이 발생합니다. 구독 범위 내에서 사용하고 싶다면 이 환경 변수를 설정하지 않는 것이 정답입니다.
Claude Pro 계약자라면 터미널에서 claude를 실행하고, 「Claude.ai」로 로그인하는 것만으로 완료됩니다.
claude
# 브라우저가 열리므로, Claude Pro 계정으로 사인인
함정: Claude Pro ≠ 순수 Messages API
이 부분이 가장 오해하기 쉬운 포인트였습니다. Claude Code (CLI)는 Pro 구독으로 커버되지만, anthropic Python SDK를 통해 직접 api.anthropic.com을 호출하는 「순수 Messages API」는 별도 과금입니다.
즉, 앞으로 소개할 자작 Python 스크립트 (Ring 1~4)를 실행하려면, Claude Pro와는 별개로 Anthropic Console에서 API 키를 발급받고 소액의 크레딧을 충전해야 합니다.
Claude Code (CLI) → Pro 구독으로 커버
자작 Python 스크립트 (SDK) → Console API 키 + 종량제 별도 필요
「Pro를 사용 중인데 왜 돈이 또 드는가」라며 처음에는 혼란스러웠지만, CLI와 순수 API는 별개의 과금 체계라는 것을 이해하고 나서는 납득이 갔습니다.
핸즈온: 4개의 Ring으로 배우는 에이전트 패턴
여기서부터는 anthropic Python SDK를 사용하여, 단순한 도구 호출부터 본격적인 멀티 에이전트 구성까지 하나씩 개념을 쌓아 올리겠습니다.
Ring 1: 단발성 도구 호출
최소 구성으로서 도구 1개, 메시지 1개, 호출 1개를 시도합니다.
import anthropic
client = anthropic.Anthropic()
tools = [{
...
실행 결과:
stop_reason: tool_use
호출된 도구: get_weather
인자: {'city': 'Tokyo'}
여기서 이해해야 할 가장 중요한 점은, Claude 스스로는 도구를 실행하지 않는다는 것입니다. stop_reason: "tool_use"는 「이 도구를 이 인자로 호출하고 싶다」는 의사 표시일 뿐이며, 실행 여부는 애플리케이션 측의 책임입니다.
Ring 2: 에이전트 루프 (Agent Loop)
현실의 태스크는 단 한 번의 도구 호출(tool call)로 완결되지 않습니다. 결과를 보고 다음 행동을 결정해야 하므로, while 루프와 대화 이력(conversation history)의 축적이 필요합니다.
messages = [{"role": "user", "content": "도쿄와 오사카 중 어디가 더 따뜻해?"}]
while True:
response = client.messages.create(
...
주의할 점: 더미 데이터의 키 불일치
첫 실행에서는 다음과 같은 결과가 나왔습니다.
최종 답변: 죄송합니다. 도쿄와 오사카 모두 날씨 데이터를 가져올 수 없었습니다.
원인은 단순했습니다. 더미 데이터의 딕셔너리 키(dictionary key)는 영어("Tokyo")였던 반면, Claude는 일본어 질문문으로부터 그대로 city="東京"와 같이 인자를 구성했기 때문에, 딕셔너리에 해당 키가 없어 get()이 기본값(데이터 없음)을 반환한 것입니다.
# Before(영어 키만 존재)
fake_data = {"Tokyo": "맑음, 28도", "Osaka": "흐림, 25도"}
# After(일/영 양국어 대응)
...
수정 후에는 문제없이 동작했습니다.
최종 답변: 현재 날씨를 비교하면:
- 도쿄: 맑음, 28도
- 오사카: 흐림, 25도
...
이 사례는 CCA-F의 「도구 설계 (tool design)」 영역에서도 다뤄지는 중요한 교훈입니다. 도구의 스키마(schema)에 입력 형식(예: "도시명은 영어로 입력")을 명시하거나, 도구 측에서 입력을 정규화(normalization)하는 설계가 필요합니다. 실제 운용에서는 예상치 못한 입력 패턴을 어떻게 흡수하느냐가 에이전트의 신뢰성을 좌우합니다.
Ring 3: 복수 도구의 병렬 실행
Claude는 한 턴(turn)에 여러 도구를 동시에 호출할 수 있습니다. 이를 효율적으로 처리하려면 ThreadPoolExecutor 등을 사용하여 병렬 실행(parallel execution)합니다.
import concurrent.futures
def handle_tool_calls(response):
tool_use_blocks = [b for b in response.content if b.type == "tool_use"]
...
날씨에 더해 인구수도 가져오는 도구를 추가하고, "도쿄와 오사카의 날씨와 인구를 알려줘"라고 질문하면, 한 턴에 4개의 도구 호출(날씨×2, 인구×2)이 발생하며 병렬로 실행됩니다.
## 도쿄
- 날씨: 맑음, 28도
- 인구: 약 1,400만 명
...
설계상의 주의점으로서, 읽기 전용 도구(검색·참조)는 병렬 실행에 적합하지만, 상태를 변경하는 도구(쓰기·전송·삭제)는 실행 순서가 결과에 영향을 미치기 때문에 직렬 실행(serial execution)을 해야 한다는 원칙이 있습니다.
Ring 4: 멀티 에이전트 오케스트레이션 (Multi-agent Orchestration)
마지막은 하나의 Claude가 모든 것을 담당하는 것이 아니라, 「오케스트레이터 (orchestrator)」가 「워커 (worker)」에게 태스크를 위임하는 패턴입니다.
def worker_agent(task: str) -> str:
"""독립된 컨텍스트에서 단일 서브 태스크를 실행하는 워커"""
response = client.messages.create(
...
"신상품 출시 계획을 작성하라"라는 목표를 던지면, 오케스트레이터가 "시장·경쟁 분석", "프로모션 설계", "채널·재고·가격 전략"과 같은 서브 태스크로 분해하고, 각각 독립된 워커가 검토한 내용을 마지막에 하나의 계획으로 통합해 주었습니다.
왜 독립된 워커를 사용하는가? 동일한 세션 내에서 Claude에게 자기 검토(self-review)를 시키면, 직전의 추론에 영향을 받아 오류를 놓치기 쉽습니다. 이전 문맥을 가지지 않는 별도의 인스턴스에 검증이나 실행을 맡기는 것이 미묘한 문제를 발견하기 더 쉽다는 것이 이 설계의 목적입니다.
4개의 Ring을 마치며
| Ring | 개념 | 주의할 점 |
|---|---|---|
| 1 | 단발성 도구 호출, stop_reason의 의미 | 없음 |
| 2 | while 루프, 대화 이력의 축적 | 더미 데이터의 일/영 키 불일치 |
| 3 | 1턴 내의 복수 도구 호출과 병렬 실행 | 위와 동일 (수정 필요) |
| 4 | 오케스트레이터/워커 구성 | 없음 |
돌이켜보면, 가장 큰 배움은 "작동하지 않았던 순간"이었습니다. Ring2에서 날씨 데이터를 가져오지 못했던 원인을 추적하면서, 도구의 스키마 설계 (Schema Design)와 입력의 정규화 (Normalization)가 실제 운영에서 얼마나 중요한지 실감할 수 있었습니다. 이는 교과서적인 설명만으로는 얻을 수 없는 깨달음입니다.
다음에 하고 싶은 일
- Tool Runner (SDK 내장)로 교체: 이번에는 직접 작성한
while루프를 사용했지만, SDK에서 제공하는 Tool Runner를 사용하면 코드 양이 절반 정도로 줄어듭니다. 동일한 개념이 얼마나 간결해지는지 비교해보고 싶습니다. - Claude Agent SDK로의 이행: 2026년 6월 15일부터 Pro/Max/Team/Enterprise 계약자는 Agent SDK용 월간 크레딧을 무료로 받을 수 있게 되었습니다. 순수 Messages API와는 별도 과금이었던 이번 스크립트를, 구독 범위 내에서 완결되는 형태로 다시 작성할 수 있을지 시도해보고 싶습니다.
- MCP (Model Context Protocol) 연동: 외부 도구 및 데이터 소스로의 연결을 표준화하는 메커니즘으로, CCA-F의 "도구 설계 · MCP 통합" 영역과도 직결됩니다.
참고 문서
- 샘플 코드 일체 (본 기사의 리포지토리): https://github.com/qameqame/agentic-orchestration-tutorial
- Tool use: https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview
- Agent SDK의 루프 해설: https://platform.claude.com/docs/en/agent-sdk/agent-loop
- Claude Code의 루프 설계: https://code.claude.com/docs/en/how-claude-code-works
마치며
에이전트 설계 및 오케스트레이션 (Orchestration)은 개념 자체는 단순하지만, 실제로 직접 구현해보면 "도구의 입력 설계", "병렬 실행과 직렬 실행의 구분 사용", "컨텍스트 분리 (Context Separation)의 효과" 등 실무에서 매우 중요한 세부적인 판단 사항들이 곳곳에서 나타납니다. CCA-F 대비를 위해 시작했지만, 업무에서 에이전트를 구축하는 데 있어서도 그대로 사용할 수 있는 지식이 되었다고 느낍니다.
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기