API Development

Claude API 활용 튜토리얼: 첫 AI 애플리케이션 만들기

Anthropic의 Claude API를 활용하여 실제 동작하는 AI 애플리케이션을 처음부터 끝까지 만들어봅니다. Python과 TypeScript 예제를 포함한 완전한 실전 가이드입니다.

Claude는 Anthropic에서 개발한 대규모 언어 모델로, 안전성과 유용성에 중점을 둔 AI입니다. 이 튜토리얼에서는 Claude API를 사용하여 실제 애플리케이션을 만드는 방법을 단계별로 설명합니다. API 키 발급부터 실전 프로젝트 구현까지 모든 과정을 다룹니다.

1. 시작하기 전에

1.1 필요한 것들

  • Anthropic 계정 (API 키 발급용)
  • Python 3.8+ 또는 Node.js 16+
  • 기본적인 프로그래밍 지식
  • 터미널/명령 프롬프트 사용 경험
  • 텍스트 에디터 또는 IDE (VS Code 추천)

1.2 Claude API 특징

  • 높은 컨텍스트 윈도우: 최대 200,000 토큰 지원
  • 안전성: Constitutional AI 기반의 안전한 출력
  • 다양한 모델: Claude 3.5 Sonnet, Opus, Haiku 등
  • 멀티모달: 텍스트와 이미지 처리 가능
  • 스트리밍: 실시간 응답 생성

2. API 키 발급하기

Step 1: Anthropic Console 접속

  1. console.anthropic.com 방문
  2. 계정 생성 또는 로그인
  3. 이메일 인증 완료

Step 2: API 키 생성

  1. 좌측 메뉴에서 "API Keys" 선택
  2. "Create Key" 버튼 클릭
  3. 키 이름 입력 (예: "My First Project")
  4. 생성된 키를 안전한 곳에 복사 (한 번만 표시됨)

Step 3: 크레딧 확인

신규 가입 시 $5 상당의 무료 크레딧을 제공합니다. "Usage" 메뉴에서 잔액과 사용량을 확인할 수 있습니다.

중요: API 키는 절대 코드에 직접 포함하지 마세요. 환경 변수나 .env 파일을 사용하여 안전하게 관리하세요.

3. 환경 설정

3.1 Python 환경 설정

Step 1: 가상 환경 생성

# Windows
python -m venv venv
venv\Scripts\activate

# Mac/Linux
python3 -m venv venv
source venv/bin/activate

Step 2: 필수 패키지 설치

pip install anthropic python-dotenv

Step 3: .env 파일 생성

# .env
ANTHROPIC_API_KEY=your-api-key-here

3.2 TypeScript 환경 설정

Step 1: 프로젝트 초기화

mkdir claude-app
cd claude-app
npm init -y
npm install @anthropic-ai/sdk dotenv
npm install -D typescript @types/node tsx

Step 2: tsconfig.json 설정

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "lib": ["ES2020"],
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

Step 3: .env 파일 생성

# .env
ANTHROPIC_API_KEY=your-api-key-here

4. 첫 번째 API 호출

4.1 Python 기본 예제

# hello_claude.py
import os
from anthropic import Anthropic
from dotenv import load_dotenv

# 환경 변수 로드
load_dotenv()

# Claude 클라이언트 초기화
client = Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY"))

# 메시지 생성
message = client.messages.create(
    model="claude-3-5-sonnet-20241022",
    max_tokens=1024,
    messages=[
        {
            "role": "user",
            "content": "안녕하세요! Claude API 테스트 중입니다."
        }
    ]
)

# 응답 출력
print(message.content[0].text)

실행:

python hello_claude.py

4.2 TypeScript 기본 예제

// src/hello-claude.ts
import Anthropic from '@anthropic-ai/sdk';
import * as dotenv from 'dotenv';

dotenv.config();

const client = new Anthropic({
  apiKey: process.env.ANTHROPIC_API_KEY,
});

async function main() {
  const message = await client.messages.create({
    model: 'claude-3-5-sonnet-20241022',
    max_tokens: 1024,
    messages: [
      {
        role: 'user',
        content: '안녕하세요! Claude API 테스트 중입니다.',
      },
    ],
  });

  console.log(message.content[0].text);
}

main().catch(console.error);

실행:

npx tsx src/hello-claude.ts

5. 실전 프로젝트: AI 콘텐츠 분석기

