API Styles
API(애플리케이션 프로그래밍 인터페이스) 스타일은 시스템 간 통신 방식을 결정하는 중요한 설계 패턴으로, 다양한 시스템과 장치가 서로 디지털적으로 통신할 수 있도록 연결해주는 역할을 한다. API 스타일은 API가 외부 세계와 상호작용하는 방식을 결정하는 중요한 요소이다.
API 스타일은 크게 다섯 가지로 분류할 수 있다:
- 리소스 스타일 (Resource Style)
- 하이퍼미디어 스타일 (Hypermedia Style)
- 쿼리 스타일 (Query Style)
- 터널 스타일 (Tunnel Style)
- 이벤트 기반 스타일 (Event-based Style)
각 스타일은 고유한 강점과 약점을 가지고 있으며, 적절한 API 스타일 선택은 해결하려는 문제, API 소비자, 그리고 API가 사용되는 컨텍스트에 따라 달라진다.
API Style의 간략 비교
스타일 | 핵심 개념 | 목적 | 특징 | 주요 원리 및 작동 원리 |
---|---|---|---|---|
리소스 스타일 | 리소스 중심의 CRUD 작업 | 단순하고 직관적인 데이터 조작 | HTTP 메서드 사용, URI 기반 리소스 식별 | 클라이언트가 URI를 통해 리소스에 접근하고, HTTP 메서드를 통해 조작 |
하이퍼미디어 스타일 | 리소스 간의 링크를 통한 상태 전이 | 클라이언트와 서버의 결합도 감소 | HATEOAS 원칙 준수, 동적인 탐색 가능 | 응답에 포함된 링크를 통해 클라이언트가 다음 가능한 작업을 탐색 |
쿼리 스타일 | 클라이언트가 필요한 데이터만 요청 | 효율적인 데이터 전송 | 쿼리 언어 사용, 정밀한 데이터 요청 가능 | 클라이언트가 쿼리를 정의하여 서버에 요청, 서버는 해당 데이터만 응답 |
터널 스타일 | 원격 프로시저 호출(RPC)을 통한 기능 호출 | 고성능, 경량 통신 | 바이너리 포맷 사용, 스트리밍 지원 | 클라이언트가 함수를 호출하듯이 서버의 기능을 원격으로 실행 |
이벤트 기반 스타일 | 이벤트를 기반으로 비동기 통신 | 실시간 데이터 처리, 확장성 제공 | 메시지 브로커 사용, 낮은 결합도 | 이벤트 발생 시 이를 브로커에 발행, 구독자는 해당 이벤트를 처리 |
리소스 스타일 (Resource Style)
핵심 개념과 목적:
- 리소스 중심의 접근 방식으로, 데이터와 기능을 리소스로 모델링
- 목적: 클라이언트가 리소스를 직접 조작할 수 있는 인터페이스 제공
특징:
REST(Representational State Transfer) 아키텍처 기반
리소스를 URI로 식별하고 HTTP 메서드(GET, POST, PUT, DELETE)를 통해 리소스 조작
상태 없는(Stateless) 통신 방식
균일한 인터페이스 제공
작동 원리:
클라이언트가 리소스의 URI에 HTTP 요청을 보냄
서버는 요청된 리소스의 상태를 표현하는 응답(주로 JSON 형식)을 반환
클라이언트는 응답을 처리하고 필요에 따라 추가 요청을 수행
구성 요소:
리소스(URI로 식별됨)
HTTP 메서드(동작 정의)
표현 형식(주로 JSON, 과거에는 XML)
상태 코드(응답 상태 표시)
리소스 스타일 (REST) 아키텍처:
- 클라이언트가 서버의 리소스에 직접 접근하여 조작
주요 기능:
- OpenAPI를 통한 API 문서화
- 캐싱 가능
- 자원 기반 접근법으로 직관적인 사용
하이퍼미디어 스타일 (Hypermedia Style)
핵심 개념과 목적:
리소스 스타일의 확장으로, 리소스 간 탐색을 위한 링크 제공
목적: 클라이언트가 API를 동적으로 탐색할 수 있도록 하여 유연성 증가
특징:
HATEOAS(Hypermedia As The Engine Of Application State) 원칙 적용
응답에 관련 리소스 링크 포함
클라이언트가 API 구조를 사전에 알 필요가 없음
작동 원리:
클라이언트가 초기 진입점에 요청
서버는 리소스와 함께 관련 작업에 대한 링크 제공
클라이언트는 제공된 링크를 통해 다음 단계 리소스 접근
구성 요소:
- 리소스(URI로 식별)
- 하이퍼링크(다음 가능한 작업 안내)
- 링크 관계(rel 속성)
- 표현 형식(주로 JSON 또는 HAL, JSON-LD 등)
하이퍼미디어 스타일 아키텍처:
- 클라이언트가 응답에 포함된 링크를 따라 상태 전이
|
|
주요 기능:
- API 발견 가능성(discoverability) 향상
- 클라이언트와 서버 간 결합도 감소
- 워크플로우 표현 가능
쿼리 스타일 (Query Style)
핵심 개념과 목적:
- 단일 진입점을 통해 다양한 리소스에 접근
- 목적: 클라이언트가 필요한 데이터를 정확히 요청할 수 있도록 함
특징:
구조화된 형태의 리소스 관리
데이터베이스 쿼리와 유사한 접근 방식
단일 요청으로 복합적인 데이터 검색 가능
작동 원리:
- 클라이언트가 단일 엔드포인트에 쿼리 전송
- 서버는 쿼리를 해석하여 필요한 데이터 검색
- 응답으로 요청된 데이터 구조 반환
구성 요소:
- 단일 엔드포인트
- 쿼리 언어(예: GraphQL)
- 스키마(가능한 쿼리 정의)
- 리졸버(데이터 검색 로직)
쿼리 스타일 (GraphQL) 아키텍처:
- 클라이언트가 쿼리를 정의하여 서버에 요청, 서버는 해당 데이터만 응답
주요 기능:
오버페칭(over-fetching)과 언더페칭(under-fetching) 문제 해결
단일 요청으로 복잡한 데이터 구조 검색
클라이언트 맞춤형 응답 구조
터널 스타일 (Tunnel Style)
핵심 개념과 목적:
- 원격 함수 호출을 통한 API 구현
- 목적: 로컬 프로그래밍의 확장으로서 간편한 API 생성
특징:
- RPC(Remote Procedure Call) 방식 사용
- 함수 중심적 접근
- 개발자 친화적
작동 원리:
- 클라이언트가 서버의 특정 함수 호출 요청
- 서버는 요청된 함수 실행 후 결과 반환
- 프로시저 호출과 유사한 방식으로 작동
구성 요소:
- 서비스 정의(함수 명세)
- 직렬화 메커니즘(예: Protocol Buffers)
- 전송 프로토콜(예: HTTP/2)
- 클라이언트/서버 스텁(stub) 코드
터널 스타일 아키텍처
- 클라이언트가 서버의 함수를 원격으로 호출
주요 기능:
효율적인 바이너리 전송
강력한 타입 시스템
양방향 스트리밍 지원
이벤트 기반 스타일 (Event-based Style)
핵심 개념과 목적:
- 이벤트 생성 및 구독 기반 통신
- 목적: 비동기 통신을 통한 시스템 간 느슨한 결합
특징:
- 푸시 기반 통신 모델
- 생산자/소비자 패턴
- 비동기적 작동
작동 원리:
- 이벤트 생산자가 이벤트 발생 시 메시지 브로커에 이벤트 발행
- 메시지 브로커가 이벤트를 구독자에게 전달
- 구독자는 자신이 관심 있는 이벤트 유형만 처리
구성 요소:
- 이벤트 생산자
- 이벤트 소비자
- 메시지 브로커(예: Apache Kafka)
- 이벤트 형식 및 스키마
이벤트 기반 스타일 아키텍처:
- 이벤트 발행자가 이벤트를 브로커에 발행, 구독자는 해당 이벤트를 처리
주요 기능:
- 실시간 데이터 처리
- 시스템 간 느슨한 결합
- 확장성 있는 아키텍처 구성
실무에서 고려사항 및 주의할 점
리소스 스타일 (Resource Style)
고려사항:
- 리소스 모델링: 비즈니스 개체를 적절한 리소스로 정의하는 것이 중요
- URI 설계: 명확하고 일관된 명명 규칙 필요
- 버전 관리: API 변경 시 하위 호환성 관리 필요
- 보안: 인증 및 권한 부여 메커니즘 구현 필요
주의할 점:
과도한 요청: 복잡한 작업에 여러 요청이 필요할 수 있음
리소스 간 관계 표현의 어려움
비동기 작업 처리가 어려울 수 있음
클라이언트 요구에 맞는 응답 구조 제공의 한계
하이퍼미디어 스타일 (Hypermedia Style)
고려사항:
- 링크 관계 설계: 명확한 링크 의미와 관계 정의 필요
- 미디어 타입 선택: 적절한 하이퍼미디어 형식 선택(HAL, JSON-LD 등)
- 클라이언트 구현 복잡성: 클라이언트가 링크 기반 탐색 처리 필요
주의할 점:
- 과도한 정보: 너무 많은 링크가 응답 크기 증가 가능
- “챗티(chatty)” API: 정보 획득을 위해 여러 요청 필요 가능
- 클라이언트 개발 복잡성 증가
- 캐싱 전략이 더 복잡해질 수 있음
쿼리 스타일 (Query Style)
고려사항:
- 스키마 설계: 명확한 데이터 모델과 관계 정의 필요
- 성능 최적화: 복잡한 쿼리 처리를 위한 최적화 필요
- 권한 관리: 데이터 접근 제어 메커니즘 필요
주의할 점:
- 쿼리 복잡성: 클라이언트가 데이터 모델을 이해해야 함
- 캐싱 어려움: 동적 쿼리로 인한 캐싱 전략 복잡성
- 속도 제한(rate limiting) 구현의 어려움
- 보안 위험: 과도하게 복잡한 쿼리가 서버 리소스 소모 가능
터널 스타일 (Tunnel Style)
고려사항:
- 서비스 정의: 명확한 함수 인터페이스 설계 필요
- 직렬화 효율성: 효율적인 데이터 교환 형식 선택
- 언어 간 호환성: 다양한 클라이언트 언어 지원 고려
주의할 점:
- 유지보수 어려움: REST API보다 업데이트와 유지관리가 어려움
- 브라우저 지원 제한: 특수 클라이언트 라이브러리 필요
- 디버깅 복잡성: 바이너리 형식으로 인한 디버깅 어려움
- 게이트웨이와 프록시 통합 문제 가능
이벤트 기반 스타일 (Event-based Style)
고려사항:
- 이벤트 모델링: 명확한 이벤트 유형과 구조 정의 필요
- 메시지 브로커 선택: 적절한 메시징 시스템 선택(Kafka, RabbitMQ 등)
- 이벤트 순서 보장: 필요 시 이벤트 순서 보장 메커니즘 구현
주의할 점:
- 구현 복잡성: 다른 스타일보다 구현 시간이 더 소요됨
- 중복 메시지: 잘못 설계 시 중복 메시지 발생 가능
- 오류 처리의 어려움: 비동기 특성으로 인한 오류 추적 복잡성
- 디버깅과 모니터링 어려움: 이벤트 흐름 추적이 어려울 수 있음
API 스타일 비교
기본 특성 비교
특성 | 리소스 기반 | 하이퍼미디어 기반 | 쿼리 기반 | 터널 기반 | 이벤트 기반 |
---|---|---|---|---|---|
중심 개념 | 리소스(명사) | 링크와 상태 전이 | 데이터 요청 | 프로시저/함수 | 이벤트와 알림 |
통신 패턴 | 요청-응답 | 요청-응답 | 요청-응답 | 요청-응답 | 발행-구독 |
상태 관리 | 무상태 | 하이퍼미디어 상태 | 무상태 | 무상태/상태 가능 | 이벤트 스트림 |
대표 구현 | REST | HATEOAS, HAL | GraphQL, OData | SOAP, JSON-RPC, gRPC | WebSocket, MQTT, Kafka |
주요 사용 사례 | 웹 API, 모바일 백엔드 | 워크플로우 기반 앱 | 데이터 집약적 앱 | 프로시저 중심 시스템 | 실시간 앱, IoT |
기술적 특성 비교
특성 | 리소스 기반 | 하이퍼미디어 기반 | 쿼리 기반 | 터널 기반 | 이벤트 기반 |
---|---|---|---|---|---|
데이터 형식 | JSON, XML | HAL, JSON-LD, Collection+JSON | JSON, GraphQL 스키마 | SOAP XML, Protocol Buffers | JSON, Avro, CloudEvents |
통신 프로토콜 | HTTP | HTTP | HTTP, WebSocket | HTTP, TCP/IP | WebSocket, MQTT, AMQP |
캐싱 용이성 | 높음 | 높음 | 중간 | 낮음 | 낮음 |
계약 정의 | OpenAPI, RAML | OpenAPI + 링크 | GraphQL 스키마, OData 메타데이터 | WSDL, Protobuf | AsyncAPI, CloudEvents |
타입 안전성 | 선택적 | 선택적 | 높음 | 매우 높음 | 다양함 |
개발 및 사용 측면 비교
측면 | 리소스 기반 | 하이퍼미디어 기반 | 쿼리 기반 | 터널 기반 | 이벤트 기반 |
---|---|---|---|---|---|
학습 곡선 | 낮음 | 중간 | 중간~높음 | 중간 | 중간~높음 |
개발자 친화성 | 높음 | 중간 | 높음 | 중간 | 중간 |
클라이언트 복잡성 | 낮음 | 중간 | 중간 | 중간~높음 | 높음 |
서버 복잡성 | 낮음 | 높음 | 높음 | 중간 | 높음 |
코드 생성 도구 | 많음 | 제한적 | 많음 | 풍부함 | 증가 중 |
성능 및 확장성 비교
측면 | 리소스 기반 | 하이퍼미디어 기반 | 쿼리 기반 | 터널 기반 | 이벤트 기반 |
---|---|---|---|---|---|
오버페칭 문제 | 있음 | 있음 | 없음/적음 | 중간 | 해당 없음 |
언더페칭 문제 | 있음 | 있음 | 없음/적음 | 중간 | 해당 없음 |
네트워크 효율성 | 중간 | 낮음 | 높음 | 중간~높음 | 높음 |
실시간 능력 | 제한적 | 제한적 | 구독으로 가능 | 제한적 | 기본 지원 |
대규모 확장성 | 좋음 | 좋음 | 좋음 | 좋음 | 매우 좋음 |
장단점 비교
API 스타일 | 장점 | 단점 |
---|---|---|
리소스 기반 | - 직관적이고 이해하기 쉬움 - HTTP 인프라와 완벽하게 통합 - 풍부한 도구 및 라이브러리 - 효과적인 캐싱 | - 오버페칭/언더페칭 문제 - 여러 리소스 조회에 비효율적 - 버전 관리 복잡성 |
하이퍼미디어 기반 | API 변경 시 클라이언트 영향 최소화 - 자연스러운 API 탐색 가능 - 워크플로우 중심 상호작용에 적합 | - 구현 복잡성 증가 - 대역폭 사용량 증가 - 클라이언트 구현 어려움 |
쿼리 기반 | - 클라이언트가 필요한 데이터만 요청 - 오버페칭/언더페칭 문제 해결 - 강력한 타입 시스템 | - 서버 구현 복잡성 - 캐싱 전략 복잡 - 쿼리 복잡도 관리 필요 |
터널 기반 | - 엄격한 계약과 타입 안전성 - 바이너리 직렬화로 높은 성능 - 양방향 스트리밍 지원 | HTTP 기능 활용도 낮음 - 클라이언트-서버 결합도 증가 - 브라우저 지원 제한적 |
이벤트 기반 | - 실시간 데이터 처리 - 시스템 간 느슨한 결합 - 비동기 처리로 확장성 향상 | - 복잡한 설계 및 디버깅 - 이벤트 순서 및 일관성 관리 - 초기 설정 복잡성 |
산업 및 사용 사례 비교
API 스타일 | 적합한 산업 | 주요 사용 사례 | 대표적 예시 |
---|---|---|---|
리소스 기반 | 웹 서비스, SaaS | CRUD 작업 중심 애플리케이션 | GitHub API, Twitter API |
하이퍼미디어 기반 | 금융, 워크플로우 중심 산업 | 복잡한 비즈니스 프로세스, 자기 발견형 API | PayPal API (HATEOAS 부분) |
쿼리 기반 | 데이터 집약적 서비스, 모바일 앱 | 대시보드, 분석 도구, 커스텀 보고서 | GitHub GraphQL API, Facebook GraphQL |
터널 기반 | 엔터프라이즈, 금융, 통신 | 마이크로서비스 간 통신, 레거시 시스템 통합 | Salesforce SOAP API, Google gRPC 서비스 |
이벤트 기반 | IoT, 실시간 애플리케이션, 게임 | 채팅 앱, 알림 시스템, 실시간 대시보드 | Slack의 실시간 메시징, IoT 장치 통신 |
API 스타일을 선택할 때 고려해야 할 주요 요소
주요 요소 | 설명 및 고려사항 |
---|---|
비즈니스/기술 요구 | 프로젝트 목적, 주요 기능, 활용 사례, 확장성 |
호환성 | 언어/플랫폼, 프로토콜, 데이터 포맷 |
보안 | 인증/인가, 암호화, 입력 검증, 속도 제한, CORS |
신뢰성/장애대응 | 장애 복구, 데이터 일관성, 중복 처리, DLQ |
유지보수/미래대비 | 버전 관리, 하위 호환성, 문서화, 커뮤니티 지원, 자동화 도구 |
성능/확장성 | 응답 속도, 캐싱, 비동기 처리, 부하 분산 |
운영 난이도 | 학습 곡선, 도입/운영 복잡성, 디버깅/모니터링 용이성 |
비용/라이선스 | 도구/서비스 비용, 라이선스 정책 |
데이터 일관성 | Strong/Eventually Consistency, 트랜잭션 관리 |
유연성 | 다양한 활용 사례 지원, 커스터마이징 가능성 |
API 스타일별 확장성 요소
스타일 | 확장성 강점 | 확장성 도전 과제 |
---|---|---|
리소스 | Stateless, 캐싱 용이 | Over-fetching 문제 |
쿼리 | 정밀한 데이터 요청 | 복잡 쿼리 성능 저하 |
터널 | 고성능 이진 통신 | 서비스 디스커버리 복잡성 |
이벤트 기반 | 생산자/소비자 독립 확장 | 이벤트 순서 관리 복잡성 |
하이퍼미디어 | 클라이언트-서버 결합도 감소 | “Chatty” API 위험 |
용어 정리
용어 | 설명 |
---|---|
API (애플리케이션 프로그래밍 인터페이스) | 소프트웨어 구성 요소가 서로 통신할 수 있도록 하는 메커니즘 |
REST (Representational State Transfer) | 로이 필딩이 제안한 분산 하이퍼미디어 시스템을 위한 아키텍처 스타일 |
HATEOAS (Hypermedia as the Engine of Application State) | 클라이언트가 하이퍼미디어 링크를 통해 동적으로 API를 탐색할 수 있게 하는 REST의 제약 조건 |
GraphQL | 클라이언트가 필요한 데이터 구조를 정확히 요청할 수 있는 쿼리 언어 |
RPC (Remote Procedure Call) | 원격 서버의 프로시저를 로컬 시스템에서 호출하는 것처럼 실행할 수 있게 하는 기술 |
gRPC | Google에서 개발한 오픈소스 RPC 프레임워크 |
Protocol Buffers | 구조화된 데이터를 직렬화하기 위한 바이너리 형식 메커니즘 |
HTTP/2 | HTTP 프로토콜의 두 번째 주요 버전으로, 성능 향상에 중점을 둠 |
WebSocket | 클라이언트와 서버 간 지속적인 양방향 연결을 제공하는 통신 프로토콜 |
SSE (Server-Sent Events) | 서버에서 클라이언트로 자동 업데이트를 보내는 기술 |
Webhook | 특정 이벤트가 발생할 때 알림을 제공하는 HTTP 콜백 |
Apache Kafka | 고성능 분산 스트리밍 플랫폼 |
Pub-Sub (Publish-Subscribe) | 발행자가 메시지를 특정 수신자에게 직접 보내지 않고 채널에 게시하면, 구독자가 관심 있는 채널에서 메시지를 수신하는 메시징 패턴 |
JSON (JavaScript Object Notation) | 데이터 교환을 위한 경량 텍스트 기반 형식 |
HAL (Hypertext Application Language) | JSON 또는 XML을 확장하여 하이퍼링크를 포함하는 형식 |
OpenAPI | RESTful API를 설계, 구축, 문서화하기 위한 사양 |
오버페칭 (Over-fetching) | 필요한 것보다 더 많은 데이터를 가져오는 현상 |
언더페칭 (Under-fetching) | 필요한 데이터를 가져오기 위해 여러 요청이 필요한 현상 |
직렬화 (Serialization) | 데이터 구조를 전송이나 저장에 적합한 형식으로 변환하는 과정 |
API 게이트웨이 | API 호출을 중개하고 라우팅, 변환, 모니터링 등의 추가 기능을 제공하는 서비스 |
마이크로서비스 | 작고 독립적인 서비스로 구성된 소프트웨어 아키텍처 접근 방식 |
AsyncAPI | 비동기 API를 위한 명세로, 이벤트 기반 아키텍처를 문서화하는 데 사용됨 |
CQRS (Command Query Responsibility Segregation) | 명령(데이터 변경)과 쿼리(데이터 조회)를 분리하는 아키텍처 패턴 |
Event Sourcing | 상태 변경을 이벤트 시퀀스로 저장하는 방식으로, 특정 시점의 상태를 재구성할 수 있음 |
Rate Limiting | API 사용량 제한 기능 |
DLQ | Dead Letter Queue. 처리 실패 이벤트를 별도 저장해 재처리하는 큐 |
Eventual Consistency | 분산 시스템에서 데이터가 결국에는 일관된 상태로 수렴하는 모델 |
참고 및 출처
- How to choose the right API style and technology for your software architecture
- Red Hat API 관리 솔루션
- REST API 설계 가이드
- GraphQL 공식 문서
- gRPC 공식 문서
- Apache Kafka 문서
- 마이크로서비스 아키텍처에서의 API 설계
- HATEOAS 원칙
- Red Hat Developer - API 아키텍처의 5가지 유형
- REST API와 HATEOAS
- AsyncAPI 이니셔티브
- 이벤트 기반 아키텍처 소개
- HAL 명세
- Martin Fowler - 이벤트 소싱
- JSON-RPC 2.0 명세
- dret.net - API 스타일 비교 PDF
- Apache APISIX - API 스타일 선택 방법