본문 바로가기
BackEnd

CQRS Pattern

by oncerun 2023. 2. 2.
반응형

마틴 파울러의 CQRS를 읽어보자.

 

CQRS는 Command Query의 책임을 분리하는 것이다.

 

Query는 상태를 변경하지 않는 결과를 반환하는 것 ( 사이드 이펙트가 없음)

 

Commands는 상태를 변경하지만 결과를 반환하지 않는 것

 

마틴 파울러는 CQRS의 핵심은 서로 다른 모델을 사용하여 데이터의 갱신, 추가와 조회를 개별 적은

로 분리하는 것을 의미합니다.

 

하지만 이는 일부 상황에서 CQRS는 효율적이고 대부분의 시스템에서는 위험한 복잡성을 추가하는

것과 같다고 합니다.

 

이러한 주장에서 우리가 알아보아야 할 것은 무엇일까요?

 

바로 어떠한 상황에서 CQRS 패턴은 효율적인지 확인해 보아야 합니다.

 

또한 왜 대부분의 시스템에서는 명령과 조회의 책임을 분리함에 따라 복잡성을 낮추는 것이 아니라

증가시키는지 알아보아야 합니다.

 

서비스의 요구사항은 항상 발전합니다.

 

과거에 적합했던 모델은 서비스가 발전함에 따라 초기 모델과는 다르게 더 정교하고 복잡하게 변해버릴 수 있습니다.

 

그렇기 때문에 우리는 여러 데이터를 가진 모델을 좀 더 세분화해서 사용하고 싶거나 여러 데이터를 하나로 축소하거나 결합하여 데이터를 추출해야 하는 일이 많아질 수 있습니다.

 

업데이트 측면에서는 특정 데이터들만 조합해서 저장하거나 가공되어 입력값과 완전히 다른 값이 저장되거나 업데이트될 수 있습니다.

 

서비스가 발전함에 따라 개발자는 하나의 모델을 다양한 모델로 나누어 보기 시작합니다.

 

사용자가 서비스를 이용할 때는 이렇게 다양하게 나누어진 모델을 조회하고 사용하게 됩니다.

 

분명 이러한 모델을 서로 다르지만 근원지는 하나의 모델일 것입니다.

 

개발자는 일반적으로 도메인의 핵심 요소를 가지도록 개념적으로 모델을 구축합니다.

 

그러한 모델은 데이터베이스의 모델과 굉장히 유사한 형태를 가지도록 구성됩니다.

 

실제 사용자와 상호작용하는 UI는 매우 빠르게 복잡해질 수 있는 구조를 가질 수밖에 없습니다.

그럼에도 불구하고 여전히 우리는 모든 표현에서 사용되는 단일 통합 모델을 가지고 이 문제를 해결하려 합니다.

conceptual model이라는 단어가 자꾸 나오는데 이는 시스템을 이해하고 설계할 때 도움을 주는 추상적인 표현이라고 한다.

기본 구성 요소, 이들 간의 관계, 그들의 동작을 규정하는 규칙을 정의하는 모델로 예를 들면 데이터 베이스 설계 시 개념적 설계와 비슷한 역할을 하는 것 같다.

 

그렇다면 개념적으로 모델을 분리한다는 것을 어디까지 반영해야 할지 고민이 된다.

 

CQRS가 소개하려는 변화는 conceptual model을 update model과 display model로 분리하려는 것으로 Command와 Query라는 용어를 사용합니다.

 

CQRS의 이론적 근거는 복잡한 도메인에서는 Command와 Query에 대한 개념의 모델이 같은 경우 모델이 더욱 복잡해져 둘 다 잘 수행되지 않을 수 있다는 것입니다.

 

분리된 모델에 의해 우리는 다른 object model을 사용하게 되고 이는 마치 다른 하드웨어에서 서로 다른 논리 프로세스에서 진행되는 것으로 판단할 수 있다.

 

웹에서는 쿼리 모델을 사용해 UI를 렌더링 하고 변경 사항을 처리하기 위해 별도의 명령 모델로 변경 사항을 저장합니다.

 

이는 다시 업데이트된 결과를 쿼리 모델로 조회하여 제공합니다.

 

CQRS에서는 다양한 방식이 사용될 수 있습니다. 동일한 데이터 표현 방식을 사용하는 경우 이는 동일한 데이터베이스를 공유하기 때문에 서로 소통할 수 있습니다.

 

또는 서로 다른 데이터베이스를 사용하여 각각의 표현 방식을 구성하고 쿼리 모델 측의 데이터베이스를 통계 데이터베이스로 사용할 수 있습니다.

이러한 경우 데이터베이스 간의 동기화 작업이 필요합니다. 두 모델은 별개의 모델이 아닐 수도 있습니다.

 

관계형 데이터베이스 View와 같이 동일한 객체가 Command 모델과 Query 모델에 대해 서로 다른 인터페이스를 가지도록 할 수 있습니다.

 

