이번 글에서는 가장 널리 알려진 API 프로토콜을 살펴볼 예정입니다. 다양한 API 액세스 방식은 여러 가지 상황을 더 빠르고 효율적으로 처리하는데 도움이 될 수 있습니다.
API Protocol이란?
API 프로토콜은 서로 다른 소프트웨어 애플리케이션 간에 데이터를 주고받기 위한 규칙이나 형식을 정의하는 기술입니다. API는 응용 프로그램 간에 상호작용을 가능하게 하는 인터페이스인데, 이 상호작용이 어떻게 이루어질지 정의하는 것이 바로 프로토콜입니다. API 프로토콜은 클라이언트와 서버 간의 데이터 전송 방식을 규정하며, 이를 통해 통신이 일관되게 이루어지도록 돕습니다.
REST
REST는 Representational State Transfer의 약자로, 2000년에 Roy Fielding에 의해 만들어졌으며 가장 널리 사용되고 있습니다. URL 구조와 HTTP(Hypertext Transfer Protocol, 하이퍼텍스트 전송 프로토콜)에 기반한 인터페이스로 구현된 아키텍처 스타일입니다. stateless(상태 비저장)하고, 캐싱이 가능하며 규칙(convention)에 기반한 클라이언트-서버 상호 작용을 제공합니다.
REST는 URL을 통해 어떤 리소스를 사용할지 정하고 HTTP 메서드를 사용해 어떤 작업을 수행할지 표현합니다. HTTP 메서드는 다음과 같습니다.:
- GET: 기존 리소스 또는 여러 리소스를 가져오기
- POST: 새 리소스를 생성
- PUT: 리소스를 업데이트하거나 존재하지 않는 경우 생성
- DELETE: 리소스 삭제
- PATCH: 기존 리소스를 부분적으로 업데이트
REST의 가장 큰 장점은 기술 업계에서 가장 성숙한 API 아키텍처 스타일이라는 점입니다. REST 프로토콜은 HTTP를 지원하는 모든 프로그래밍 언어를 사용하여 구축할 수 있고 JSON 및 XML과 같은 다양한 데이터 형식을 지원하기 때문에 많은 개발자가 익숙하고 작업하기 쉽게 느껴집니다.
REST는 데이터를 나타내는 리소스와 URI(Uniform Resource Identifier)덕분에 변경이 용이합니다. 즉, 개발자는 기존 클라이언트 애플리케이션을 중단하지 않고도 API 구조를 변경할 수 있습니다. 이처럼 리소스가 고유 URL 뒤에 위치하기 때문에 API를 모니터링하고 속도를 제한하기가 쉽습니다.
또한 REST는 HTTP를 활용하여 캐싱을 간소화합니다. HTTP 응답을 캐싱하면 클라이언트와 서버가 서로 지속적으로 상호 작용할 필요가 없습니다. 이렇게 HTTP의 캐싱 및 로드 밸런싱 기능을 덕에 확장이 가능하고 분산된 시스템을 구축하는 데에도 적합합니다.
반면에 REST는 under-fetching과 over-fetching이 모두 발생하기 쉽습니다. 예를 들어 중첩된(nested) 엔티티를 가져오려면 여러 번 요청해야 할 수 있습니다. 또한 일반적으로 특정 엔티티의 일부 데이터만 가져올 수 없습니다. 클라이언트는 항상 엔드포인트가 자신의 configuration대로 반환하는 모든 데이터를 수신해야 합니다.
GraphQL
GraphQL은 Facebook에서 개발한 API용 오픈 소스 쿼리 언어이며, 해당 쿼리를 수행하기 위한 프레임워크를 제공합니다. 데이터를 조작하기 위해 HTTP 메서드에 의존하지 않고 대부분 POST만 사용합니다. 그 대신 queries, mutations, 및 subscriptions을 사용하여 데이터를 처리합니다.
- Query는 서버에서 데이터를 요청하는 데 사용됩니다.
- Mutation은 서버의 데이터를 수정하는 데 사용됩니다.
- Subscription은 데이터가 변경될 때 실시간 업데이트를 받는 데 사용됩니다.
GraphQL은 클라이언트가 한 번의 쿼리로 필요한 데이터를 정확하게 요청할 수 있는 프로토콜입니다. 따라서 데이터를 과도하게 가져오거나 적게 가져오는 일이 줄어듭니다. 이는 데이터 fetching이 한 번의 왕복으로 가능하게 하여 효율적이며, 네트워크를 통해 불필요한 데이터가 전송되지 않기 때문에 네트워크 오버헤드를 줄일 수 있습니다.
GraphQL에서 API는 사용자가 요청할 수 있는 데이터 유형을 정의하는 스키마(Schema)에 의해 구조화됩니다. 이 스키마는 API를 통해 사용할 수 있는 데이터의 형식과 구조를 지정합니다. 이는 개발자를 위한 명확한 가이드 역할을 하며 데이터 접근의 일관성을 보장합니다. GraphQL을 사용하면 subscription이라는 기능을 통해 실시간 데이터 업데이트가 용이해집니다. subscription을 사용하면 말 그대로 서버가 관련 업데이트를 감지할 때 구독한 클라이언트에게 새 데이터를 선제적으로 푸시합니다. 이 메커니즘은 즉각적인 자동 업데이트를 가능하게 하여 클라이언트가 실시간으로 가장 최신의 정보를 받을 수 있도록 합니다.
유연하고 효율적인 데이터 검색 및 조작이 필요한 상황에서는 REST를 대체할 수 있는 훌륭한 대안입니다. 특히 복잡한 데이터 모델이 있는 애플리케이션이나 연결성이 제한된 모바일 애플리케이션에서 아주 적합한 선택입니다. GraphQL을 사용하면 이전 버전과 호환되는 API 스키마 변경이 가능하므로 기존 클라이언트를 중단하지 않고도 API를 쉽게 발전시킬 수 있습니다.
이와 반대로 엄격한 데이터 유효성 검사가 필요한 애플리케이션, 다양한 클라이언트를 지원해야 하는 애플리케이션, 또는 소셜 미디어와 같은 사용자 대면 앱에는 적합하지 않을 수 있습니다.
REST와는 달리 쿼리가 다를 수 있기 때문에 GraphQL은 중간 프록시 캐싱을 중단하여 캐싱 구현을 더 어렵게 만듭니다. 또한 GraphQL 쿼리는 잠재적으로 크고 복잡한 서버 측 작업을 실행할 수 있으므로 서버에 과부하가 걸리지 않도록 쿼리의 복잡성을 제한하는 경우가 많습니다.
gRPC
gRPC는 Google이 개발한 고성능 오픈소스 RPC 프레임워크입니다. 이 프레임워크는 효율적이고 빠른 데이터 전송을 목표로 하며, 프로토콜 버퍼 (Protocol Buffers)는 인터페이스 정의 언어(IDL)를 사용하여 클라이언트와 서버 간 데이터 및 호출 계약을 명확히 정의합니다. 마이크로 아키텍처에서 각 서비스의 언어가 달라도 문제없는 통신을 가능하게 합니다.
Remote Procedure Call 이란?
원격 서버에 있는 함수나 프로시저를 호출할 수 있도록 설계된 통신 모델로, 네트워크를 통한 함수 호출을 마치 로컬 함수 호출처럼 간단하게 사용할 수 있게 합니다. 이러한 방식은 네트워크 통신을 직접 구현해야 하는 부담을 덜어주어, 분산 시스템이나 클라이언트-서버 구조에서 효율적으로 사용됩니다.
gRPC 프로토콜에서 클라이언트와 서버는 프로토콜 버퍼로 요청 및 응답 스키마를 정의하며, 이를 통해 상호작용이 일관되고 안정적으로 이루어집니다. 데이터는 바이너리 형식으로 직렬화되어 전송되므로, JSON 대비 페이로드 크기를 줄여 전송 속도와 효율성이 높습니다. gRPC는 HTTP/2를 사용해 효율적인 멀티플렉싱(단일 연결에서 여러 요청과 응답을 처리해 지연 시간을 줄이고 성능을 최적화) 기능을 제공하며 TLS/SSL를 통해 데이터 전송 보안을 강화합니다.
이 프레임워크는 여러 유형의 클라이언트-서버 상호 작용을 지원합니다:
- 전통적인 요청-응답 상호 작용
- 서버 스트리밍. 클라이언트의 한 개의 요청이 여러 개의 응답을 생성할 수 있습니다.
- 클라이언트 스트리밍. 클라이언트의 여러 요청이 하나의 응답으로 처리될 수 있습니다.
gRPC의 가장 큰 장점은 컴팩트한 데이터 형식, 빠른 메시지 인코딩 및 디코딩, HTTP/2 사용으로 구현되는 높은 성능입니다. 또한 코드 생성 기능은 여러 프로그래밍 언어를 지원하며 상용구 코드를 작성하는 시간을 절약할 수 있도록 도와줍니다.
HTTP/2와 TLS/SSL을 요구함으로써 gRPC는 더 나은 보안과 스트리밍에 대한 기본 지원을 제공합니다. 인터페이스 계약의 언어에 구애받지 않는 정의는 서로 다른 프로그래밍 언어로 작성된 서비스 간의 통신을 가능하게 합니다.
하지만 데이터 형식이 사람이 읽을 수 없기 때문에 페이로드를 분석하고 디버깅을 수행하려면 추가 도구가 필요합니다. 또한 HTTP/2는 최신 버전의 최신 브라우저에서 TLS를 통해서만 지원됩니다.
gRPC 대량의 데이터를 조작하거나 다양한 클라이언트를 지원해야 하는 애플리케이션에는 최선의 선택이 아닐 수 있지만, 고성능과 낮은 오버헤드로 잘 알려져 있어 서비스 간 빠르고 효율적인 통신이 필요한 마이크로서비스 간 통신이나, 실시간 데이터 스트리밍(채팅, IoT) 또는 분산 시스템에서의 데이터 전송 애플리케이션에 적합합니다.
WebSocket
웹소켓은 전이중 통신(full-duplex)을 지원하여 클라이언트와 서버 간의 양방향 데이터 교환을 가능하게 하는 실시간 통신 프로토콜입니다. 영구적인 연결을 유지한다는 점에서 기존 HTTP의 요청-응답 모델과 다릅니다. 반복적으로 연결을 열고 닫을 때에 비해 오버헤드가 적습니다. 따라서 빈번한 데이터 업데이트가 필요한 시나리오에 더 효율적입니다.
또한 지속적인 연결을 설정하고 유지하므로 각 요청에 대해 반복적으로 연결을 열고 닫을 필요가 없으므로 지연 시간이 짧은(low latency) 통신을 제공합니다.
요청/응답 기반인 REST(상태 비저장형 단방향 대화)와 달리 웹소켓은 양방향의 지속적인 커뮤니케이션을 할 수 있으므로 채팅 애플리케이션이나 온라인 게임과 같이 실시간 업데이트가 필요한 애플리케이션에 이상적입니다.
웹소켓은 복잡한 데이터 조작이 필요한 애플리케이션이나 확장성이 중요한 애플리케이션에는 적합하지 않을 수 있습니다. 하지만 양방향 지속적 연결 덕분에 실시간 커뮤니케이션과 low latency가 중요한 상황의 경우 REST보다 효율적으로, 매우 요긴하게 쓰일 수 있습니다.
SOAP
SOAP는 Simple Object Access Protocol의 약자로, 네트워크 상에서 애플리케이션 간 통신을 위한 표준 프로토콜입니다. 주로 웹 서비스의 데이터 교환을 위해 설계되었으며, XML 형식을 기반으로 데이터를 송수신합니다.
SOAP의 주요 특징은 높은 표준 준수와 보안성입니다. SOAP는 HTTP, SMTP 등 다양한 프로토콜 위에서 동작하며, 메시지 전송 중 데이터의 무결성을 보장하기 위해 강력한 보안 기능을 제공합니다. 이를 통해 트랜잭션 관리나 인증, 메시지 암호화 등 복잡한 작업을 안전하게 처리할 수 있습니다. 또한 SOAP는 상태를 유지해야 하는 애플리케이션에 적합하며, ACID 트랜잭션을 지원하는 환경에서도 안정적으로 작동합니다. XML 기반 구조 덕분에 확장성이 뛰어나며, 데이터의 명확한 정의와 구조를 유지할 수 있습니다.
SOAP는 주로 높은 보안 수준, 안정성, 표준화된 구조가 필요한 엔터프라이즈 애플리케이션에서 활용되며, 금융, 헬스케어, 정부 기관과 같은 산업 분야에서 자주 사용됩니다. 예를 들어, 보안이 중요한 금융 거래 시스템이나 전자 건강 기록(EHR)과 같은 애플리케이션에 적합합니다. 이러한 환경에서는 데이터 무결성과 보안이 핵심이며, SOAP의 표준화된 메시징 시스템과 높은 신뢰성이 큰 이점으로 작용합니다. 또한 다양한 시스템과의 상호 운용성이 요구되는 복잡한 통합 작업에서도 SOAP는 효과적인 선택이 될 수 있습니다.
어떤 것을 선택해야 할까?
이제 여러 가지 API 통신 프로토콜 중 하나를 고를 때 고려해야 할 몇 가지 기준을 살펴보겠습니다.
1. Data Format
REST는 요청 및 응답 데이터 형식 측면에서 가장 유연한 접근 방식입니다. JSON 및 XML과 같은 하나 또는 여러 데이터 형식을 지원하도록 REST 서비스를 구현할 수 있습니다.
반면 GraphQL은 데이터를 요청할 때 사용해야 하는 쿼리 언어를 자체적으로 정의합니다. GraphQL 서비스는 JSON 형식으로 응답합니다. 응답을 다른 형식으로 변환할 수는 있지만 이는 흔하지 않으며 성능에 영향을 미칠 수 있습니다.
gRPC 프레임워크는 사용자 정의 바이너리 형식인 프로토콜 버퍼를 사용합니다. 이는 사람이 읽을 수 없지만 gRPC의 성능을 높이는 주요 이유 중 하나이기도 합니다. 여러 프로그래밍 언어에서 지원되지만 이 형식은 사용자 지정할 수 없습니다.
2. Data Fetch
GraphQL은 서버에서 데이터를 가져오는 데 가장 효율적인 API 접근 방식입니다. 클라이언트가 가져올 데이터를 선택할 수 있기 때문에 일반적으로 네트워크를 통해 불필요한 데이터가 전송되지 않습니다.
반면, REST와 gRPC는 이러한 고급 클라이언트 쿼리 기능을 지원하지 않습니다. 따라서 새로운 엔드포인트나 필터를 서버에 개발하고 배포하지 않으면 서버에서 불필요한 데이터가 반환될 수 있습니다.
3. Browser Support
REST와 GraphQL API는 모든 최신 브라우저에서 지원됩니다. 일반적으로 JavaScript 클라이언트 코드가 브라우저에서 서버 API로 HTTP 요청을 보내는 데 사용됩니다.
반면, gRPC는 HTTP/2를 지원하는 브라우저에서만 사용할 수 있습니다. 그러나 gRPC-Web라는 익스텐션을 사용하면, 이는 HTTP 1.1을 기반으로 하기 때문에 제한된 기능을 가지고 있지만 모든 브라우저에서 사용할 수 있습니다.
4. Code Generation
GraphQL은 추가 라이브러리가 필요하며, 이러한 라이브러리는 GraphQL 스키마 처리, annotation 기반 프로그래밍, GraphQL 요청의 서버 처리 지원을 제공합니다.
gRPC 프레임워크도 추가 라이브러리를 필요로 하며, 필수적인 코드 생성 단계가 포함됩니다. 프로토콜 버퍼 컴파일러는 서버 및 클라이언트 보일러플레이트 코드를 생성하고, 이를 활용할 수 있습니다.
REST는 특정 프로그래밍 언어나 HTTP 라이브러리를 사용하여 구현할 수 있는 아키텍처 스타일로, 미리 정의된 스키마를 사용하지 않으며 코드 생성을 요구하지 않습니다. 다만, Swagger나 OpenAPI를 활용하면 스키마를 정의하고 원하는 경우 코드를 생성할 수 있습니다.
5. Response Time
gRPC는 최적화된 이진 형식을 사용하여 REST와 GraphQL에 비해 응답 시간이 훨씬 빠릅니다. 그렇지만 다른 프로토콜도 로드 밸런싱을 사용하여 클라이언트 요청을 여러 서버에 고르게 분배할 수 있습니다.
gRPC는 기본적으로 HTTP 2.0을 사용하기 때문에, REST와 GraphQL API에 비해 지연 시간이 더 낮습니다. HTTP 2.0을 통해 여러 클라이언트는 새로운 TCP 연결을 설정하지 않고 동시에 여러 요청을 보낼 수 있습니다. 대부분의 성능 테스트에 따르면, gRPC는 REST보다 약 5배에서 최대 10배까지 더 빠른 성능을 보여줍니다.
6. Caching
REST에서 요청과 응답의 캐싱은 간단하고 성숙한 방식으로, HTTP 수준에서 데이터를 캐싱할 수 있게 해 줍니다. 각 GET 요청은 애플리케이션 자원을 노출하며, 이는 브라우저, 프록시 서버, 또는 CDN에 의해 쉽게 캐시 될 수 있습니다.
반면, GraphQL은 기본적으로 POST 메서드를 사용하고, 각 쿼리가 다를 수 있기 때문에 캐싱 구현이 더 복잡합니다. 이는 특히 클라이언트와 서버가 지리적으로 멀리 떨어져 있을 때 더욱 그렇습니다. 이 문제를 해결할 수 있는 방법 중 하나는 GET을 사용하여 쿼리를 수행하고, 서버에 미리 계산되어 저장된 지속적인 쿼리를 사용하는 것입니다. 일부 GraphQL 미들웨어 서비스는 또한 캐싱 기능을 제공합니다.
현재 gRPC는 기본적으로 요청과 응답의 캐싱을 지원하지 않습니다. 그러나, 응답을 캐시 할 수 있는 맞춤형 미들웨어 계층을 구현하는 것은 가능합니다.
7. Intended Usage
REST는 도메인에 적합한 아키텍처 스타일로, 동작보다는 자원 집합으로 쉽게 설명할 수 있습니다. HTTP 메서드를 활용하면 이러한 자원에 대해 표준적인 CRUD 작업을 수행할 수 있습니다. HTTP의 의미론에 의존함으로써 호출자에게 직관적이며, 이는 공용 인터페이스에 적합합니다. 또한 REST는 좋은 캐싱 지원을 제공하여, 사용 패턴이 안정적이고 지리적으로 분산된 사용자들이 있는 API에 적합합니다.
GraphQL은 여러 클라이언트가 서로 다른 데이터 세트를 요구하는 공용 API에 적합합니다. 따라서 GraphQL 클라이언트는 표준화된 쿼리 언어를 통해 원하는 정확한 데이터를 지정할 수 있습니다. 또한, 여러 출처에서 데이터를 집계하여 여러 클라이언트에 제공하는 API에 좋은 선택이 됩니다.
gRPC 프레임워크는 마이크로서비스 간의 빈번한 상호작용이 필요한 내부 API를 개발할 때 적합합니다. 주로 IoT 장치와 같은 저수준 에이전트에서 데이터를 수집하는 데 사용됩니다. 그러나 제한된 브라우저 지원으로 인해 고객-facing 웹 애플리케이션에서 사용하기 어려운 점이 있습니다.
Mix and Match
세 가지 API 프로토콜에는 각각 장단점이 있습니다. 그러나 모든 경우에 적합한 접근 방식은 없으며 사용 사례에 따라 어떤 접근 방식을 선택할지 결정해야 합니다.
매번 한 가지를 선택할 필요는 없습니다. 또한 솔루션 아키텍처에서 다양한 스타일을 혼합하여 사용할 수도 있습니다.
아래의 아키텍처 다이어그램 예시에서 보듯이, 서로 다른 애플리케이션 계층에서 서로 다른 API 프로토콜을 적용할 수도 있습니다.
마무리
이번 글에서는 웹 API 설계에 널리 사용되는 커뮤니케이션 스타일을 살펴보았습니다. REST, GraphQL, gRPC, WebSocket, SOAP의 사용 사례를 살펴보고 장점과 장단점을 살펴봤습니다.
또한 어떤 API 프로토콜을 사용할지 결정하기 전에 고려해야 할 몇 가지 기준을 살펴보고 비교해 보았고, 애플리케이션 계층에 따라 서로 다른 접근 방식을 혼합하여 사용할 수 있는 방법을 살펴봤습니다.
REST에서 요청과 응답의 캐싱은 간단하고 성숙한 방식으로, HTTP 수준에서 데이터를 캐싱할 수 있게 해 줍니다. 각 GET 요청은 애플리케이션 자원을 노출하며, 이는 브라우저, 프록시 서버, 또는 CDN에 의해 쉽게 캐시 될 수 있습니다.
반면, GraphQL은 기본적으로 POST 메서드를 사용하고, 각 쿼리가 다를 수 있기 때문에 캐싱 구현이 더 복잡합니다. 이는 특히 클라이언트와 서버가 지리적으로 멀리 떨어져 있을 때 더욱 그렇습니다. 이 문제를 해결할 수 있는 방법 중 하나는 GET을 사용하여 쿼리를 수행하고, 서버에 미리 계산되어 저장된 지속적인 쿼리를 사용하는 것입니다. 일부 GraphQL 미들웨어 서비스는 또한 캐싱 기능을 제공합니다.
현재 gRPC는 기본적으로 요청과 응답의 캐싱을 지원하지 않습니다. 그러나, 응답을 캐시 할 수 있는 맞춤형 미들웨어 계층을 구현하는 것은 가능합니다.
'개발 이모저모' 카테고리의 다른 글
동시성 프로그래밍: Python 코루틴과 Go 고루틴 (3) | 2025.02.02 |
---|---|
SQLAlchemy 2.0 - Major Migration Guide (2) | 2025.01.19 |
NGINX, Proxy, Load Balance (0) | 2025.01.04 |
파이썬 비동기 웹 애플리케이션 기본 개념부터 FastAPI까지 (3) | 2024.11.09 |
IAM: Identity and Access Management 와 Keycloak (1) | 2024.10.12 |