여러 서비스에서의 Message기반 비동기 호출 아키텍처를 구성할 때, Message Driven Architecture, Event Driven Architecture의 선택지가 존재한다. 여기서 Message와 Event의 차이를 정리해보려 한다.
메시징
메시징은 서비스가 메시지를 서로 비동기적(메시지 브로커를 사용하는 경우와 통상적인 경우)으로 주고받는 통신 방식이다. 보통 메시징 기반 애플리케이션은 서비스 사이에 Message Brocker(대표적으로 Kafka, RebbitMQ)를 두어 비동기 통신을 구현하지만, 서비스가 직접 서로 통신하는 BrockerLess 아키텍처도 존재한다.
BrockerLess 아키텍처는 통신할 애플리케이션이 가용중이 아니라면 내부적으로 큐를 두는 방식 등을 통해 메시지 손실 방지에 대한 대책을 마련해야 한다.
비동기 방식이기에 요청을 받은 애플리케이션은 응답할 수 있을 때 응답하며, 요청한 애플리케이션은 응답을 위해 블로킹하지 않는다. MessageBrocker(Message Channel)를 사용하는 방식에서는 송신자(클라이언트)가 채널에 메시지를 쓰고, 송신자가 채널에서 메시지를 읽고 응답을 채널에 쓰는 방식을 사용한다.
메시지
메시지는 Header와 Body로 구성된다. Header는 송신된 데이터에 대한 MetaData가 Key/Value 형식으로 구성된다. Body는 당연하지만 텍스트 또는 이진 포맷 데이터로 구성된다.
메시지의 종류는 다양하지만 대표적으로 문서(document), 커맨드(command), 이벤트(event)가 사용된다.
문서는 데이터만 포함된 메시지이다. 메시지를 해석하는 방법은 수신자가 결정한다. (커맨드에 대한 응답을 문서로 표현할 수 있음)
메시지 채널
메시지는 채널을 통해 교환된다. 보통 메시징 인프라(kafka, RebbitMQ)에서 이를 구현한다. 메시지 송신자는 DrivenAdapter를 통해 메시지 채널로 메시지를 발행하고, 메시지 수신자는 DrivingAdapter를 통해 메시지를 수신한다.
두 애플리케이션 혹은 서비스 사이의 통신을 위한 통로라고 생각하면 편하다.
채널은 두 종류가 있다. 하나의 컨슈머를 지정하여 메시지(보통 커맨드)를 전달하는 점대점 채널, 같은 채널을 바라보는 모든 컨슈머에게 메시지(보통 이벤트)를 전달하는 발행-구독(publish-subscribe) 채널이 그 종류이다.
커맨드 (Command)
"야 너 어떤거 해"
커맨드는 대게 메시지라고 알고있는 방식이다. RPC 요청과 동등하게 호출할 작업과 전달할 매개변수가 지정되어 있다. 의미 그대로 명령이라고 생각하면 이해하기 쉽다. 함수의 호출, RPC 요청과 같이 어떤 행위를 수행하라고 명령하는 것이다.
커맨드 요청/응답 통신 구조에서 supplier는 메시지 식별자, 응답받을 채널, 본문을 요청 채널로 비동기 송신한다. consumer는 메시지를 읽고 로직을 처리한 뒤 메시지 식별자를 포함한 응답 데이터를 요청 메시지에 포함된 응답 채널에 비동기 송신한다.
이벤트 (Event)
"어떤 일이 발생했음"
이번트는 송신자에게 어떤 일이 발생했음을 알리는 메시지 방식이다. 보통 도메인 객체의 상태 변화를 이벤트로 발행한다. 현실 세계의 웹 쇼핑몰의 세일 이벤트라고 생각하면 이해하기 쉽다. 쇼핑몰(송신자, 발행자) 세일이라는 이벤트를 발행한다. 이벤트는 누구든 볼 수 있고, 필요에 의해 수신자(구독자)는 이벤트에 대한 행위를 수행한다.
이벤트는 대개 발행/구독(Pub/Sub) 스타일의 상호 작용을 사용하여 통신한다. Publisher는 자신의 발행/구독 채널에 이벤트 메시지를 발행하고, Subscriber는 구독중인 채널의 이벤트를 확인하여 이를 처리한다.
유의할 점
메시지 기반 통신에서 유의할 점은 나중에 메시지 브로커의 한 종류인 kafka를 학습하며 다루어 볼 예정이다.
유의할 점을 대략적으로 설명하면 아래와 같다. (커맨드와 이벤트를 잘 구분해야 한다.)
메시지 순서 유지
메시지의 순서가 어긋나면 문제가 발생할 수 있다. 주문을 생성, 변경하고 취소하는 순서를 가진 이벤트 메시지를 차례대로 전송했는데, 메시지 채널에서 순서가 지켜지지 않은채 저장되고 이를 수신자가 받았다고 가정한다. 수신자는 주문을 생성하기도 전에 취소하는 말이 안되는 처리를 진행할 수도 있다.
중복 메시지 처리
비동기 통신은 같은 메시지를 여러번 전달할 수 있음을 항상 인지해야 하며, 중복 메시지에 대한 문제점을 해결할 방안을 마련해야 한다.
예를 들어, 특정 주문을 결제하는 이벤트가 중복해서 발생했을 때, 이벤트를 중복해서 처리하면 두번의 결제가 이루어지는 말이 안되는 처리가 진행될 수 있다.
- 메시지 처리에 있어 멱등성을 유지한다.
- 메시지를 추적하거나 중복 메시지를 솎아내기 위한 로직을 작성한다.
'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 |
IPC: 메시지 포맷과 설계 순서 (3) | 2024.03.19 |