이번 포스팅은 IPC중 HTTP 기반의 동기 통신중 대표적인 REST와 gRPC의 차이를 메시지 포맷과 애플리케이션 설계 순서에 따라 정리해보려 한다. 정의와 장단점, 유의할 점 등을 간단하게만 알아본다. 기술에 대한 깊은 학습은 추후 기술을 사용할 기회가 주어진다면 진행하려 한다.
프로세스간 통신에는 여러 선택지가 있다. 동기적인 요청/응답 통신을 하는 HTTP기반의 REST
, gRPC
(HTTP 2.0)와 AMQP, STOMP등 비동기 메시지 기반의 통신 메커니즘도 존재한다. 메시지 포맷도 JSON
, XML
과 같이 인간이 읽을 수 있는 텍스트 포맷부터 avro
, Protocol buffer
처럼 효율이 우수한 이진 포맷까지 다양하다.
HTTP 기반 동기 요청/응답 통신
동기 요청/응답(request/response) 통신에서 클라이언트는 서비스에 요청을 하고 응답을 기다린다. 클라이언트는 응답이 제때 도착하리라 기대하고 응답을 대기하는 도중 블로킹할 수 있다. 결과적으로 클라이언트와 서비스가 강하게 결합되는 통신이다.
장단점
동기 통신은 요청에 대한 응답이 제때 도착하리라는 신뢰성이라는 장점이 존재하는 반면, 요청/응답 서버 모두 가용중일 때, 통신이 가능하다는 단점이 존재한다. 이러한 단점은 분산 서비스 환경에서 치명적이다.
여러개로 나누어진 분산 서비스에서 모든 통신이 동기적으로 수행된다면 어떨까? 하나의 요청이 5개의 서비스에 걸쳐 수행되어야 한다면, 5개의 서비스 인스턴스가 모두 가용중이어야 하고 요청을 제 때 처리할 수 있는 상태여야 한다. 문제는 5개의 서비스에 걸쳐 사용자의 요청을 처리할 때, 스레드와 같은 리소스를 계속해서 점유한다는 것이다.
따라서 MSA에서는 이벤트기반 아키텍처를 구성하여 각 서비스가 비동기 메시지 통신을 하는 것이 일반적이다.
메시지 포맷과 설계 순서
IPC의 핵심은 메시지 교환이다. 메시지를 분석하여 서비스는 특정 로직의 수행을 결정한다. 대부분의 메시지는 데이터를 담고 있기 때문에 데이터 포맷은 중요한 설계 결정 항목이다. 메시지는 크게 텍스트와 이진 포맷으로 분류된다.
텍스트 포맷을 사용하면 API 설계 순서가 애플리케이션 개발에 구애받지 않는다. 하지만 이진 포맷은 애플리케이션 개발 전 API 설계가 필수적으로 선행되어야 한다.
텍스트 메시지 포맷
텍스트 메시지 포맷은 대표적으로 JSON, XML이 있다. 텍스트 기반 포맷은 사람이 읽을 수 있고, 자기 서술적(메시지 그 자체만으로 의미가 분명한)이라는 장점이 있다. 또한 메시지 consumer는 메시지 중 자신에게 필요한 값만 골라 사용하고 나머지는 무시할 수 있으므로 메시지의 프로퍼티 구조가 자주 변경되어도 하위 호환성이 쉽게 보장된다.
단점은 메시지가 다소 길다는 것이다. 모든 메시지가 Key
:Value
쌍으로 이루어져 있고, 사람이 읽을 수 있는 문자열로 구성된다. 이는 이진 값보다는 데이터 볼륨이 크고, 메시지의 텍스트를 파싱하는 과정에서 오버헤드가 발생할 수 있다는 단점이 있다. 트래픽 많음 + 통신에 필요한 데이터 큼 2단 콤보를 맞아버리면 당연히 성능이 떨어질 수 밖에 없을 것이다. 따라서 효율과 성능이 중요한 경우에는 이진 포맷을 고려해보는 것이 좋다.
텍스트 메시지 포맷의 API 설계 순서가 비교적 자유로운 이유
메시지 텍스트 포맷의 장점 덕분이라고 할 수 있다. 사람이 읽을 수 있고, 자기 서술적이라는 장점은 통신을 하는 두 서비스가 미리 약속을 하지 않아도 이해할 수 있다. 예를 들어 클라이언트와 서버가 텍스트 포맷에 대한 약속을 하지 않은 상태라고 가정한다. 여기서 클라이언트가 서버에게 내가 주문한 음식 내용을 요청했을 때, 서버가 아래와 같이 응답했다면 클라이언트는 완벽하게는 아니지만 무리없이 응답을 이해할 수 있을 것이다.
{
"orderId": 1,
"orderNumber": 1221,
"orderMenu": "동대문 엽기 떡볶이 치즈추가",
"orderState": "주문 접수",
"payment": "신용카드"
}
RPC와 이진 메시지 포맷
이진 포맷은 말그대로 데이터가 이진 값인 메시지 포맷이다. RPC
(Remote Procedure Call)에서 대표적으로 사용한다. 텍스트 메시지 포맷보다 크기가 작기에 성능이 좋다.
RPC는 원격 시스템의 함수(return이 필요)나 프로시저(명령)를 호출하기 위한 통신 기술이다. 클라이언트와 서버 두 환경의 제약없이 통신이 가능하다는 것이 장점이다. 이러한 장점을 취하기 위해 IDL
(Interface Definition Language)를 사용한다.
IDL은 메시지 구조 정의에 필요한 언어이며, 컴파일러는 IDL을 기반으로 이진 메시지를 직렬화/역직렬화하는 코드를 생성한다. IDL은 대표적으로 Protobuf
, Thrift
가 있다.
Thrift를 예시로 설명하면, 아래와 같이 IDL을 작성한다.
struct Person {
1: required string name,
2: optional int32 age,
3: optional string email,
}
IDL을 컴파일러를 통해 직렬화/역직렬화 하는 코드를 생성한 다음 이를 사용하는 서버에서 라이브러리를 통해 사용한다.
이진 메시지 포맷의 API 설계 순서가 우선되어야 하는 이유
서비스 간 통신에 이진 데이터 포맷을 사용하기 위한 작업을 위에서 설명했다. 만약 이진 데이터 포맷을 직렬화/역직렬화 하는 라이브러리가 없는 채로 두 서비스가 통신하게 되면 어떨까?
메시지의 이해가 불가능할 것이다. 101010101110011101011100
지금 내가 어떤 규칙에 따라 임의로 작성한 이진 데이터이다. 다른 사람이 이걸 이해할 수 있을까?
따라서 두 서비스의 통신에 이진 메시지 포맷을 사용하기 위해서는 이진 데이터가 어떤 구조로 이루어져있고, 어떻게 직렬화/역직렬화 되는지에 대한 규칙을 정해야 한다. 이를 IDL이라는 도구를 통해 정의하고 컴파일하며, 코드에서 라이브러리를 통해 직렬화/역직렬화 과정을 거치게된다. 그렇기에 비즈니스 로직을 작성하기 전 API 설계가 필수적으로 선행되어야 한다.
정리
HTTP기반 동기 요청/응답 통신은 분산 서비스 환경에서 사용하기엔 비효율적이다.
동기 요청/응답 통신은 상호작용하는 두 서버가 모두 가용 중이라는 제약이 존재하기 때문이다.
또한 요청이 응답을 기다리기 위해 blocking되는 과정에서 스레드와 같은 리소스를 점유하기에 리소스 사용에 있어 비효율적이다.
메시지 포맷에는 텍스트, 이진 메시지 포맷 두 종류가 있다.
텍스트 포맷은 사람이 읽을 수 있다는 큰 장점, 메시지 크기가 크다는 단점이 존재한다.
이진 메시지 포맷은 크기가 작다는 장점, API 설계가 선행되어야 한다는 단점이 존재한다.
'CS' 카테고리의 다른 글
DDD - 외부 시스템 호출 분리와 이벤트 (0) | 2024.04.06 |
---|---|
DDD - 애그리거트 트랜잭션 관리와 동시성 처리 (0) | 2024.04.05 |
DDD - 도메인과 애그리거트 (1) | 2024.03.27 |
Blocking vs Non-Blocking I/O (0) | 2024.03.26 |
비동기 메시징 통신: Message vs Event (0) | 2024.03.17 |