이제 실제로 유용한 애플리케이션을 만들어보겠습니다. 텍스트를 분석하여 감정, 주요 키워드, 요약을 제공하는 콘텐츠 분석기를 구현합니다.

5.1 Python 구현

# content_analyzer.py
import os
import json
from typing import Dict, List
from anthropic import Anthropic
from dotenv import load_dotenv

load_dotenv()

class ContentAnalyzer:
    def __init__(self):
        self.client = Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY"))
        self.model = "claude-3-5-sonnet-20241022"

    def analyze(self, text: str) -> Dict:
        """
        텍스트를 분석하여 감정, 키워드, 요약을 반환합니다.

        Args:
            text: 분석할 텍스트

        Returns:
            분석 결과를 담은 딕셔너리
        """
        prompt = f"""다음 텍스트를 분석해주세요:

텍스트:
{text}

다음 형식의 JSON으로 응답해주세요:
{{
  "sentiment": "긍정적/부정적/중립적",
  "sentiment_score": 0.0-1.0 사이의 숫자,
  "keywords": ["키워드1", "키워드2", ...],
  "summary": "한 문장 요약",
  "main_topics": ["주제1", "주제2", ...]
}}"""

        try:
            message = self.client.messages.create(
                model=self.model,
                max_tokens=2048,
                messages=[{"role": "user", "content": prompt}]
            )

            response_text = message.content[0].text
            # JSON 파싱
            result = json.loads(response_text)
            return result

        except Exception as e:
            return {"error": str(e)}

    def batch_analyze(self, texts: List[str]) -> List[Dict]:
        """
        여러 텍스트를 일괄 분석합니다.

        Args:
            texts: 분석할 텍스트 리스트

        Returns:
            각 텍스트의 분석 결과 리스트
        """
        results = []
        for text in texts:
            result = self.analyze(text)
            results.append(result)
        return results

# 사용 예시
if __name__ == "__main__":
    analyzer = ContentAnalyzer()

    sample_text = """
    오늘 출시된 신제품이 정말 혁신적입니다.
    특히 사용자 인터페이스가 직관적이고,
    성능도 기대 이상입니다.
    다만 가격이 다소 높은 편이라는 점은 아쉽습니다.
    """

    result = analyzer.analyze(sample_text)
    print(json.dumps(result, indent=2, ensure_ascii=False))

5.2 스트리밍 응답 구현

실시간으로 응답을 받아 사용자 경험을 개선할 수 있습니다.

# streaming_example.py
import os
from anthropic import Anthropic
from dotenv import load_dotenv

load_dotenv()

client = Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY"))

def stream_response(prompt: str):
    """스트리밍 방식으로 응답을 받습니다."""
    with client.messages.stream(
        model="claude-3-5-sonnet-20241022",
        max_tokens=2048,
        messages=[{"role": "user", "content": prompt}]
    ) as stream:
        for text in stream.text_stream:
            print(text, end="", flush=True)
        print()  # 줄바꿈

# 사용 예시
if __name__ == "__main__":
    stream_response("AI의 미래에 대해 300자 정도로 설명해주세요.")

5.3 TypeScript 고급 예제: 대화 관리

// src/conversation-manager.ts
import Anthropic from '@anthropic-ai/sdk';
import * as dotenv from 'dotenv';

dotenv.config();

interface Message {
  role: 'user' | 'assistant';
  content: string;
}

class ConversationManager {
  private client: Anthropic;
  private messages: Message[] = [];
  private model = 'claude-3-5-sonnet-20241022';

  constructor() {
    this.client = new Anthropic({
      apiKey: process.env.ANTHROPIC_API_KEY,
    });
  }

  async sendMessage(userMessage: string): Promise {
    // 사용자 메시지 추가
    this.messages.push({
      role: 'user',
      content: userMessage,
    });

    try {
      const response = await this.client.messages.create({
        model: this.model,
        max_tokens: 2048,
        messages: this.messages,
      });

      const assistantMessage = response.content[0].text;

      // 어시스턴트 응답 저장
      this.messages.push({
        role: 'assistant',
        content: assistantMessage,
      });

      return assistantMessage;
    } catch (error) {
      console.error('Error:', error);
      throw error;
    }
  }

  getConversationHistory(): Message[] {
    return [...this.messages];
  }

  clearHistory(): void {
    this.messages = [];
  }

