Claude API 완전 가이드 | Anthropic SDK 실전 사용법·요금·함수 호출

Claude API 완전 가이드 | Anthropic SDK 실전 사용법·요금·함수 호출

이 글의 핵심

Claude API는 Anthropic이 제공하는 대화형 AI API입니다. OpenAI API와 유사하지만 더 긴 컨텍스트(200K 토큰), 강력한 프롬프트 캐싱, 뛰어난 코드 생성 능력이 특징입니다.

Claude API란?

Claude API는 Anthropic이 제공하는 대화형 AI API입니다. GPT-4, Gemini와 함께 2026년 현재 가장 많이 사용되는 LLM API 중 하나로, 특히 긴 문서 처리, 코드 작성, 안전성에서 강점을 보입니다.

이 글에서는 Claude API를 실무에 바로 적용할 수 있도록 API 키 발급부터 고급 기능까지 Python과 TypeScript 예제로 설명합니다.

# 30초 만에 시작하는 Claude API
import anthropic

client = anthropic.Anthropic(api_key="your-api-key")

message = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Python으로 피보나치 수열 구현해줘"}]
)
print(message.content[0].text)

목차

  1. 모델 비교 및 요금
  2. API 키 발급
  3. SDK 설치
  4. 기본 메시지 API
  5. 스트리밍
  6. 시스템 프롬프트
  7. 멀티턴 대화
  8. Tool Use (함수 호출)
  9. Vision (이미지 입력)
  10. 프롬프트 캐싱
  11. 실전 패턴: 오류 처리 & 재시도

모델 비교 및 요금

모델컨텍스트입력 ($/MTok)출력 ($/MTok)특징
claude-haiku-4-5200K$0.80$4.00가장 빠름, 저비용
claude-sonnet-4-5200K$3.00$15.00균형잡힌 성능
claude-opus-4-5200K$15.00$75.00최고 성능
claude-sonnet-4-6200K$3.00$15.00최신, 향상된 추론

실무 팁: 개발/테스트는 Haiku, 프로덕션은 Sonnet을 사용하면 비용을 크게 절감할 수 있습니다.


API 키 발급

  1. console.anthropic.com 접속
  2. 계정 생성 (Google/GitHub 로그인 가능)
  3. API KeysCreate Key
  4. 키 복사 후 안전하게 보관 (재확인 불가)
# .env 파일에 저장
ANTHROPIC_API_KEY=sk-ant-api03-...

SDK 설치

Python

pip install anthropic

TypeScript / Node.js

npm install @anthropic-ai/sdk
# 또는
pnpm add @anthropic-ai/sdk

기본 메시지 API

Python

필요한 모듈을 임포트하고 초기 설정을 진행합니다.

import anthropic

client = anthropic.Anthropic()  # ANTHROPIC_API_KEY 환경변수 자동 사용

message = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=1024,
    messages=[
        {"role": "user", "content": "대한민국의 수도는 어디인가요?"}
    ]
)

# 응답 구조
print(message.content[0].text)  # 서울입니다.
print(message.model)             # claude-sonnet-4-5
print(message.usage)             # 토큰 사용량

TypeScript

TypeScript/JavaScript 예제 코드입니다.

import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic();

const message = await client.messages.create({
  model: "claude-sonnet-4-5",
  max_tokens: 1024,
  messages: [{ role: "user", content: "대한민국의 수도는 어디인가요?" }],
});

console.log(message.content[0].type === "text" ? message.content[0].text : "");

응답 객체 구조

설정 파일 예시입니다.

{
  "id": "msg_01XFDUDYJgAACzvnptvVoYEL",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "서울입니다."
    }
  ],
  "model": "claude-sonnet-4-5",
  "stop_reason": "end_turn",
  "usage": {
    "input_tokens": 14,
    "output_tokens": 5
  }
}

스트리밍

대화형 앱에서 실시간 응답을 표시할 때 필수입니다.

Python (동기)

필요한 모듈을 임포트하고 초기 설정을 진행합니다.

import anthropic

client = anthropic.Anthropic()

with client.messages.stream(
    model="claude-sonnet-4-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Python의 GIL에 대해 설명해줘"}]
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)
    
    # 완료 후 최종 메시지 객체 접근
    final_message = stream.get_final_message()
    print(f"\n\n총 토큰: {final_message.usage.input_tokens + final_message.usage.output_tokens}")

Python (비동기)

아래는 stream_response 함수 구현 예제입니다. 위에서 설명한 핵심 로직을 담고 있습니다.

import asyncio
import anthropic

client = anthropic.AsyncAnthropic()

async def stream_response():
    async with client.messages.stream(
        model="claude-sonnet-4-5",
        max_tokens=1024,
        messages=[{"role": "user", "content": "비동기 프로그래밍이란?"}]
    ) as stream:
        async for text in stream.text_stream:
            print(text, end="", flush=True)

asyncio.run(stream_response())

TypeScript (스트리밍)

TypeScript/JavaScript 예제 코드입니다.

import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic();

