[DDD] Event Driven 아키텍쳐: 커맨드와 이벤트

[원본 링크]

이전 포스트
https://m.blog.naver.com/sssang97/223133481493

이벤트를 기반으로 시스템을 분리해서 만들다보면, 당연히 이런 고민이 뒤따를 것이다.
"이벤트 처리가 실패하면 어떻게 하지?"

이에 대한 관점에서 이벤트와 커맨드(Command)가 분리된다.

커맨드 또한 이벤트의 한 종류이긴 하지만, 오류 처리시의 제어권이 달라진다.




Event

이벤트는 기본적으로 정리나 알림 등에 대한 메세지지를 보내는 것이다.

보통 이벤트의 경우에는 오류가 발생하더라도 그 오류를 다른 시스템에 전파하지는 않는다.

예를 들어, 누군가가 구매를 시도했을 경우에 재고가 없어서 리필을 해주거나 대응을 해줄 필요가 있다고 가정한다. 그래서 재고가 떨어지면 관리자에게 이메일을 보내주도록 했다.
그런데 이메일을 보내는게 실패하거나 늦어졌다고 해서 그렇게 크리티컬한 문제로 이어지는 일은 적은 편이다.

이런 "알림"의 형태를 가진 기능에는 Event가 적합하다.

그래서 이런 크리티컬하지 않은 기능이 실패했을 때는 보통 로그를 남기거나 다른 issue report 채널에 전송하는 정도로만 끝내는게 보통이다.
그렇기 때문에 이러한 형태의 일반적인 event들은 실패해도 큰 문제가 없는 경우에 적용하는 것이 좋다.




Command

반면 커맨드는 핸들러에게 명확한 행위를 요구하도록 "명령"하는 메시지 단위다.

Event와 크게 다를 것은 없지만, 오류 처리를 명확하게 요구한다는 점이 다르다.

예를 들어, 결제 요청과 그 처리를 Event-driven으로 구성한다고 가정하겠다. 결제 처리중에 뭔가의 이유로 실패를 했다면, 이건 당연히 매출을 가르는 중차대한 문제다.
어떤 방식으로는 이벤트를 전송한 client 관점에서도 무언가 대응을 할 필요가 있다.
이럴때는 Command를 사용해야 한다.

기본적인 원리는 그리 특이할게 없다.
그냥 실패했을때 오류를 되돌려줘서 event sender 입장에서 뭔가 대응을 할 수 있게 하는 것이다.

event sender와 handler가 한 프로그램에 공존하는 환경에서는 로직 자체에서 오류를 반환하거나 throw하게 할 수 있다.
반면 event sender와 handler가 분리된 환경에서는 다시 RPC나 message broker를 통해 event sender에게 error event를 되돌려주도록 할 수도 있다.

물론 후자의 경우에는 문제가 훨씬 복잡해지기 때문에, 이에 대한 해결법으로 여러가지 파생 패턴들이 많이 나왔다.
https://blog.naver.com/sssang97/223026977131
https://blog.naver.com/sssang97/223057488695
이런게 또 MSA 경험을 끔찍하게 만드는 주 요소 중 하나다.



참조
https://event-driven.io/en/whats_the_difference_between_event_and_command/