하지만 보통 CQRS라고 하면 이들을 별개의 모델로 취급하는 것을 말합니다.

 

CQRS를 사용하면 자연스럽게 다른 아키텍처 패턴과 일치하게 됩니다.

 

1. 하나의 데이터 모델에서 멀어짐으로써 CRUD기반의 단일표현의 상호작용보다는 task-based UI 접근 방식으로 가까워지는 것이 더 쉽습니다. task-based UI는 사용자가 수행하려는 작업(task)을 기준으로 UI를 구성하는 것을 말합니다.

 

2. CQRS는 event-based programming models과 잘 어울립니다. CQRS 패턴을 이용하는 경우 Event Collaboration을 통해 통신하는 별도의 서비스로 분리되는 경우가 많습니다. MSA 아키텍처에 CQRS 패턴이 자주보이는 이유 중 하나입니다. 이를 통해 쉽게 Event Sourcing의 이점을 가질 수 있다는 것입니다.

 

3. CQRS 방식에서 Command과 Query 모델이 분리되어 있다는 것은 두 모델이 상호 동기화 되는 것이 어렵다는 것을 의미합니다. 그래서 일관성을 위해 일정 시간이 지난 후에 두 모델이 상호 동기화되는 eventual consistency 기법을 사용할 수 있습니다.

eventual consistency는 분산 시스템에서 사용되는 정합성 모델로 데이터의 정합성이 최종적으로 보장될 것을 의미합니다.

즉 시스템의 모든 노드가 동일한 데이터를 갖게 되는 것은 시간이 지날수록 보장될 수 있다는 것을 말합니다.

 

4. 많은 도메인의 경우 업데이트 시 꽤 많은 비즈니스 로직이 필요합니다.

이 경우 EagerReadDerivation을 사용하여 쿼리 모델을 단순화하는 것이 필요할지도 모릅니다.

 

5. CQRS는 복잡한 도메인에 적합하며 도메인 주도 설계의 이점도 있습니다.

When to use it

다른 패턴들과 마찬가지로 CQRS는 어떤 곳에서는 유용하고 다른 곳에서는 유용하지 않을 수 있습니다.

 

많은 시스템이 CRUD mental model에 적합하기 때문에 CRUD의 스타일로 진행되는 것이 옳을 수 있습니다.

 

CQRS라는 개념을 도입한 사례를 보았을 때 CQRS가 소프트웨어를 더 어려운 방향으로 이끌고 있는 상황도 많이 보았습니다.

 

그렇기에 CQRS를 도입하기 전에 CQRS가 주는 이익과 손실에 대해 깊이 고민해 볼 필요가 있습니다.

 

특히 CQRS는 시스템 전체가 아니라 DDD의 바운디드 콘텍스트에만 사용되어야 한다.

이러한 사고방식에 따르면 각 바운디드 콘텍스트는 모델링 방법에 대한 결정이 필요합니다.

 

지금까지 CQRS는 단 두 가지 방법을 통해 이점을 얻었다고 보는데,

첫 번째는 복잡한 도메인을 CQRS를 통하여 더욱 유연하게 다룰 수 있다는 것.

그리고 이러한 경우가 매우 소수의 케이스라는 것이다. 왜냐하면 command와 query 간의 중복되는 공통점이 상당히 많기 때문에 모델을 공유하기가 매우 쉽기 때문이다.

 

적합한 상황이 아닌 도메인에서 CQRS를 적용하면 복잡성을 추가하고 그 결과 생산이 감소하며 위험성을 올라갈 수 있습니다.

 

또 다른 주요 이점은 고성능 애플리케이션을 처리하는 데 있다. CQRS를 사용하면 읽기 및 쓰기에 대한 로딩이 분리되어 개별적으로 확장될 수 있다.

 

만약 애플리케이션에서 읽기와 쓰기의 차이가 매우 큰 경우 CQRS는 매우 유용할 수 있습니다.

 

또한 양쪽에 다른 최적화 전략을 적용할 수도 있다. 예를 들어 읽기는 속도가 빠른 RealTimeDatabase를 사용하고 쓰기는 RDB를 사용하는 방식을 이용하는 것입니다.

 

이러한 이점에도 불구하고 CQRS 사용에 매우 주의해야 합니다. 많은 시스템은 사실 읽기와 쓰기의 모델이 대부분 잘 맞아떨어진다.

 

이런 시스템에 CQRS를 추가하면 상당한 복잡성을 추가할 수 있다.

 

CQRS는 좋은 패턴 중 하나이지만 이는 적절한 환경에서 사용할 수 있도록 노력해야 한다.

반응형

'BackEnd' 카테고리의 다른 글

🛠️ Swagger ?  (0) 2023.07.12
SSH 접속 불가  (0) 2023.03.15
Prometheus & Grafana  (0) 2023.02.17
Monitoring  (0) 2023.02.16
Event  (0) 2023.01.30

댓글