const stream = await client.messages.stream({
  model: "claude-sonnet-4-5",
  max_tokens: 1024,
  messages: [{ role: "user", content: "JavaScript의 이벤트 루프를 설명해줘" }],
});

for await (const chunk of stream) {
  if (
    chunk.type === "content_block_delta" &&
    chunk.delta.type === "text_delta"
  ) {
    process.stdout.write(chunk.delta.text);
  }
}

시스템 프롬프트

모델의 역할과 행동 방식을 정의합니다.

필요한 모듈을 임포트하고 초기 설정을 진행합니다.

import anthropic

client = anthropic.Anthropic()

message = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=1024,
    system="""당신은 10년 경력의 시니어 백엔드 개발자입니다.
    - Python, Go, Rust에 능숙합니다
    - 성능 최적화와 시스템 설계를 중시합니다
    - 코드 리뷰 시 실용적이고 구체적인 피드백을 제공합니다
    - 한국어로 답변합니다""",
    messages=[
        {"role": "user", "content": "이 Django 코드의 N+1 쿼리 문제를 해결해줘:\n\n```python\ndef get_posts():\n    posts = Post.objects.all()\n    return [(p.title, p.author.name) for p in posts]\n```"}
    ]
)

print(message.content[0].text)

멀티턴 대화

대화 히스토리를 관리하여 맥락 있는 대화를 구현합니다.

import anthropic

client = anthropic.Anthropic()

conversation_history = []

def chat(user_message: str) -> str:
    conversation_history.append({
        "role": "user",
        "content": user_message
    })
    
    response = client.messages.create(
        model="claude-sonnet-4-5",
        max_tokens=2048,
        system="당신은 친절한 프로그래밍 튜터입니다.",
        messages=conversation_history
    )
    
    assistant_message = response.content[0].text
    conversation_history.append({
        "role": "assistant",
        "content": assistant_message
    })
    
    return assistant_message

# 대화 예시
print(chat("Python이란 무엇인가요?"))
print(chat("방금 설명한 Python으로 Hello World를 출력해줘"))
print(chat("거기서 변수를 추가해줘"))

Tool Use (함수 호출)

Claude가 외부 함수를 호출하여 실시간 정보를 처리할 수 있게 합니다.

import anthropic
import json
from datetime import datetime

client = anthropic.Anthropic()

# 도구 정의
tools = [
    {
        "name": "get_weather",
        "description": "특정 도시의 현재 날씨 정보를 가져옵니다",
        "input_schema": {
            "type": "object",
            "properties": {
                "city": {
                    "type": "string",
                    "description": "날씨를 조회할 도시 이름 (예: Seoul, Tokyo)"
                },
                "unit": {
                    "type": "string",
                    "enum": ["celsius", "fahrenheit"],
                    "description": "온도 단위"
                }
            },
            "required": ["city"]
        }
    },
    {
        "name": "get_stock_price",
        "description": "주식 가격을 조회합니다",
        "input_schema": {
            "type": "object",
            "properties": {
                "ticker": {
                    "type": "string",
                    "description": "주식 티커 심볼 (예: AAPL, TSLA)"
                }
            },
            "required": ["ticker"]
        }
    }
]

# 실제 함수 구현
def get_weather(city: str, unit: str = "celsius") -> dict:
    # 실제로는 날씨 API 호출
    return {"city": city, "temperature": 22, "unit": unit, "condition": "맑음"}

def get_stock_price(ticker: str) -> dict:
    # 실제로는 주식 API 호출
    return {"ticker": ticker, "price": 180.50, "currency": "USD"}

def process_tool_call(tool_name: str, tool_input: dict) -> str:
    if tool_name == "get_weather":
        result = get_weather(**tool_input)
    elif tool_name == "get_stock_price":
        result = get_stock_price(**tool_input)
    else:
        result = {"error": f"Unknown tool: {tool_name}"}
    return json.dumps(result, ensure_ascii=False)

def chat_with_tools(user_message: str) -> str:
    messages = [{"role": "user", "content": user_message}]
    
    while True:
        response = client.messages.create(
            model="claude-sonnet-4-5",
            max_tokens=1024,
            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})
            
            tool_results = []
            for block in response.content:
                if block.type == "tool_use":
                    result = process_tool_call(block.name, block.input)
                    tool_results.append({
                        "type": "tool_result",
                        "tool_use_id": block.id,
                        "content": result
                    })
            
            messages.append({"role": "user", "content": tool_results})

# 실행
print(chat_with_tools("서울 날씨와 애플 주가를 알려줘"))

Vision (이미지 입력)

Claude는 이미지를 이해하고 분석할 수 있습니다.

import anthropic
import base64
from pathlib import Path

client = anthropic.Anthropic()

# 방법 1: Base64 인코딩
def analyze_image_file(image_path: str, question: str) -> str:
    image_data = Path(image_path).read_bytes()
    base64_image = base64.standard_b64encode(image_data).decode("utf-8")
    
    # 확장자로 media type 결정
    ext = Path(image_path).suffix.lower()
    media_types = {".jpg": "image/jpeg", ".png": "image/png", 
                   ".gif": "image/gif", ".webp": "image/webp"}
    media_type = media_types.get(ext, "image/jpeg")
    
    message = client.messages.create(
        model="claude-sonnet-4-5",
        max_tokens=1024,
        messages=[
            {
                "role": "user",
                "content": [
                    {
                        "type": "image",
                        "source": {
                            "type": "base64",
                            "media_type": media_type,
                            "data": base64_image,
                        },
                    },
                    {"type": "text", "text": question}
                ],
            }
        ],
    )
    return message.content[0].text

