이렇게 CQRS패턴은 MSA 구조에서 자연스럽게 동시에 설계하게 되는 패턴이라고 생각해도 됩니다.
하지만 CQRS 는 복잡성을 안고가야 한다는 커다란 단점이 존재 합니다.
클래스 파일이 많아 진다는 복잡성…
코드 로직의 복잡성…
물리적으로 READ와 COMMAND DB가 분리 되어 관리 포인트 이중화…
DB가 나뉘어져 있으면 동기화는 어떻게…?
DB 동기화 처리를 위한 다시 또 등장하는 이벤트소싱 이란 기술
이벤트소싱을 처리 하기 위한 이벤트 메세징 처리 기술
MQTT? KAFKA?
관련하여 닷넷에서 CQRS패턴에 대한 오버엔지니어링에 대한 토픽을 공유해 드리고자 이 스레드를 생성 합니다.
그림을 보시면 매장에서 발생되는 주문 처리를 하기 위해 각 도메인 단위로 세세하게 서비스를 나뉠 수 있습니다.
[주문 접수] [결제처리] [User] … 등이 각 독립적으로 관리 및 운영되는 서비스로 MSA 형태라고 보시면 됩니다.
그중 [결제 처리 서비스]를 보시면 다시, 명령과 조회를 처리하는 하나의 작은 서비스 형태로 다시 나뉜 모습을 볼 수 있습니다.
↑↑ 이러한 설계 부분이 바로 CQRS 입니다.
이러한 상황에서 DB도 독립적으로 나뉘어지게 됩니다.
단순히 이렇게 DB를 나누어 놓기만 한다면 성능상 큰 이점을 보긴 어렵습니다.
때문에 보통 성능 최적화에 중점을 두어 Command와 Query 데이터베이스 목적에 맞게 데이터를 효율적으로 관리 합니다.
일반적으로 Command 데이터는 정규화로 데이터를 보관하고,
Query는 조회를 빠르게 하기 위해 정규화 하지 않고 조회에 필요한 모든 데이터가 모두 포함되어 있는 denormalize 상태로 NoSQL 을 사용하여 데이터를 보관 합니다.
이런 설계로 목표가 어느정도 뚜렸해 진다면 독립적으로 나누어진 DB를 어떻게 동기화 처리를 할 수 있는지에 대해 다음 목표 방향으로 자연스럽게 흘러가게 됩니다.
이때 백앤드 서버 진영에서 제시되는 방법중 하나가 [이벤트 드리븐 아키텍처] 의 하나중 MQTT나 Kafka 같은 이벤트 처리를 통한 동기화 기법 입니다.
이렇게,
DB 동기화까지 고려하여 설계를 하고 완벽하다고 볼 수 있겠지만 또 한가지의 고려대상이 튀어 나옵니다.
바로 데이터의 히스토리 관리를 어떻게 할지 고민이 생깁니다.
이전에 Query DB는 denormalize 상태로 데이터를 관리 한다고 설명 했습니다.
이런 데이터는 바로 데이터가 어떻게 생성 되어 졌는지에 대해 히스토리 추적이 불가능합니다.
예를 들어 취소된 주문 데이터에 대해 어떤 스탭으로 주문이 취소 되었는지 역추적 하기가 힘들다는 문제가 발생 되는 것이죠.
이때 또 다시 [이벤트소싱] 이라는 기법이 등장 합니다. [이벤트소싱] 은 이벤트 스토어를 별도로 두고
데이터를 최종적인 상태만을 기록하는 것이 아닌 이벤트가 발생되는 시점을 모두 기록해서 이벤트를 정주행 했을때 온전한 최종 상태를 볼 수 있다는 특징이 있습니다.
반대로 데이터 추적도 역주행으로 쉽게 가능하지요!
이렇게 MSA를 고려 했을때 자연스럽게 서비스간 통신을 위한
이벤트 드리븐 아키텍처 → CQRS → DB 동기화 → 이벤트 소싱 등등등 고려해야 할 부분이 많습니다.