  async streamMessage(userMessage: string): Promise {
    this.messages.push({
      role: 'user',
      content: userMessage,
    });

    const stream = await this.client.messages.stream({
      model: this.model,
      max_tokens: 2048,
      messages: this.messages,
    });

    let fullResponse = '';

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

    console.log(); // 줄바꿈

    this.messages.push({
      role: 'assistant',
      content: fullResponse,
    });
  }
}

// 사용 예시
async function main() {
  const conversation = new ConversationManager();

  console.log('User: AI에 대해 간단히 설명해주세요.');
  const response1 = await conversation.sendMessage(
    'AI에 대해 간단히 설명해주세요.'
  );
  console.log('Assistant:', response1);

  console.log('\nUser: 실생활에서 어떻게 활용되나요?');
  await conversation.streamMessage('실생활에서 어떻게 활용되나요?');

  // 대화 기록 저장
  const history = conversation.getConversationHistory();
  console.log('\n=== 대화 기록 ===');
  console.log(JSON.stringify(history, null, 2));
}

main().catch(console.error);

6. 이미지 분석 기능 추가

Claude는 이미지를 분석할 수 있는 멀티모달 기능을 제공합니다.

6.1 이미지 분석 Python 예제

# image_analyzer.py
import os
import base64
from anthropic import Anthropic
from dotenv import load_dotenv

load_dotenv()

class ImageAnalyzer:
    def __init__(self):
        self.client = Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY"))

    def analyze_image(self, image_path: str, question: str = "이 이미지에 무엇이 있나요?") -> str:
        """
        이미지를 분석합니다.

        Args:
            image_path: 이미지 파일 경로
            question: 이미지에 대한 질문

        Returns:
            분석 결과
        """
        # 이미지를 base64로 인코딩
        with open(image_path, "rb") as image_file:
            image_data = base64.standard_b64encode(image_file.read()).decode("utf-8")

        # 파일 확장자로 미디어 타입 결정
        ext = image_path.lower().split('.')[-1]
        media_type_map = {
            'jpg': 'image/jpeg',
            'jpeg': 'image/jpeg',
            'png': 'image/png',
            'gif': 'image/gif',
            'webp': 'image/webp'
        }
        media_type = media_type_map.get(ext, 'image/jpeg')

        message = self.client.messages.create(
            model="claude-3-5-sonnet-20241022",
            max_tokens=2048,
            messages=[
                {
                    "role": "user",
                    "content": [
                        {
                            "type": "image",
                            "source": {
                                "type": "base64",
                                "media_type": media_type,
                                "data": image_data,
                            },
                        },
                        {
                            "type": "text",
                            "text": question
                        }
                    ],
                }
            ],
        )

        return message.content[0].text

# 사용 예시
if __name__ == "__main__":
    analyzer = ImageAnalyzer()
    result = analyzer.analyze_image(
        "screenshot.png",
        "이 이미지에서 UI/UX 개선점을 제안해주세요."
    )
    print(result)

7. 에러 처리와 모범 사례

7.1 안전한 API 호출

# robust_api_call.py
import os
import time
from anthropic import Anthropic, APIError, RateLimitError
from dotenv import load_dotenv

load_dotenv()

class RobustClaudeClient:
    def __init__(self, max_retries: int = 3):
        self.client = Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY"))
        self.max_retries = max_retries

    def call_with_retry(self, messages: list, **kwargs) -> str:
        """
        재시도 로직이 포함된 API 호출
        """
        for attempt in range(self.max_retries):
            try:
                response = self.client.messages.create(
                    model="claude-3-5-sonnet-20241022",
                    max_tokens=2048,
                    messages=messages,
                    **kwargs
                )
                return response.content[0].text

            except RateLimitError as e:
                if attempt < self.max_retries - 1:
                    wait_time = 2 ** attempt  # 지수 백오프
                    print(f"Rate limit 도달. {wait_time}초 후 재시도...")
                    time.sleep(wait_time)
                else:
                    raise

            except APIError as e:
                print(f"API 에러: {e}")
                if attempt < self.max_retries - 1:
                    time.sleep(1)
                else:
                    raise

    def validate_input(self, text: str, max_length: int = 100000) -> bool:
        """
        입력 검증
        """
        if not text or not text.strip():
            raise ValueError("빈 텍스트는 처리할 수 없습니다.")

        if len(text) > max_length:
            raise ValueError(f"텍스트가 너무 깁니다. (최대: {max_length}자)")

        return True

