CQRS에 대한 단상. Methodoloy

2009~2012년 언급되다 잠잠해졌는데 SNS에서 CQRS(집적모델/조회모델 분리)에 대한 글들이 보이길래 정리겸 싸 봄.

1. 간단한 도메인 모델과 아키텍처 - 문제없음.
일반적으로 도메인은 집적에 관여하는 엔터티나 조회에 관여하는 엔터티가 크게 다르지 않고, 이럴 때 컴포넌트 파티셔닝은 island of data(ref BCF. Oliver Sims)를 따르는게 보통이고 별 문제가 없다.
2. 복잡한 도메인 모델의 아키텍처 - 문제 봉착.
서로간의 데이터와 로직을 필요로 하는 경우 island of data적용엔 두가지 문제가 따른다.
첫째는, 집적모델과 조회모델간 간극 발생인데.. 데이터를 집적하고 처리하기 위한 로직은 강건하고 일관되며 변경이 없는 편인데 비해, 조회쪽은 도메인 전문가 입맛에 따라 컴포넌트/컨텍스트를 자유롭게 넘나들고 시시때때로 변한다. 집적모델과 조회모델간 간극이 생길 수 밖에 없다.(게다가 갈수록 복잡해진다)
둘째는, 성능상의 문제. A와 B 컴포넌트를 통해서 다수의 데이터를 조회한 뒤 C,D컴포넌트의 로직과 데이터로 필터링/조인해서 결과를 C, D, E컴포넌트를 이용해 집적하는 경우를 생각해 보자. (이런 경우는 흔하다) 이 경우 집적을 기준으로 파티셔닝된 모델로는 성능이 나올 수 없다.

그래서 보통은 분석/설계 과정에서 마스터 데이터와 로직을 갖는 쪽으로 컴포넌트/컨텍스트를 병합(aggregate or context 범위 확대)하기도 하고, 아키텍처 원칙에서 '예외적으로, ~의 경우에는 쿼리조인을 허용하고 조인된 쿼리는 별도의 리스트로 관리한다' 와 같은 식으로 접근한다. 10년전이나 지금이나 매한가지.. ㅇㅇ(쥬니어 개발자의 경우.. '쿼리로 처리하고 dao에서 호출하면 되는데 왜 굳이 아키텍처 원칙이 필요하죠?'란 의문을 갖게된다.)

3. CQRS - 집적모델과 조회모델 분리.
집적모델(CUD, 키데이터, 유효성 조회)과 구현은 island of data를 그대로 따르고, 조회모델(R)과 구현을 완전히 분리를 하면.. 집적을 기준으로 만들어진 모델은 조회때문에 혼란스러워 지지 않고, 조회는 성능을 갖는다.
물론, 성능을 얻지 못하고, 데이터 싱크, thread-safe에 대한 고민만 얻고, 모델과 늘어난 기술셋, 애매모호한 아키텍처 원칙에 개발자들의 혼란만 가중시킬 수도 있다. ㅇㅇ
4. SI프로젝트에서의 CQRS - 부분적인 적용. 리포트.
보통 시스템의 집적모델은 islandofdata, 조회는 파티셔닝과 아키텍처 원칙으로 조정, 리포트는 별도로 구분해서 아키텍처, 원칙, 구현을 달리한다. 리포트만 분리하고 조회모델을 분리하진 않아서 굳이 CQRS라고 명칭지을 수야 없지만 부분적으로 CQRS개념을 따르고 있다고 봐도 무방하다.(스펙일치, 유효성 검사, 키데이터 조회는 집적모델 사용, 컨텍스트를 넘나드는 조회성 내용은 별도의 아키텍처/구현/쿼리 허용)

5. 시스템 전체의 CQRS 적용 - 사례
집적과 조회가 다른 업무로 구분되고, 수행시점도 다르고, 이행하는 조직도 다른 경우에 적합하다. 가령 데이터를 집적한뒤 보험 조회서비스를 제공하는 보험 개발원이나 손해보험협회가 그러한 케이스. 대개의 경우 집적과 조회가 밀접해서 모델분리를 시스템 전체로 확대할만한 경우가 드물다. CQRS는 2011년에 20여명으로 구성된 소규모 프로젝트에서 적용했는데.. 업무, 수행시점, 이행 조직이 집적/조회로 구분되어 무난히 적용.

6. 받아들여지지 않는 이유
아키텍처는 환경과 편의성에 따른 선택의 하나고.. “적은 메커니즘을 일관되게 사용해서 목적한 바를 쉽고 신속하게 달성하는 것”이 원칙.그런데 CQRS의 경우 메커니즘은 늘어나는데 모호함, 쉽고 신속한지도 의문, 얻어지는 이득도 의문.. 그렇기에 쉬이 받아들여지지 않음.. Udi dahan이 'Clarified CQRS'를 뿌린지 햇수로 8년이지만 모델 분리가 일반화 되지 않은게 다 그런 이유..

6. 결론.
대규모 업무시스템을 구축하는 프로젝트에서 '조회모델의 아키텍처 원칙 파괴, 강건한 CUD모델을 갉아먹는 조회모델'은 반복적으로 등장하는 이슈겠지만.. 위와같은 이유로 모델을 분리하는건 앞으로도 쉽지 않을 듯.. 하지만, 분명 모델을 분리해야 하는 사이트는 언젠가는 만날테고.. 그럴때 도메인의 요구에 의해서 자연스레 모델을 분리할 수 있고, 그렇게 구축해도 별다른 문제가 없다는 것만 기억해도 이득. 
- 'CQRS를 도입하겠습니다'와 같은 접근은 금물, 집적과, 조회가 분리된 업무의 후보아키텍처로 생각하는게 바람직. 저장소 분리, 브로커, 캐쉬, 이벤트 소싱을 묶어서 별도의 아키텍처 셋으로 포장하는 경향이 있는데 그런 관점은 피해야하지않나 싶음.애초에 모델분리가 목적인데 성능향상, 별도의 아키텍처, 기술셋 채용이 우선이면 순서가 뒤바뀐 꼴.. 

패러다임에 빠지게 되면 최초의 목적을 상실하게 된다. Methodoloy

Anti-OOP: if를 피하는 법 링크의 글과 코드를 읽어보자.


일상화된 아키텍처(계약 : 계산식-비즈니스룰)를

객체지향적으로 구현하기 위해 계산식을 여러 객체로 분리해낸 모습이다.



적은 이득을 취하기 위해 주변 클래스들이 대량으로 늘어나는건 좋아하지 않는다.

단순한 코어에 인터페이스, 팩토리, 리파지토리, 전략, 정책, 유틸, 스펙, 커맨드, 

중계자, VO, DTO, 프로세스, 엔터티 끝도 없이 붙여나갈 수 있다.


이런 글이 있다. 10 Modern Software Over-Engineering Mistakes. 적당한게 좋다.


어쨌든.. 글의 내용을 간단히 구현하면 다음과 같이 된다.

1. 비즈니스 룰 부분(룰 해쉬, 룰 호출 함수)
- 룰 텍스트 : 상수, 함수를 키-값 해쉬형태로 기술. 함수를 람다함수로 직접기입하거나, 로컬변수를 텍스트로 참조가능
- 룰 함수 : "/"로 구분된 키로 호출
  : rule 아래쪽 두줄은 무시해도 무방(해쉬에 기입될 함수인데.. 로컬 함수 로딩 테스트 용도로 빼놓음)

2. 어플리케이션에서 사용
3. 테스트














상수와 계산식은 DICT 해쉬에 기술하고, 이를 호출하기 위한 함수를 구현하면

어플리케이션에서 rule[key]란 한 구절로 타입, arity 상관없이 편하게 호출할 수 있다.


결국, 실질적인 구현은 전체 어플리케이션을 위한 rule 함수1줄이 전부다..


* DDD에서도 언급하지만 상수, 복잡한 계산식은 비즈니스 룰로 다루는게 편하다.
 si에서는 정책성 상수/계산식을 룰엔진으로 분리하는 아키텍처가 10년 이상 일반화 되어 있다.

* 비즈니스 요건은 단순한데 레이어나 클래스가 3~8개씩 늘어나는 경우가 있다.
  조와 관련된 주변 클래스들이 늘어나는건 언제나 주의해야 한다. 

* 혼란을 느낄 수 없는 환경. 일정에 쫓겨.. 그럴듯한 것을 배재할 수 밖에 없는 상황)에서 
  개발자들이 수용할 수 있는 아키텍처가 진실로 괜찮은 아키텍처의 첫걸음이 아닐까 싶다. 

How Agile and OO have lost their way together Methodoloy

Robert C. Martin이 5년전쯤 

Midwest에서 했던 발표이래 가장 괜찮은 OO / Agile 발표자료.


이것저것 다양한 것들을 말하지만 허튼 소리가 한마디도 없다.

반대로 말하면 그만큼 맹종이 널리 퍼져있다는 얘기가 되겠지만 말이다.


찬찬히 정리해야겠다.


1 2 3 4 5 6 7 8 9 10 다음