# 방법 2: URL (공개 이미지)
def analyze_image_url(image_url: str, question: str) -> str:
    message = client.messages.create(
        model="claude-sonnet-4-5",
        max_tokens=1024,
        messages=[
            {
                "role": "user",
                "content": [
                    {
                        "type": "image",
                        "source": {"type": "url", "url": image_url},
                    },
                    {"type": "text", "text": question}
                ],
            }
        ],
    )
    return message.content[0].text

# 사용 예
result = analyze_image_file("screenshot.png", "이 에러 메시지가 무엇을 의미하나요?")
print(result)

프롬프트 캐싱

반복적으로 사용되는 긴 컨텍스트의 비용을 최대 90% 절감합니다.

import anthropic

client = anthropic.Anthropic()

# 긴 시스템 프롬프트나 문서를 캐싱
LARGE_DOCUMENT = """
[매우 긴 기술 문서 내용 - 5000+ 토큰...]
"""  # 실제로는 수천 토큰의 문서

def ask_about_document(question: str) -> str:
    message = client.messages.create(
        model="claude-sonnet-4-5",
        max_tokens=1024,
        system=[
            {
                "type": "text",
                "text": "당신은 기술 문서 전문가입니다. 다음 문서를 바탕으로 질문에 답변하세요.",
            },
            {
                "type": "text",
                "text": LARGE_DOCUMENT,
                "cache_control": {"type": "ephemeral"}  # 캐싱 활성화 (5분)
            }
        ],
        messages=[{"role": "user", "content": question}]
    )
    
    # 캐시 히트 여부 확인
    usage = message.usage
    print(f"입력 토큰: {usage.input_tokens}")
    print(f"캐시 생성: {getattr(usage, 'cache_creation_input_tokens', 0)}")
    print(f"캐시 읽기: {getattr(usage, 'cache_read_input_tokens', 0)}")
    
    return message.content[0].text

# 첫 번째 호출: 캐시 생성
print(ask_about_document("이 문서의 주요 내용을 요약해줘"))

# 두 번째 호출: 캐시 히트 (비용 90% 절감)
print(ask_about_document("이 문서에서 성능 최적화 방법은?"))

실전 패턴: 오류 처리 & 재시도

import anthropic
import time
from typing import Optional

client = anthropic.Anthropic()

def create_message_with_retry(
    messages: list,
    model: str = "claude-sonnet-4-5",
    max_tokens: int = 1024,
    system: Optional[str] = None,
    max_retries: int = 3,
    base_delay: float = 1.0,
) -> str:
    """재시도 로직이 포함된 안정적인 API 호출"""
    
    for attempt in range(max_retries):
        try:
            kwargs = {
                "model": model,
                "max_tokens": max_tokens,
                "messages": messages,
            }
            if system:
                kwargs["system"] = system
            
            response = client.messages.create(**kwargs)
            return response.content[0].text
            
        except anthropic.RateLimitError as e:
            # 요청 한도 초과 - 지수 백오프
            if attempt < max_retries - 1:
                delay = base_delay * (2 ** attempt)
                print(f"요청 한도 초과. {delay}초 후 재시도 ({attempt + 1}/{max_retries})")
                time.sleep(delay)
            else:
                raise
                
        except anthropic.APIStatusError as e:
            if e.status_code == 529:  # 과부하
                if attempt < max_retries - 1:
                    delay = base_delay * (2 ** attempt)
                    print(f"서버 과부하. {delay}초 후 재시도")
                    time.sleep(delay)
                else:
                    raise
            else:
                raise  # 다른 오류는 즉시 전파
                
        except anthropic.APIConnectionError:
            if attempt < max_retries - 1:
                time.sleep(base_delay)
            else:
                raise

# 사용
result = create_message_with_retry(
    messages=[{"role": "user", "content": "안녕하세요!"}],
    system="You are a helpful assistant.",
)
print(result)

ChatGPT API vs Claude API 비교

항목Claude APIChatGPT API
최대 컨텍스트200K 토큰128K 토큰
프롬프트 캐싱✅ 지원 (90% 절감)❌ 미지원
코드 생성⭐⭐⭐⭐⭐⭐⭐⭐⭐
문서 분석⭐⭐⭐⭐⭐⭐⭐⭐⭐
JSON 모드
Vision
생태계성장 중매우 넓음
가격 (Sonnet 수준)$3/$15$5/$15

마치며

Claude API는 특히 긴 문서 처리, 코드 리뷰, 복잡한 추론 작업에서 탁월한 성능을 발휘합니다. 프롬프트 캐싱을 적극 활용하면 비용을 크게 절감할 수 있습니다.

다음 단계: