Command Query Responsibility Segregation 의 앞글자를 따서 CQRS
간단하게 파악해보기..
간단하게 생각하자면? 데이터 저장소로부터의 읽기와 업데이트 작업을 분리하는 패턴
: 코드만 분리하는 것은 아님. 구현 방식, 규모에 따라 DB나 프로세스를 나누기도 한다.
정리를 해보자면?
명령(시스템 데이터 변경)을 책임지는 요소를 Segregation.
쿼리(시스템 데이터 조회)역할을 책임지는 구성 요소를 Segregation
명령과 조회에 단일 모델을 사용한다면? - 필요한 필드가 점점 늘어나게됨
-> 코드의 역할/책임이 모호,
-> 의미/가독성 나빠짐
-> 유지 보수성이 떨어짐
-> 기능에 따라 필요한 필드가 달라진다
오히려 분리할때 보다 더 복잡하다
JPA를 사용할때 연관관계에 있는 테이블의 로딩 전략, Eager , Lazy 에 따른 복잡성.
명령과 쿼리는 다루는 데이터가 다르다.
- Command : 한 영역의 데이터
- Queury : 여러 영역의 데이터
Command Query는 코드 변경 빈도, 사용자도 다름
ex ) 사용자의 주문 기능, 백오피스의 주문 목록 조회 기능
이렇게 변경 빈도가 다른 기능이 한 코드에 있다면?
- 서로 다른 이유로 코드가 변경.
- 책임의 크기가 맞지 않다(단일 책임 원칙 위배)
기능마다 성능 요구가 다름
- 트래픽 패턴, 성능 요구 다름
(ex : 상품 조회(빨라야됨), 상품 등록, 주문, 판매수치 확인(조금 느려도됨..))
-기능마다 서로 다른 성능 향상 방법 필요(단일 모델로는 다양한 성능 향상 기법 적용이 어려움)
ex) 상품 목록을 레디스 같은 곳에 캐싱 -> 쿼리 모델은 레디스를 사용
보통 MSA 서비스의 형태에서 많이 접할 수 있는 구조.
명령과 쿼리가 다른 DB를 사용하게된다면?
명령에서 일어난 변동사항을 쿼리쪽에 알맞게 전달해야 한다. 여러가지 전달 방법이 있다
3가지 방법 정도를 알아 보겠다.
2번째 방식과 비슷하지만, 명령쪽 코드에서 변경내역을 따로 저장하지 않아도 됨.(명령 코드 단순)
마찬가지로 메시징을 두는 변형방식이 존재
변경전파 CDC에 대해 더 알고 싶다면? - (사용하는 DB) change data capture 로 검색해보면 좋다고 한다.
Command 와 Query가 다른 DB 사용시 주의사항
데이터 유실 : 유실 허용 여부에 따라 DB 트랜잭션 범위 중요.
허용 가능 지연 시간 : 명령의 변경 내역을 얼마나 빠르게 쿼리 쪽에 전달해야 하는가에 따라 구현의 선택이 달라질 수 있다.
중복 전달 : 중복으로 데이터를 전달하더라도 쿼리쪽 데이터가 망가지지 않도록 처리해야함
다른 주의점도 많다. 이와 관련해서는 Messiging에 대해 알아보자
CQRS 에 대한 글
https://martinfowler.com/bliki/CQRS.html
https://gist.github.com/meigwilym/025f08208b5640ad26bc410c8a83b10f