도메인 기반 개발 요약 시작하기 – CQRS 패턴

시스템에서 제공하는 기능은 크게 두 가지 범주로 나눌 수 있습니다.

1. 상태 변경 기능

ex) 신규 주문 생성, 배송정보 변경

2. 상태 정보 조회 기능

ex) 주문내역 조회, 회원정보 조회

도메인 모델 관점에서 상태 변경 기능은 주로 하나의 집계 상태를 변경합니다. 예를 들어 주문 취소 기능과 배송 정보 변경 기능은 하나의 주문 집계를 변경합니다. 반면에 조회 기능에 필요한 데이터를 표시하려면 둘 이상의 수집기가 필요한 경우가 많습니다.

단일 모델에서 양쪽 끝의 기능을 구현하면 상태를 변경하는 범위와 상태를 검색하는 범위가 정확히 일치하지 않기 때문에 모델이 불필요하게 복잡해집니다. CQRS는 이러한 복잡성을 해결하는 데 사용되는 방법입니다.


CQRS

상태를 제공하는 쿼리에 대한 모델에서 상태를 변경하는 명령에 대한 모델을 분리하는 패턴인 명령 쿼리 책임 분리.


CQRS 패턴 https://martinfowler.com/bliki/CQRS.html

CQRS는 복잡한 도메인에 적합합니다. 도메인이 복잡해짐에 따라 명령 기능과 조회 기능에서 처리하는 데이터의 범위에 차이가 있습니다.

이 두 함수를 단일 모델로 취급하면 조회 함수의 로딩 속도에 필요한 것보다 모델 구현이 더 복잡해집니다. CQRS 패턴은 둘을 구분합니다.


조회할 모델을 위와 같이 분리하면 복잡한 Join, SubQuery, N+1 문제 등 조회와 관련된 문제를 줄일 수 있습니다. 또한 검색에 최적화된 별도의 DB구축이 용이하다.

데이터베이스가 분리되어 있으면 데이터베이스 간의 동기화가 문제가 되며 이벤트를 사용하여 처리됩니다. 명령 모델에서 상태가 변경되면 해당 이벤트가 발생하고 해당 이벤트를 쿼리 모델로 전달하여 변경 사항을 반영합니다.

그러나 동기화를 실시간으로 해야 하는 경우 동기 이벤트와 글로벌 트랜잭션을 사용해야 하지만 전체적인 성능(응답 속도 및 처리량)이 저하됩니다.

단, 실시간 동기화가 되지 않는 영역이 있다고 가정해 봅시다. 예를 들어, 통계 데이터. 검찰, 분, 시 단위로 최신 자료를 반영하는 것이 문제가 되지 않을 때가 있다. 이 경우 데이터를 비동기적으로 보내면 데이터 동기화로 인해 명령 모델의 성능이 저하되지 않도록 할 수 있습니다.


웹 및 CQRS

일반적인 웹 서비스에서는 상태를 변경하는 것보다 상태를 검색하는 요청이 더 많습니다. 예를 들어, 주문 요청보다 상품 상세 정보 조회 요청이 비교할 수 없을 정도로 많습니다.

검색 기능에 대한 요청 비율이 매우 높기 때문에 개발팀은 검색 성능을 향상시키기 위해 다양한 기술을 사용합니다. 쿼리 최적화, 캐싱 또는 조회 전용 저장소는 별도로 사용할 수 있습니다.

많은 양의 트래픽을 발생시키는 웹 서비스는 자신도 모르게 CQRS를 적용합니다. 명령/쿼리 모델을 명시적으로 분리하지 않습니다.


CQRS 장단점

CQRS 패턴 적용의 장점은 명령 모델을 구현할 때 도메인 자체에 집중할 수 있다는 것입니다. 쿼리 성능 향상에도 유리합니다.

반면 단점도 있다. 단점은 구현할 코드가 더 많다는 것입니다. 또한 더 많은 구현 기술이 필요할 수 있습니다. 조회 모델을 별도로 구현하기 위해 다른 데이터베이스를 사용하거나 데이터 동기화를 위해 메시징 시스템을 도입해야 할 수 있습니다.