[Design] EDA의 개념 (1) – Event

요즘 개발하면서 자주 듣는 두가지 패러다임이 있는 것 같다. EDA ( Event – Driven – Architecture ) 와 DDD ( Domain – Driven – Design ) 두가지가 바로 그것이다.
이 둘은 많이 사용되면서 서로 각각 고유의 접근 방식과 철학을 가지고 있다. 이 둘은 장점이 아주 명확하고 서로 상호 배타적이지 않기 때문에 각각의 장점을 잘 살릴 수 있는 방향으로 둘을 결합시켜 사용되는 경우도 많다고 생각한다. 하지만, 제대로 사용하지 않으면 사용하지 않은 것만 못하는 결과가 나타나기도 하기 때문에 잘 알고 사용하는것이 중요하다.
따라서 이번 시리즈는 이러한 패러다임을 제대로 이해하고 사용하기 위해 하나씩 기록해보고자 한다. ( 이 글은 Martin Fowler 가 설명하는 EDA 에 대한 youtube 영상과 그의 Blog 글을 통해 EDA란 무엇이고, 그 개념에 대해 기록한 글이다. )

Event, Command and Message

본격적으로 살펴보기 이전에, 이 3가지 개념의 의미에 대해서 먼저 짚고 가자.
1. Message : 메시지는 한 시스템에서 다른 시스템으로 요청하는 것으로 처리에 필요한 모든 payload 를 포함하는 요청을 말한다. 두 시스템 사이에 존재하는 메시지는 일반적인 것으로 만드는 특별한 의도가 없을 뿐만 아니라 의미가 적기 때문에, 이 메시지에 추가적인 개념을 포함시켜 볼 수 있다.
2. Event : 이벤트는 과거에 발생한 사건을 알리기 위한 메시지를 말한다. 이 Event는 과거를 나타내며 한 번 일어난 후에는 변하지 않는 상태를 뜻한다. 그렇기 때문에 Event는 불변이며, 상황에 대한 알림이기 때문에 이 Event 를 Approve 하거나 Reject 하는것은 불가능하다.
3. Command : 커맨드는 어떤 행동을 취하기 위해서 한 시스템에서 다른 시스템으로 전송하는 메시지를 말한다. 이는 가능한 미래를 나타내기 때문에 이를 Approve, Reject와 같은 처리를 하고 응답할 수 있다.

Trap 1 – Passive-aggressive Command

넘어가기 이전에, Event 와 Command 를 사용할 때 생길 수 있는 문제점 하나만 먼저 살펴보자. Martin Fowler 가 제시한 Event 와 Command 를 사용함에 있어서 발생될 수 있는 문제이다.
이는 수신자가 동작을 수행하기를 기대할 때 , 해당 의도를 표시하기 위해 Command를 사용해야 하지만 메시지를 Event로 발행하는 것을 말한다. Martin Fowler는 보험 시스템에 대한 예시를 들었다.

… You could have your insurance quoting system might insist on sending a communication an email to the a customer. A natural way to do that of course will be a command “Send an email”. But of course if you go too far down the event route you then get this effect of passive-aggresive events or passive-aggresive commands where you’re saying ” the customer needs to be sent a message about their new quote! hints, hints.. “
And you know you don’t really want to go down that path if you’re trying to read how the systmem works.

즉, 일반적으로라면 “이메일을 보내라” 라는 Command 를 사용해야 할 메시지가 Event 라는 네이밍을 달고 “이메일을 보내라”는 동작을 수행하기를 기대하고 있다. 그와 더불어 Event에 메일을 보내기 위한 다수의 정보들( Hints )을 포함하는 것을 말한다. 이러한 함정에 빠지지 않도록 Event, Command 의 개념을 잘 숙지하고 보자.

EDA – Martin Fowler

그럼 이제 본격적으로 Martin Fowler 가 얘기하는 Event Driven Architecture 에 대해서 알아보자.
그는 영상에서 이렇게 설명한다.

We identified four different things I would called them patterns that often come under the term event driven. An event-driven system might you when people say they have an event-driven system they usually mean they’ve got at least one of these patterns in play. And could mean they have all four patterns in play.

그는 4가지 중요한 Pattern 을 통해 Event Driven Architecture 를 설명한다. 그 각각의 4가지 패턴을 통해서 EDA 가 구성되고, Event Driven System 은 이들 중 적어도 1가지는 갖춰야 한다고 말한다. 그렇다면 Event Driven System 을 구성하는 이 4가지 패턴에 대해서 하나씩 살펴보자.

Event Notification

어떤 시스템이 가지고 있는 ( 관리하는 ) 도메인의 변경 사항을 남들에게 전파하는 것을 말한다. 이때 이벤트를 Publish 하는 Source System 이 해당 Event의 응답에 대해 많이 신경쓰지 않는다는 것이 핵심이다. ( 만약, 이 Event 의 응답에 대해 전혀 신경쓰지 않거나, Source System 이 응답을 기다리거나 하면 간접적으로 사용한다고 표현했다. )

