Claude API 가이드
Anthropic의 Claude API는 안전하고 강력한 AI 기능을 애플리케이션에 통합할 수 있는 RESTful API입니다. 이 가이드는 API 키 발급부터 고급 기능 활용까지 Claude API의 모든 것을 다룹니다.
업데이트 안내: 모델/요금/버전/정책 등 시점에 민감한 정보는 변동될 수 있습니다.
최신 내용은 공식 문서를 확인하세요.
🧭 Codex 대비 안내
Codex는 OpenAI 계정/키로 시작하며, CLI는 로그인 흐름 또는 API 키 인증을 제공합니다.
Codex 앱은 macOS 환경에서 제공됩니다. Codex 가이드 참고.
핵심 포인트
- Claude 4 시리즈: Opus (최고 성능), Sonnet (균형), Haiku (속도)
- Python, TypeScript SDK 및 HTTP API 지원
- 스트리밍, 툴 사용, 비전 등 고급 기능
- 프롬프트 캐싱으로 최대 90% 비용 절감
- 200K 토큰 컨텍스트 윈도우
Claude API 개요
모델 라인업
모델
모델 티어는 일반적으로 다음과 같이 구분됩니다:
• 고성능 티어: 복잡한 추론/분석에 적합
• 균형 티어: 성능과 비용의 균형
• 경량 티어: 빠른 응답과 대량 처리
공통 특징(상세 수치는 문서 참고):
• 긴 컨텍스트 지원
• 비전(이미지 입력) 지원
• 툴 사용 지원
• 프롬프트 캐싱 지원
주요 기능
기능
// 1. 대화형 AI
• 다중 턴 대화
• 컨텍스트 유지
• 시스템 프롬프트로 행동 제어
// 2. 비전 (Vision)
• 이미지 분석 및 설명
• 차트, 다이어그램 해석
• OCR 및 문서 이해
• 이미지 크기/형식 제한 있음 (최신 정책 확인)
// 3. 툴 사용 (Tool Use)
• 외부 함수/API 호출
• 구조화된 데이터 반환
• 다단계 툴 체이닝
• JSON 스키마 기반 정의
// 4. 스트리밍
• 실시간 응답 스트리밍
• 사용자 경험 개선
• 긴 응답에 적합
// 5. 프롬프트 캐싱
• 반복 컨텍스트 캐싱
• 반복 컨텍스트 비용 절감
• 정책/TTL은 변경 가능
시작하기
API 키 발급
절차
1. Anthropic Console 접속
https://console.anthropic.com
2. 계정 생성 또는 로그인
3. API Keys 메뉴로 이동
4. "Create Key" 클릭
5. 키 이름 입력 (예: "production", "development")
6. 생성된 키 복사 (한 번만 표시됨)
sk-ant-api03-...
7. 안전한 곳에 저장 (환경 변수 권장)
보안 주의사항
- API 키는 절대 코드에 하드코딩하지 마세요
- 환경 변수나 비밀 관리 시스템 사용
- Git에 커밋하지 않도록 .gitignore 설정
- 프론트엔드에 노출 금지 (서버에서만 사용)
- 주기적으로 키 교체
빠른 시작
Python
# 1. SDK 설치
$ pip install anthropic
# 2. API 키 설정
$ export ANTHROPIC_API_KEY='sk-ant-api03-...'
# 3. 첫 요청
import anthropic
client = anthropic.Anthropic()
message = client.messages.create(
model="claude-20260101" ,
max_tokens=1024,
messages=[
{"role": "user", "content": "안녕하세요!"}
]
)
print(message.content[0].text)
TypeScript
// 1. SDK 설치
$ npm install @anthropic-ai/sdk
// 2. 첫 요청
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
});
const message = await client.messages.create({
model: 'claude-20260101' ,
max_tokens: 1024,
messages: [
{ role: 'user', content: '안녕하세요!' }
],
});
console.log(message.content[0].text);
Messages API
기본 사용법
Python
import anthropic
client = anthropic.Anthropic(api_key="sk-ant-...")
message = client.messages.create(
model="claude-20260101" ,
max_tokens=1024,
system="당신은 친절한 AI 어시스턴트입니다.", # 선택적
messages=[
{
"role": "user",
"content": "Python으로 피보나치 수열을 구하는 함수를 작성해줘."
}
],
temperature=1.0, # 0.0 ~ 1.0, 기본 1.0
top_p=0.9, # 선택적
top_k=40, # 선택적
)
# 응답 출력
print(message.content[0].text)
# 응답 메타데이터
print(f"Model: {message.model}")
print(f"Stop reason: {message.stop_reason}") # end_turn, max_tokens, tool_use
print(f"Input tokens: {message.usage.input_tokens}")
print(f"Output tokens: {message.usage.output_tokens}")
다중 턴 대화
Python
import anthropic
client = anthropic.Anthropic()
# 대화 히스토리 관리
conversation = [
{"role": "user", "content": "내 이름은 철수야."},
]
# 첫 번째 요청
message1 = client.messages.create(
model="claude-20260101" ,
max_tokens=1024,
messages=conversation
)
print("Claude:", message1.content[0].text)
# 대화에 Claude의 응답 추가
conversation.append({
"role": "assistant",
"content": message1.content[0].text
})
# 사용자 메시지 추가
conversation.append({
"role": "user",
"content": "내 이름이 뭐라고 했지?"
})
# 두 번째 요청
message2 = client.messages.create(
model="claude-20260101" ,
max_tokens=1024,
messages=conversation
)
print("Claude:", message2.content[0].text) # "철수"라고 기억함
시스템 프롬프트
Python
# 시스템 프롬프트로 역할 정의
message = client.messages.create(
model="claude-20260101" ,
max_tokens=2048,
system="""당신은 시니어 백엔드 개발자입니다.
규칙:
1. Python과 FastAPI에 전문성을 가지고 있습니다
2. 코드는 PEP 8 스타일을 따릅니다
3. 타입 힌트를 반드시 포함합니다
4. 보안과 성능을 우선시합니다
5. 항상 에러 핸들링을 포함합니다""",
messages=[
{
"role": "user",
"content": "FastAPI로 사용자 인증 엔드포인트를 만들어줘."
}
]
)
print(message.content[0].text)
스트리밍
Python 스트리밍
Python
import anthropic
client = anthropic.Anthropic()
# stream=True로 스트리밍 활성화
with client.messages.stream(
model="claude-20260101" ,
max_tokens=1024,
messages=[
{"role": "user", "content": "긴 이야기를 들려줘."}
],
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)
print() # 줄바꿈
# 최종 메시지 객체 얻기
message = stream.get_final_message()
print(f"\n\nTotal tokens: {message.usage.input_tokens + message.usage.output_tokens}")
고급 스트리밍
Python
import anthropic
client = anthropic.Anthropic()
# 이벤트별 처리
with client.messages.stream(
model="claude-20260101" ,
max_tokens=1024,
messages=[{"role": "user", "content": "안녕하세요!"}],
) as stream:
for event in stream:
if event.type == "message_start":
print(f"메시지 시작: {event.message.model}")
elif event.type == "content_block_start":
print("콘텐츠 블록 시작")
elif event.type == "content_block_delta":
if hasattr(event.delta, 'text'):
print(event.delta.text, end="", flush=True)
elif event.type == "content_block_stop":
print("\n콘텐츠 블록 종료")
elif event.type == "message_delta":
print(f"\nStop reason: {event.delta.stop_reason}")
elif event.type == "message_stop":
print("메시지 종료")
TypeScript 스트리밍
TypeScript
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic();
const stream = await client.messages.stream({
model: 'claude-20260101' ,
max_tokens: 1024,
messages: [
{ role: 'user', content: '긴 이야기를 들려줘.' }
],
});
// 텍스트 스트림
for await (const text of stream.textStream) {
process.stdout.write(text);
}
// 최종 메시지
const message = await stream.finalMessage();
console.log(`\n\nTotal tokens: ${message.usage.input_tokens + message.usage.output_tokens}`);
툴 사용 (Function Calling)
툴 정의
Python
import anthropic
import json
client = anthropic.Anthropic()
# 툴 정의
tools = [
{
"name": "get_weather",
"description": "특정 위치의 현재 날씨를 가져옵니다.",
"input_schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "도시 이름, 예: Seoul"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "온도 단위"
}
},
"required": ["location"]
}
},
{
"name": "calculate",
"description": "수학 계산을 수행합니다.",
"input_schema": {
"type": "object",
"properties": {
"expression": {
"type": "string",
"description": "계산식, 예: 2 + 2"
}
},
"required": ["expression"]
}
}
]
# 첫 요청
message = client.messages.create(
model="claude-20260101" ,
max_tokens=1024,
tools=tools,
messages=[
{"role": "user", "content": "서울의 현재 날씨는 어때?"}
]
)
print("Response:", json.dumps(message.model_dump(), indent=2, ensure_ascii=False))
툴 실행 루프
Python
import anthropic
client = anthropic.Anthropic()
# 실제 툴 구현
def get_weather(location: str, unit: str = "celsius") -> str:
# 실제로는 API 호출
return json.dumps({
"location": location,
"temperature": 22,
"unit": unit,
"condition": "맑음"
})
def calculate(expression: str) -> str:
try:
result = eval(expression) # 실제로는 안전한 파서 사용
return str(result)
except Exception as e:
return f"Error: {e}"
# 툴 맵
tool_functions = {
"get_weather": get_weather,
"calculate": calculate,
}
# 대화 시작
messages = [
{"role": "user", "content": "서울 날씨를 알려주고, 화씨로 변환해줘."}
]
while True:
# Claude 호출
response = client.messages.create(
model="claude-20260101" ,
max_tokens=4096,
tools=tools,
messages=messages
)
print(f"\nStop reason: {response.stop_reason}")
# 종료 조건
if response.stop_reason == "end_turn":
print(f"\nFinal answer: {response.content[0].text}")
break
# 툴 사용 요청 처리
if response.stop_reason == "tool_use":
# Assistant 응답 추가
messages.append({
"role": "assistant",
"content": response.content
})
# 툴 실행
tool_results = []
for block in response.content:
if block.type == "tool_use":
tool_name = block.name
tool_input = block.input
print(f"\nCalling tool: {tool_name}({tool_input})")
# 툴 실행
tool_function = tool_functions[tool_name]
tool_result = tool_function(**tool_input)
print(f"Tool result: {tool_result}")
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": tool_result
})
# 툴 결과 추가
messages.append({
"role": "user",
"content": tool_results
})
비전 (이미지 입력)
이미지 분석
Python
import anthropic
import base64
client = anthropic.Anthropic()
# 이미지 파일 읽기
with open("diagram.png", "rb") as f:
image_data = base64.standard_b64encode(f.read()).decode("utf-8")
# 이미지와 함께 요청
message = client.messages.create(
model="claude-20260101" ,
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/png", # image/jpeg, image/gif, image/webp
"data": image_data,
},
},
{
"type": "text",
"text": "이 다이어그램을 설명해주세요."
}
],
}
],
)
print(message.content[0].text)
여러 이미지
Python
# 여러 이미지 비교
def load_image(path: str) -> str:
with open(path, "rb") as f:
return base64.standard_b64encode(f.read()).decode("utf-8")
message = client.messages.create(
model="claude-20260101" ,
max_tokens=2048,
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "이 두 이미지의 차이점을 설명해주세요:"},
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/jpeg",
"data": load_image("before.jpg"),
},
},
{"type": "text", "text": "vs"},
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/jpeg",
"data": load_image("after.jpg"),
},
},
],
}
],
)
print(message.content[0].text)
프롬프트 캐싱
캐싱 기본
개념
프롬프트 캐싱이란?
• 반복적으로 사용되는 컨텍스트(시스템 프롬프트, 문서 등)를 캐싱
• 캐시된 토큰은 입력 비용의 10%만 청구 (90% 절감)
• 5분 TTL, 사용 시마다 자동 갱신
• 최소 1024 토큰부터 캐싱 가능
비용 예시 (Claude 4 Sonnet):
일반 입력: 변동 / 1M tokens
캐시 읽기: 변동 / 1M tokens (90% 할인)
캐시 쓰기: 변동 / 1M tokens (25% 추가 비용)
언제 사용?
✓ 긴 시스템 프롬프트
✓ 큰 문서 분석 (여러 질문)
✓ 코드베이스 분석
✓ 반복적인 대화 (5분 이내)
캐싱 사용법
Python
import anthropic
client = anthropic.Anthropic()
# cache_control을 사용하여 캐싱할 블록 지정
response = client.messages.create(
model="claude-20260101" ,
max_tokens=1024,
system=[
{
"type": "text",
"text": "당신은 Python 전문가입니다. PEP 8 스타일을 따르고...", # 긴 시스템 프롬프트
"cache_control": {"type": "ephemeral"} # 캐싱 활성화
}
],
messages=[
{
"role": "user",
"content": "FastAPI 라우터를 작성해줘."
}
]
)
# 캐시 사용량 확인
print(f"Input tokens: {response.usage.input_tokens}")
print(f"Cache creation tokens: {response.usage.cache_creation_input_tokens}")
print(f"Cache read tokens: {response.usage.cache_read_input_tokens}")
# 5분 이내 두 번째 요청 (캐시 히트)
response2 = client.messages.create(
model="claude-20260101" ,
max_tokens=1024,
system=[
{
"type": "text",
"text": "당신은 Python 전문가입니다. PEP 8 스타일을 따르고...", # 동일한 텍스트
"cache_control": {"type": "ephemeral"}
}
],
messages=[
{
"role": "user",
"content": "이제 Pydantic 모델을 작성해줘."
}
]
)
# 캐시 히트 확인
print(f"\n두 번째 요청:")
print(f"Cache read tokens: {response2.usage.cache_read_input_tokens}") # 캐시된 토큰 수
문서 캐싱
Python
# 긴 문서를 캐싱하여 여러 질문
with open("long_document.txt", "r") as f:
document = f.read() # 예: 50,000 토큰
# 첫 번째 질문 (캐시 생성)
response1 = client.messages.create(
model="claude-20260101" ,
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{
"type": "text",
"text": f"다음 문서를 기반으로 답변해주세요:\n\n{document}",
"cache_control": {"type": "ephemeral"}
},
{
"type": "text",
"text": "주요 내용을 요약해주세요."
}
]
}
]
)
print(response1.content[0].text)
print(f"\n캐시 생성: {response1.usage.cache_creation_input_tokens} tokens")
# 두 번째 질문 (캐시 재사용)
response2 = client.messages.create(
model="claude-20260101" ,
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{
"type": "text",
"text": f"다음 문서를 기반으로 답변해주세요:\n\n{document}",
"cache_control": {"type": "ephemeral"}
},
{
"type": "text",
"text": "주요 등장인물은 누구인가요?"
}
]
}
]
)
print(response2.content[0].text)
print(f"\n캐시 읽기: {response2.usage.cache_read_input_tokens} tokens")
# 비용 절감 계산
normal_cost = 50000 * 3.00 / 1_000_000 # 변동
cached_cost = 50000 * 0.30 / 1_000_000 # 변동
print(f"\n비용 절감: ${normal_cost - cached_cost:.4f} (90%)")
HTTP API 직접 호출
cURL 예시
bash
curl https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-20260101",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": "안녕하세요!"
}
]
}'
응답 구조
JSON
{
"id": "msg_01XYZ...",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "안녕하세요! 무엇을 도와드릴까요?"
}
],
"model": "claude-20260101" ,
"stop_reason": "end_turn",
"stop_sequence": null,
"usage": {
"input_tokens": 12,
"output_tokens": 18
}
}
비용 최적화
최적화 전략
전략
// 1. 올바른 모델 선택
간단한 작업 → Haiku (변동/변동)
일반 작업 → Sonnet (변동/변동)
복잡한 작업 → Opus (변동/변동)
// 2. 프롬프트 캐싱
• 긴 시스템 프롬프트 캐싱
• 대용량 문서 캐싱
• 반복적인 컨텍스트 캐싱
→ 90% 비용 절감
// 3. max_tokens 제한
• 필요한 만큼만 요청
• 출력이 입력보다 5배 비쌈
• 기본값 사용 지양
// 4. 불필요한 토큰 제거
• 장황한 시스템 프롬프트 축약
• 중복 컨텍스트 제거
• XML 태그보다 간결한 구분자
// 5. 스트리밍
• 비용은 동일하지만 사용자 경험 개선
• 조기 종료 가능
// 6. 배치 처리
• 여러 작업을 하나의 요청으로 통합
• 단, 실패 시 전체 재시도 필요
비용 계산기
Python
class CostCalculator:
PRICING = {
"claude-" : (15.0, 75.0),
"claude-" : (3.0, 15.0),
"claude-" : (0.25, 1.25),
}
def calculate(self, model: str, input_tokens: int, output_tokens: int,
cached_tokens: int = 0) -> float:
"""비용 계산 (USD)"""
input_price, output_price = self.PRICING[model]
# 일반 입력 토큰
normal_input = input_tokens - cached_tokens
input_cost = normal_input * input_price / 1_000_000
# 캐시된 토큰 (90% 할인)
cache_cost = cached_tokens * (input_price * 0.1) / 1_000_000
# 출력 토큰
output_cost = output_tokens * output_price / 1_000_000
return input_cost + cache_cost + output_cost
def compare_models(self, input_tokens: int, output_tokens: int):
"""모델별 비용 비교"""
print(f"입력: {input_tokens} 토큰, 출력: {output_tokens} 토큰\n")
for model in self.PRICING:
cost = self.calculate(model, input_tokens, output_tokens)
print(f"{model:20} ${cost:.6f}")
# 사용 예시
calc = CostCalculator()
# 일반적인 요청 (2K input, 500 output)
calc.compare_models(input_tokens=2000, output_tokens=500)
# 출력:
# claude- 변동
# claude- 변동
# claude- 변동
모범 사례
일반 권장사항
모범 사례
// 1. 에러 처리
✓ 항상 try-except 사용
✓ 재시도 로직 구현 (지수 백오프)
✓ Rate Limit 에러 처리 (429)
✓ 타임아웃 설정
// 2. 보안
✓ API 키 환경 변수 관리
✓ 서버 사이드에서만 호출
✓ HTTPS 필수
✓ 로그에 민감 정보 제외
// 3. 성능
✓ 스트리밍으로 UX 개선
✓ 프롬프트 캐싱 적극 활용
✓ 적절한 max_tokens 설정
✓ 비동기 처리 (asyncio)
// 4. 비용
✓ 작업에 맞는 모델 선택
✓ 토큰 사용량 모니터링
✓ 불필요한 컨텍스트 제거
✓ 캐싱 가능한 부분 식별
// 5. 품질
✓ 명확한 시스템 프롬프트
✓ Few-shot 예시 제공
✓ 출력 포맷 명시
✓ 다양한 입력으로 테스트
핵심 정리
- Claude API 가이드의 핵심 개념과 흐름을 정리합니다.
- Claude API 개요를 단계별로 이해합니다.
- 실전 적용 시 기준과 주의점을 확인합니다.
실무 팁
- 입력/출력 예시를 고정해 재현성을 확보하세요.
- Claude API 가이드 범위를 작게 잡고 단계적으로 확장하세요.
- Claude API 개요 조건을 문서화해 대응 시간을 줄이세요.