CQRS(Command Query Responsibility Segregation) 패턴
기타

CQRS(Command Query Responsibility Segregation) 패턴

CQRS 패턴이란?

Command Query Responsibility Segregation의 약자로 명령 조회 책임 분리로 해석된다. 조금 더 쉬운 말로 하면 데이터 저장소에 대한 읽기(R) 및 업데이트(CUD) 작업을 구분하는 패턴이라는 의미다. Read 작업을 하나로 묶고, Create, Update, Delete 작업을 하나로 묶는다!

 


CQRS 패턴을 사용하게 되었을까?

 

이는 R과 CUD의 서로다른 특징 때문이다. 기존의 아키텍처(하나로 되어있는)에서는 R과 CUD의 구분없이 동일한 데이터 모델을 사용한다. 간단한 CRUD 작업에서는 이 방식이 좋을 수 있다. 하지만 만약 애플리케이션이 복잡해진다면? Read는 보통 일반적인 CUD의 DTO와 다르게 생긴 DTO를 return 한다(필요한 데이터들 등..). 여기서 Object 매핑이 복잡해질 수 있다. 그리고 Create, Update, Delete('쓰기' 과정이 들어가는 부분)를 할 때 Read와는 다르게 데이터 모델 쪽에서 복잡한 validation 및 비즈니스 논리를 가질 수 있다. 이렇게 R과 CUD의 작업에 대한 차이로 인해 CQRS를 사용하면 분리를 함으로써 이득을 얻을 수 있다.


CQRS 패턴을 사용함으로써 얻는 장점

  • R과 CUD 각각에 최적화된 데이터 스키마를 사용해서 성능을 향상시킬 수 있다.
  • 관심사를 분리함으로써 복잡한 비즈니스 로직은 CUD쪽 모델로 이동해서 R 모델은 간단해진다.
  • R과 CUD에서 필요한 데이터 형식이 다를 수 있는데, CQRS 패턴을 사용함으로써 R로 인해 Entity의 구조가 변경되는 것을 막을 수 있다.

그럼 CQRS는 언제 사용하면 좋을까? 

  • 여러 사용자가 동일한 데이터에 동시에 접근하는 공동 작업 도메인인 경우. CQRS를 사용하면 Command를 충돌을 최소화하는 방향으로 정의하거나 발생한 충돌을 Command로 병합될 수 있다.
  • 여러 단계를 거치거나 복잡한 도메인 모델을 사용하는 인터페이스. 이유는 위에서 설명한 R과 CUD의 서로 다른 특징과 같다.
  • 읽기 수가 쓰기 수보다 훨씬 큰 경우. 두 모델을 별도로 조정할 수 있다.
  • 개발자가 나뉘어서 쓰기 모델, 읽기 모델에 집중할 수 있는 경우
  • 시스템이 시간에 따라 변화하면서 여러 버전의 모델을 포함할 수 잇거나 비즈니스 규칙이 정기적으로 변하는 경우

이와는 반대로 도메인이 간단한 경우에는 CQRS 패턴이 권장되지 않는다.


그럼 CRUD 패턴을 어떻게 적용할 수 있을까?

 

전통적인 CRUD 계층 구조는 다음과 같다.

http://auconsil.blogspot.com/2013/08/cqrs-command-query-responsibility.html

이러한 계층 구조에 CQRS 패턴을 적용하는 방법에는 크게 3가지가 있다.

 

1단계

http://auconsil.blogspot.com/2013/08/cqrs-command-query-responsibility.html

가장 간단하게 적용할 수 있는 방식이다.

단일 Data Store에 Command와 Query Model을 분리했다.

이렇게 구현하면 DB를 분리하지 않고 단순 model만 분리했기 때문에 단순하게 CQRS 패턴을 적용할 수 있다는 장점이 있지만 동일한 DB를 사용에 따른 성능상 문제점을 개선하지 못한다.

 

2단계

http://auconsil.blogspot.com/2013/08/cqrs-command-query-responsibility.html

DB까지 분리한 구조이다.

Command용 DB와 Query용 DB를 분리하고 별도의 Broker를 통해 데이터 동기화처리를 하는 방식이다.

서로 다른 DB를 가지기 때문에 각 시스템에 맞는 DB를 선택할 수 있다는 장점이 있고 1단계에서의 성능 관점의 문제를 해결할 수도 있다. 하지만 동기화 처리를 위한 Broker의 가용성과 신뢰도가 보장되어야 하는 리스크가 존재한다.

 

3단계

https://kariera.future-processing.pl/blog/cqrs-simple-architecture/

이벤트 소싱을 적용한 구조이다.

이벤트 소싱이란 간단하게 말하자면 모든 앱 내의 activity를 이벤트로 전환해서 이벤트 스트림을 별도의 DB에 저장하는 방법을 말한다. 사용자가 온라인 서점에서 책을 주문한다고 가정해보자. 1번 책을 사고 -> 취소하고 -> 2번 책을 샀다고 할때, 기존의 방식이라면 우리는 결과적으로 2번 책을 샀다는 값만 저장하게 된다. 하지만 이벤트 소싱 방식에서는 '이벤트' 그 자체를 저장하므로 '1번 책을 주문', '1번 책 주문을 삭제', '2번 책을 주문' 이 데이터를 모두 저장한다.

이벤트 소싱의 이벤트 스트림은 오직 추가만 가능하고, 이 데이터를 필요로 하는 시점에 구체화 단계를 거쳐 조회대상 데이터를 작성하므로 CQRS의 모델 분리 관점과 궁합이 잘 맞아 많이 사용한다.

 

 

결론

CQRS 패턴의 기본 개념과 어떻게 쓰이는지, 어떤 장단점이 있는지 살펴봤다.

지금 실무에서 사용하고 있는 패턴이긴 하지만 아직 프로젝트 초반이고 익숙하지 않아서 충분히 경험해보고 공부해본 뒤 내용을 좀 더 추가하면 좋을 것 같다:)

 

추가로,

이벤트에 대해 좀 더 공부해보고

https://www.youtube.com/watch?v=BnS6343GTkY

이 영상도 함께 보면 좋을 것 같다.

 


Reference

https://docs.microsoft.com/ko-kr/azure/architecture/patterns/cqrs

https://www.popit.kr/cqrs-eventsourcing/

http://auconsil.blogspot.com/2013/08/cqrs-command-query-responsibility.html

https://mjspring.medium.com/%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EC%86%8C%EC%8B%B1-event-sourcing-%EA%B0%9C%EB%85%90-50029f50f78c

728x90
반응형