이러한 Event Notification은 Source System 과 Target System 간의 낮은 수준의 커플링을 어렵지 않게 만들어 낼 수 있다는 장점이 있다. 하지만 실제 비즈니스 영역에 적용했을 때 다양한 이벤트 알림에 걸쳐 실행되는 논리적 흐름이 있다면 이것으로 인해 문제가 생긴다.
Event Notification Pattern을 사용하면 잘 분리된 시스템을 쉽게 만들 수 있으므로 계속해서 개발하다 보면 이벤트를 통해 경계( Context ) 가 확고하게 나뉘어지게 된다. 이렇게 분리된 경계와 이벤트의 응답에 대해 신경쓰지 않는다는 점 때문에 현재 처리하고 있는 이벤트가 어떤 비즈니스 로직의 일부분인지, 더 큰 규모의 흐름을 보지 못하게 되어 나중에 문제가 발생할 수도 있다.

Event-Carried State Transfer

이는 Event Notification 의 발전된 패턴이다. 그렇다면 어떻게 뭐가 발전되었을까? 그는 이렇게 설명한다.

Event notification often involves additional traffic because the systems that are the consumer system still have to go back to the original source to get more information. And of course, we reduce that burden by putting more information into the event.

그가 설명한 예시와 함께 보자. ‘Linda의 주소가 변경되었다’ 는 이벤트를 다음과 같이 표현해 볼 수 있다.

  1. 뭔가 바뀌었다.
  2. Linda에 대한 정보가 바뀌었다.
  3. Linda의 주소가 바뀌었다.
  4. Linda의 예전 주소는 A 인데 B로 바뀌었다.

이벤트에 대한 정보를 1, 2, 3과 같이 표현하면 뭐가 어떻게 바뀐 것인지, 주소가 바뀌었으면 어떻게 바뀐 것인지.. 등등 추가적인 정보를 위해서 다시 이 이벤트를 발행한 Source System 에 질의하기 위해 Traffic 을 발생시키게 된다. 그리고 당연히, 자세한 정보를 더 포함시켜서 이벤트를 발행하게 되면 불필요한 Traffic 을 줄일 수 있다.
그렇다면 4번처럼 이벤트를 발행하면 모든 문제가 해결되겠는가? 하면 또 다른 문제가 발생한다.

메시지를 수신하는 System 은 4번처럼 이벤트를 발행하게 될 경우에 “뭐가 바뀌었느냐, 주소가 어디로 바뀐것이냐” 와 같은 트래픽은 발생하지 않는다. 하지만, 수신하는 시스템이 자신이 주소가 변경된것에 대한 일을 처리하기 위해 “주소”가 아닌 다른 고객 정보가 필요할 수 있다. 이러한 정보를 얻기 위해서는 다시 고객 정보를 가지고 있는 고객관리시스템에 질의해야만 한다.
그렇다면 고객정보를 관리하는 고객관리시스템은 고객정보와 관련된 Flow 들이 처리될 때 마다 다른 System들이 “Linda 의 방문 기록 정보를 조회해 달라”, “Linda 의 최종접속지 IP주소를 가르쳐 달라” 는 식의 트래픽을 받게 된다.

바로 이런 상황에서 사용할 수 있는 전략이 Event-Carried State Transfer 이다.
해당 Event 를 구독하는 Downstream System들이 앞으로 필요하게 될 모든 고객데이터의 복사본을 보관하는 것이다. 즉, Source System 은 모든 Downstream 들이 보유하고자 원하는 모든 정보를 Event 를 통해 Broadcasting 해야 하지만 이를 통해 Downstream System 들은 자신이 관심 있는 ( 사용할 가능성이 있는 ) 정보들을 복사하여 저장함으로써 더 이상 Source System 에 질의하지 않아도 된다는 장점이 생긴다. 이는 네트워크를 사용하지 않는 질의 이기 때문에, 비용을 절약할 수 있고 Performance 성능 향상도 기대해볼 수 있다.

또한 이와 더불어 Downstream System 들의 처리 능력과 성능이 더이상 Source System 과 무관하다는 장점도 생긴다. 예를들어 Linda 의 정보를 고객 관리 서비스에 조회해서 정보를 가져온 뒤 비즈니스 로직을 수행했다면, 고객 관리 시스템에 요청이 너무 많아 응답이 느려질 경우 Downstream System 또한 덩달아 느려지는 현상이 발생할 수가 있다. 하지만, 이런 식으로 복사본을 통해 관리하면 고객 관리 시스템과 아무런 연관관계가 없기 때문에 상관없다.

물론, 단점으로는 데이터에 해당하는 복사본이 많아진다는 점인데 이에 대해 마틴 파울러는 스토리지가 비싸지 않고, 모든 데이터를 전부 저장하는게 아닌 사용 가능성이 있는 데이터만 선택적으로 복사하기 때문에 그렇게 나쁘지 않다고 말한다.

하지만 Data 를 복제하여 고가용성( high availability )을 확보하는것은 분명한 장점이나, 반드시 함께 따라오는 이슈가 있다. 바로 Data 정합성에 대한 보장이다.

… So Event-Carried State Transfer has this trade-off. I get even more decoupling, even more availability but i lose complexity of keeping the duplicated data and inevitable eventual consistency.

이 이유 때문에 Event state transfer 는 위에서 설명한 Event Transfer 보다는 덜 일반적인 패턴이다. 따라서, 적용함에 있어 정말로 이런 적용이 필요한지 깊이 고민해볼 필요가 있다.

정리

이 글에서는 EDA 를 이루는 4가지 Pattern 들 중 기본적인 패턴 2가지에 대해서 살펴봤다.
Event Notification, 그리고 이를 발전시킨 Event-Carried State Transfer. 이 내용을 잘 기억하면서 다음 글에서는 이어서 많은 분량을 차지할 EventSourcing 과 CQRS 에 대해서 알아보자.

Leave a Comment