# 사용 예시
if __name__ == "__main__":
    client = RobustClaudeClient()

    try:
        user_input = "안녕하세요!"
        client.validate_input(user_input)

        result = client.call_with_retry([
            {"role": "user", "content": user_input}
        ])
        print(result)

    except Exception as e:
        print(f"처리 중 오류 발생: {e}")

7.2 비용 최적화 팁

  • 적절한 모델 선택: 간단한 작업은 Claude 3 Haiku 사용
  • max_tokens 제한: 필요한 만큼만 토큰 사용
  • 캐싱 활용: 동일한 요청은 결과를 캐시
  • 배치 처리: 여러 요청을 하나로 묶어 처리
  • 스트리밍 사용: 사용자 경험 개선과 동시에 비용 절감

8. 프로덕션 배포 준비

8.1 환경 변수 관리

# config.py
import os
from dotenv import load_dotenv

load_dotenv()

class Config:
    ANTHROPIC_API_KEY = os.environ.get("ANTHROPIC_API_KEY")
    MODEL_NAME = os.environ.get("MODEL_NAME", "claude-3-5-sonnet-20241022")
    MAX_TOKENS = int(os.environ.get("MAX_TOKENS", "2048"))
    TEMPERATURE = float(os.environ.get("TEMPERATURE", "1.0"))

    @classmethod
    def validate(cls):
        if not cls.ANTHROPIC_API_KEY:
            raise ValueError("ANTHROPIC_API_KEY가 설정되지 않았습니다.")

        if cls.MAX_TOKENS < 1 or cls.MAX_TOKENS > 4096:
            raise ValueError("MAX_TOKENS는 1-4096 사이여야 합니다.")

        return True

8.2 로깅 구현

# logger_setup.py
import logging
from datetime import datetime

def setup_logger(name: str = "claude_app") -> logging.Logger:
    """
    애플리케이션 로거 설정
    """
    logger = logging.getLogger(name)
    logger.setLevel(logging.INFO)

    # 파일 핸들러
    fh = logging.FileHandler(f'logs/app_{datetime.now().strftime("%Y%m%d")}.log')
    fh.setLevel(logging.INFO)

    # 콘솔 핸들러
    ch = logging.StreamHandler()
    ch.setLevel(logging.WARNING)

    # 포매터
    formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
    )
    fh.setFormatter(formatter)
    ch.setFormatter(formatter)

    logger.addHandler(fh)
    logger.addHandler(ch)

    return logger

9. 트러블슈팅

문제 1: "Authentication Error"

원인: API 키가 올바르지 않거나 만료됨

해결:

  • .env 파일의 API 키 확인
  • Anthropic Console에서 키 상태 확인
  • 필요시 새 키 발급

문제 2: "Rate Limit Exceeded"

원인: API 호출 한도 초과

해결:

  • 재시도 로직에 지수 백오프 구현
  • 요청 빈도 줄이기
  • 배치 처리 활용

문제 3: "Invalid Request Error"

원인: 잘못된 파라미터 또는 형식

해결:

  • API 문서에서 파라미터 형식 확인
  • 모델명이 정확한지 확인
  • 메시지 구조가 올바른지 검증

10. 다음 단계

이제 기본기를 익혔으니 다음 단계로 나아갈 수 있습니다:

  1. Tool Use 구현: Claude가 외부 도구를 호출하도록 설정
  2. 웹 애플리케이션 통합: Flask/FastAPI 또는 Express와 통합
  3. 데이터베이스 연동: 대화 기록 저장 및 관리
  4. 프롬프트 엔지니어링: 더 효과적인 프롬프트 작성
  5. A/B 테스팅: 다양한 모델과 설정 비교
"API는 도구일 뿐입니다. 중요한 것은 그 도구로 어떤 가치를 창출하느냐입니다."

마치며

Claude API를 활용하면 강력한 AI 기능을 애플리케이션에 쉽게 통합할 수 있습니다. 이 튜토리얼에서 배운 기본기를 바탕으로 자신만의 창의적인 AI 애플리케이션을 만들어보세요. 시작이 반입니다!

참고 자료

Tags: Claude API Anthropic Python TypeScript 튜토리얼

Related Posts