설계: 생각을 ‘차려’ 물질로 만드는 힘
이 글은 <객체지향 분석설계 말고 객체지향 사고법>에서 인용했던 다음 다발말[1]에서 말하는 '이벤트 드리븐'이란 표현에 대한 제 생각을 쓰는 글입니다.
그렇다면 왜 객체지향을 고민할수록 이벤트 드리븐으로 종결하느냐를 말씀드려 보면, 결국 두 객체는 각자의 역할을 가진 자율적인 객체라는 전제가 생기는데요. 자율적이라는 말이 갑이라는 객체가 메시지를 전달했을 때 을이라는 객체는 메시지의 완전하게 처리해야만 하는 의무를 가진다는 것입니다. 이 사상을 대응할 수 있는 것이 이벤트 드리븐이라는 사상밖에 없다고 생각하여 객체지향을 고민할수록 이벤트 드리븐으로 종결한다고 말씀드리는 이유입니다.
'이벤트 드리븐'이라는 표현으로도 지인이 뭘 의도하는지는 대략 짐작할 수 있습니다. 하지만, 마치 <객체지향 분석설계 말고 객체지향 사고법>에서 '객체 지향'의 의미만큼이나 모호한 여지를 두는 말입니다. '이벤트 드리븐'이라는 말은 Event-driven architecture를 줄여서 쓰는 말로 짐작할 수 있습니다.
Event-driven architecture (EDA) is a software architecture paradigm concerning the production and detection of events.
하지만, 위키피디아 EDA 페이지에서도 볼 수 있듯이 굉장히 다양한 맥락에서 쓰이는 포괄적인 말입니다. 한편, 여기서 흥미로운 지점은 객체 지향과 연관성을 찾을 수 있는 내용이 예제를 설명하는 부분 빼고는 없다는 점입니다. EDA 페이지에서 '객체 지향'을 뜻하는 'object-oriented'나 'object oriented'라는 단어는 아예 존재하지 않습니다. 그저 객체 지향 언어가 쓰이는 통에 예제에서 'object'란 단어를 찾을 수 있을 뿐입니다.
그럼에도 불구하고 지인이 '객체지향'과 '이벤트 드리븐'의 강한 연관성을 주장하는 부분은 이해할 수 있었습니다. 우선은 '객체지향'을 OOP나 객체지향 분석설계 말고 객체지향 사고법으로 이해한다는 전제가 필요합니다. 그리고 두 번째로 이벤트 드리븐을 포괄적인 EDA가 아니라 DDD에서 다루는 Event Sourcing을 지칭했다고 하면 무엇을 주장하려고 하는지 공감할 수 있습니다.
Event sourcing is an architectural pattern in which entities track their internal state not by means of direct serialization or object-relational mapping, but by reading and committing events to an event store.
(OOAD도 마찬가지지만) OOP에서는 객체(Object)를 일종의 경계를 지닌 프로그래밍 단위로 봅니다. 그래서 객체 사이의 교류를 메시지로 하도록 규정합니다. OOP 수준에서 메시지는 보통 메소드를 호출하는 일로 구현하는 것이 기본입니다. 그리고, 메시지가 메소드 직접 호출로 일대일 대응하여 풀리지 않는 문제를 개선하기 위해 다양한 패턴을 제시합니다. 흔히 디자인 패턴이라 부르는 것들의 상당수가 그러하죠.
디자인 패턴하면, 그 옛날[2] 나왔던 <Design Patterns>라는 전설적인 책이 있습니다. 거기에 Observer Patterns가 있습니다.
위키피디아 페이지 정의를 볼까요?
In software design and engineering, the observer pattern is a software design pattern in which an object, named the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.
어떤 주제(보통 객체로 구현)에 대해 상태 변화가 생기면 자동으로 통지가 가도록 하는 관찰자(observer)구조를 패턴으로 정의한 내용입니다. Observer를 모르시는 개발자 중에 이런 내용을 들으면 분명 Pub/Sub 패턴을 떠올리시는 분들도 있을 겁니다.
주제를 특정한 객체에 결합되지 않도록 하는 Observer 패턴을 구현하면 바로 publish-subscribe pattern을 구현하게 되기 때문입니다. 그리고, 분산 프로그래밍이 보편화된 요즘에는 Observer 패턴보다 Pub/Sub 패턴이 더욱 널리 알려져 있는 탓이기도 하고요.
위키피디아의 Observer 패턴 설명 중에 다음 내용이 있습니다.
It is often used for implementing distributed event-handling systems in event-driven software.
분산환경에서 Observer 패턴을 구현하는 한 가지 방식이 다시 Event sourcing이라고 할 수 있습니다. 다시 한번 Event sourcing의 정의를 인용하겠습니다.
Event sourcing is an architectural pattern in which entities track their internal state not by means of direct serialization or object-relational mapping, but by reading and committing events to an event store.
다만, 행간에 깔린 맥락이 Observer 패턴 설명과는 사뭇 다릅니다. 저는 특히 다음 구절에서 CRUD를 떠올립니다.
entities track their internal state not by means of direct serialization or object-relational mapping
내부 상태 관리를 사실상 DBMS 안에 있는 테이블 구조에 맡기는 방식을 모노리식이라고 볼러도 될까요? 엄밀한 정의는 아니지만 우선 그렇게 부르겠습니다. 이때, 어떤 이유로든 (굳이 MSA라는 말을 꺼내고 싶지 않지만) 이벤트라고 정의한 어떤 방식으로 분산 프로그래밍으로 상태 관리를 해야 한다면 Event Sourcing 패턴이 제격인 상황이죠.
그런데, 저는 Event Sourcing에 대해서 개발자와 협업하면서 두 차례 반복해서 겪은 부작용이 있었습니다. 제가 아이디어만 제시하고 구현을 개발자에게 맡겼더니 (8년에 걸쳐) 두 명의 다른 개발자가 모두 event store 구현체나 Event Store와의 교류 방식에 초점을 둔다는 점입니다. 생각해 보면 당연한 일인데, 서로 입장이 달라 비즈니스 기능을 요구하는 제 입장에서는 '부작용'이라고 느껴진 것이죠.
그러한 시행착오 속에서 터득한 표현이 바로 <이벤트는 변경을 알리는 표준 프로그래밍 단위>입니다. 모노리식으로 혹은 CRUD로 사실상 RDBMS로 상태 관리를 하는 (마이크로) 서비스의 영역을 넘어서는 경계 바깥으로 변화를 전할 때는 이벤트를 표준 프로그래밍 단위로 쓰면 좋겠다는 생각이 들었습니다.
한 가지 예를 들면 다음과 같은 식이 되겠네요. 이를 테면 개발팀이 달라지는 경우가 생긴다면, 굳이 모든 프로그램을 같은 언어에 동일한 방식으로 짤 이유가 없어집니다. 그런 자유도를 실용적으로 활용하면서 프로그래밍의 정합성이나 데이터 상태 관리는 DBMS에 의존한다고 하면, 서로 자유도를 지닌 시스템 사이에서는 이벤트를 '변경을 알리는 표준 프로그래밍 단위'로 활용하는 일이 매우 간편한 해결책이란 생각을 할 수 있습니다.
연식이 된(?) 개발자분들은 배치(batch) 프로그램을 떠올리실 수 있습니다. 물론 기능적으로 동등하지만, DBMS 제약이나 스키마에 고정되는 결합도를 막기 위해서, 그리고 조금 더 비즈니스 관점의 명확성을 갖추기 위해서는 배치보다는 이벤트를 정의하고 활용하는 방식이 낫다고 생각합니다.
[1] <한국말 말차림법>에서 제안한 구절에 대한 토박이 말입니다. 왜 다발말인지는 <언어에 대한 일반이론>에서 일부 답을 얻을 수 있습니다.
[2] 무려 제가 대학에 입학하던 때 나왔던 책입니다.
1. 내가 아닌 다른 사람은 모델링을 왜 하게 되는가?