API 설계 기초
API(Application Programming Interface)는 서비스와 서비스, 클라이언트와 서버가 약속된 규칙으로 소통하는 인터페이스입니다. 잘 설계된 API는 사용하기 쉽고, 변경에 강하며, 확장이 자연스럽습니다. LLM을 서비스로 제공하든, ML 파이프라인을 자동화하든, 결국 API가 서비스의 얼굴입니다.학습 목표
- REST 설계 원칙을 이해하고 리소스 중심 URL을 설계할 수 있다
- REST, GraphQL, gRPC의 차이를 비교하고 적합한 상황을 판단할 수 있다
- OpenAPI 스펙을 이해하고 자동 문서화의 가치를 설명할 수 있다
- LLM API의 호출 패턴(스트리밍, 토큰 과금, SDK)을 이해한다
왜 중요한가
현대 소프트웨어는 API로 연결된 서비스의 네트워크입니다. 프론트엔드와 백엔드, 마이크로서비스 간, 외부 SaaS와의 연동 — 모두 API를 통합니다. AI/ML 분야에서는 이 경향이 더욱 두드러집니다. 모델 학습은 내부 API를 통해 오케스트레이션되고, 모델 서빙은 REST API로 노출되며, LLM 기능은 OpenAI 호환 API로 표준화되고 있습니다. 좋은 API 설계는 단순히 “동작하는” 수준이 아니라, **개발자 경험(DX)**을 고려한 설계입니다. 명확한 URL, 일관된 응답 형식, 충분한 에러 메시지 — 이것이 사용자가 여러분의 서비스를 선택하게 만드는 차이입니다.REST 설계 원칙
REST(Representational State Transfer)는 웹 API의 가장 보편적인 아키텍처 스타일입니다.핵심 원칙
| 원칙 | 설명 | 예시 |
|---|---|---|
| 리소스 중심 URL | URL은 동사가 아닌 명사(리소스)를 표현 | /users, /models/gpt-4o |
| HTTP 메서드 매핑 | 동작은 HTTP 메서드로 표현 | GET /users, POST /users |
| 무상태(Stateless) | 각 요청은 독립적, 서버가 클라이언트 상태를 저장하지 않음 | 모든 정보를 요청에 포함 |
| 통일된 인터페이스 | 일관된 URL 패턴과 응답 구조 | 모든 리소스가 같은 패턴 |
| HATEOAS | 응답에 관련 리소스 링크 포함 | "links": {"next": "/users?page=2"} |
리소스 URL 설계 패턴
REST vs GraphQL vs gRPC 비교
| 항목 | REST | GraphQL | gRPC |
|---|---|---|---|
| 엔드포인트 | 리소스별 다수 | 단일 엔드포인트 | 서비스별 메서드 |
| 데이터 선택 | 서버가 결정 (오버/언더페칭) | 클라이언트가 필드 선택 | 프로토콜 버퍼로 정의 |
| 프로토콜 | HTTP/1.1 + JSON | HTTP/1.1 + JSON | HTTP/2 + Protobuf (바이너리) |
| 성능 | 보통 | 보통 (N+1 주의) | 높음 (바이너리, 스트리밍) |
| 학습곡선 | 낮음 | 중간 | 높음 |
| 타입 안전성 | OpenAPI로 보완 | 스키마 내장 | Protobuf로 보장 |
| 스트리밍 | SSE, WebSocket | Subscription | 양방향 스트리밍 네이티브 |
| 적합 사례 | 범용 API, 외부 공개 API | 복잡한 데이터 관계, 모바일 | 마이크로서비스 간 통신 |
| AI/ML 활용 | 모델 서빙, LLM API | ML 메타데이터 조회 | 추론 서빙 (TensorFlow Serving) |
API 버전관리
API는 시간이 지나면 변경됩니다. 기존 사용자를 깨뜨리지 않으면서 발전시키는 것이 버전관리의 핵심입니다.OpenAPI와 Swagger
OpenAPI Specification(OAS)은 REST API를 기계가 읽을 수 있는 형식으로 기술하는 표준입니다.인증과 Rate Limiting
인증 방식 요약
| 방식 | 헤더 | 적합 상황 |
|---|---|---|
| API Key | X-API-Key: key123 또는 Authorization: Bearer key123 | 서버 간 통신, 간단한 인증 |
| Bearer Token (JWT) | Authorization: Bearer eyJhbG... | 사용자별 인증, 세션 관리 |
| OAuth 2.0 | Authorization: Bearer access_token | 제3자 서비스 연동, 사용자 동의 |
Rate Limiting 설계
LLM API 호출 패턴
스트리밍 (Server-Sent Events)
LLM은 토큰을 순차적으로 생성하므로, 전체 응답을 기다리지 않고 스트리밍으로 받을 수 있습니다.토큰 기반 과금
| 개념 | 설명 |
|---|---|
| Input Tokens | 프롬프트(시스템 + 사용자 메시지)의 토큰 수 |
| Output Tokens | 모델이 생성한 응답의 토큰 수 |
| max_tokens | 생성할 최대 출력 토큰 수 (비용/시간 제어) |
| 총 비용 | (input_tokens x input_price) + (output_tokens x output_price) |
max_tokens를 설정하지 않으면 모델이 자체 판단으로 생성을 멈출 때까지 토큰을 소비합니다.
비용과 응답 시간을 제어하려면 반드시 설정하세요.비동기 배치 처리
대량의 요청을 처리할 때는 비동기 + 배치가 효율적입니다.SDK vs HTTP 직접 호출
| 항목 | SDK (openai 패키지) | HTTP 직접 (requests) |
|---|---|---|
| 코드량 | 적음 | 많음 |
| 타입 안전성 | 자동 완성, 타입 힌트 | 없음 (수동 파싱) |
| 에러 처리 | 구조화된 예외 클래스 | 수동 상태코드 확인 |
| 재시도/백오프 | 내장 | 직접 구현 |
| 스트리밍 | 이터레이터 제공 | SSE 직접 파싱 |
| 유연성 | SDK 지원 범위 내 | 완전한 제어 |
| 디버깅 | 추상화되어 내부 확인 어려움 | 원시 요청/응답 확인 가능 |
에러 응답 설계
일관된 에러 형식은 클라이언트 개발자 경험을 크게 향상시킵니다.RFC 7807 Problem Details 형식
REST에서 리소스와 컬렉션의 차이
REST에서 리소스와 컬렉션의 차이
컬렉션은 리소스의 집합입니다:
/users, /models. 복수형 명사를 사용합니다.
리소스는 컬렉션의 개별 항목입니다: /users/123, /models/gpt-4o.
GET /users는 목록을 반환하고, GET /users/123은 특정 사용자를 반환합니다.
계층 관계는 URL 경로로 표현합니다: /users/123/orders (123번 사용자의 주문 목록).페이지네이션 설계 패턴
페이지네이션 설계 패턴
오프셋 기반:
?page=2&per_page=20 — 구현 간단하나 대량 데이터에서 성능 저하.
커서 기반: ?cursor=abc123&limit=20 — 일관된 성능, 실시간 데이터에 적합.
키셋 기반: ?after_id=100&limit=20 — DB 인덱스 활용 가능, 빠름.
응답에 반드시 total_count, has_more, next_cursor 메타데이터를 포함하세요.HATEOAS가 실무에서 잘 안 쓰이는 이유
HATEOAS가 실무에서 잘 안 쓰이는 이유
HATEOAS(Hypermedia as the Engine of Application State)는 응답에 다음 가능한 액션의 링크를 포함하는 원칙입니다.
이론적으로 API 탐색성이 좋지만, 실무에서는 클라이언트가 URL을 하드코딩하는 것이 대부분이라
링크를 따라가는 구현을 하는 경우가 드뭅니다. 대신 OpenAPI 문서가 그 역할을 대신합니다.
GitHub API처럼 부분적으로 채택하는 사례도 있습니다 (Link 헤더로 페이지네이션 링크 제공).
OpenAI 호환 API가 중요한 이유
OpenAI 호환 API가 중요한 이유
많은 LLM 서빙 도구(vLLM, Ollama, LiteLLM)가 OpenAI API 형식과 호환되는 엔드포인트를 제공합니다.
이는 클라이언트 코드 변경 없이 모델을 교체할 수 있게 해줍니다.
base_url만 바꾸면 OpenAI → 오픈소스 모델 → 사내 모델로 전환이 가능합니다.
이것이 API 표준화의 실질적인 가치입니다.API 에러 코드 체계 설계하기
API 에러 코드 체계 설계하기
상태코드만으로는 에러 원인을 구체적으로 파악하기 어렵습니다.
애플리케이션 수준의 에러 코드를 별도로 정의하면 디버깅이 쉬워집니다:
INVALID_API_KEY(401),RATE_LIMIT_EXCEEDED(429),MODEL_NOT_FOUND(404)CONTEXT_LENGTH_EXCEEDED(400),CONTENT_FILTER_TRIGGERED(400) OpenAI는error.code필드에invalid_api_key,model_not_found등을 반환합니다.
체크리스트
- REST의 리소스 중심 URL 설계 원칙을 따라 API를 설계할 수 있다
- REST, GraphQL, gRPC의 차이와 각각의 적합한 사용 상황을 설명할 수 있다
- API 버전관리 전략(URL 경로, 헤더, 쿼리)의 장단점을 비교할 수 있다
- FastAPI에서 OpenAPI 자동 문서화가 어떻게 작동하는지 이해한다
- Rate Limiting의 필요성과 429 응답 설계를 설명할 수 있다
- LLM API의 스트리밍 호출과 토큰 기반 과금 구조를 이해한다
- SDK와 HTTP 직접 호출의 장단점을 비교하여 상황에 맞게 선택할 수 있다
- RFC 7807 스타일의 일관된 에러 응답 형식을 설계할 수 있다

