🤖 AI/ML

API

Application Programming Interface

소프트웨어 간 통신 규약. REST, GraphQL, gRPC 방식. 외부 서비스 연동의 핵심.

📖 상세 설명

API(Application Programming Interface)는 소프트웨어 간 상호작용을 위한 규약과 도구의 집합입니다. 웹 API의 경우 클라이언트가 서버에 HTTP 요청을 보내고, 서버가 JSON이나 XML 형식으로 응답을 반환하는 방식으로 동작합니다. 현대 소프트웨어는 API를 통해 결제, 인증, AI 모델 호출 등 다양한 기능을 외부 서비스에서 가져와 사용합니다.

API 아키텍처는 크게 REST, GraphQL, gRPC로 나뉩니다. REST는 HTTP 메서드(GET, POST, PUT, DELETE)를 활용하며 가장 널리 사용됩니다. GraphQL은 클라이언트가 필요한 데이터만 선택적으로 요청할 수 있어 오버페칭을 방지합니다. gRPC는 Protocol Buffers를 사용해 바이너리 통신으로 높은 성능을 제공하며, 마이크로서비스 간 통신에 주로 사용됩니다.

AI 분야에서 API는 모델 서빙의 핵심입니다. OpenAI, Anthropic, Google 등 AI 기업들은 API를 통해 모델을 제공하며, 개발자는 별도의 인프라 없이 최신 AI 기능을 애플리케이션에 통합할 수 있습니다. OpenAI API는 월 수천만 건의 요청을 처리하며, AI 서비스의 표준 제공 방식으로 자리잡았습니다.

API 설계에서 중요한 원칙은 일관성, 버전 관리, 명확한 문서화입니다. 좋은 API는 개발자가 직관적으로 이해하고 사용할 수 있어야 합니다. Rate Limiting, 인증, 에러 처리 등 운영적 측면도 중요하며, OpenAPI(Swagger) 같은 표준 문서화 도구를 활용하면 API 유지보수와 협업이 용이해집니다.

💻 코드 예제

"""
API 호출 예제 - OpenAI Chat Completions API
에러 처리, 재시도, 타임아웃을 포함한 프로덕션 패턴
"""

import os
import time
from openai import OpenAI
from tenacity import retry, stop_after_attempt, wait_exponential

# API 클라이언트 초기화
client = OpenAI(
    api_key=os.environ.get("OPENAI_API_KEY"),
    timeout=30.0,  # 30초 타임아웃
    max_retries=0  # tenacity로 직접 재시도 관리
)

@retry(
    stop=stop_after_attempt(3),
    wait=wait_exponential(multiplier=1, min=2, max=10)
)
def call_chat_api(messages: list, model: str = "gpt-4") -> dict:
    """
    OpenAI Chat API 호출 (재시도 로직 포함)

    Args:
        messages: 대화 메시지 리스트
        model: 사용할 모델 (기본값: gpt-4)

    Returns:
        API 응답 딕셔너리
    """
    start_time = time.time()

    try:
        response = client.chat.completions.create(
            model=model,
            messages=messages,
            temperature=0.7,
            max_tokens=1000
        )

        latency = time.time() - start_time

        return {
            "success": True,
            "content": response.choices[0].message.content,
            "model": response.model,
            "usage": {
                "prompt_tokens": response.usage.prompt_tokens,
                "completion_tokens": response.usage.completion_tokens,
                "total_tokens": response.usage.total_tokens
            },
            "latency_ms": round(latency * 1000, 2)
        }

    except Exception as e:
        return {
            "success": False,
            "error": str(e),
            "error_type": type(e).__name__
        }

# 사용 예시
messages = [
    {"role": "system", "content": "당신은 친절한 AI 어시스턴트입니다."},
    {"role": "user", "content": "API란 무엇인지 한 문장으로 설명해주세요."}
]

result = call_chat_api(messages)

if result["success"]:
    print(f"응답: {result['content']}")
    print(f"모델: {result['model']}")
    print(f"토큰 사용량: {result['usage']['total_tokens']}")
    print(f"응답 시간: {result['latency_ms']}ms")
else:
    print(f"오류 발생: {result['error_type']}")
    print(f"오류 메시지: {result['error']}")

🗣️ 실무 대화 예시

백엔드 아키텍처 설계 미팅에서

"OpenAI API의 Rate Limit이 분당 3,500 요청인데, 저희 예상 트래픽이 분당 5,000건입니다. API Gateway에서 요청을 큐잉하고, 서비스 계층에서 exponential backoff로 재시도하는 구조를 잡아야 합니다. 필요하면 OpenAI에 Rate Limit 증가를 요청할 수도 있습니다."

주니어 개발자 코드 리뷰에서

"API 호출할 때 타임아웃 설정이 없네요. 외부 서비스가 응답하지 않으면 스레드가 무한 대기하게 됩니다. 최소 30초 타임아웃을 설정하고, 에러 발생 시 적절한 fallback 응답을 반환하도록 수정해주세요."

API 설계 논의에서

"v1/users/{id} 엔드포인트의 응답에 민감한 정보가 포함되어 있어요. API 응답 필드를 최소화하고, 추가 정보가 필요하면 별도 엔드포인트로 분리합시다. 그리고 모든 엔드포인트에 rate limiting과 API 키 인증을 적용해야 합니다."

⚠️ 주의사항

⚠️
API 키 보안

API 키를 코드에 하드코딩하거나 Git에 커밋하면 안 됩니다. 환경 변수나 비밀 관리 서비스(AWS Secrets Manager, HashiCorp Vault)를 사용하고, 키가 유출되면 즉시 재발급하세요.

⚠️
Rate Limiting 대응

429 Too Many Requests 에러가 발생하면 무조건 재시도하지 말고, Retry-After 헤더를 확인하세요. Exponential backoff와 jitter를 적용하여 서버에 부하를 분산시켜야 합니다.

⚠️
API 의존성 리스크

외부 API에 강하게 의존하면 해당 서비스 장애 시 전체 시스템이 다운됩니다. Circuit Breaker 패턴, 캐싱, fallback 로직을 구현하여 부분 장애에도 서비스가 유지되도록 설계하세요.

🔗 관련 용어

📚 더 배우기