CQRS란?
CQRS
Command and Query
- 명령
- 시스템 데이터 변경
- 예) 주문 취소, 배송 완료
- 쿼리
- 시스템 데이터 조회
- 예) 주문 목록
Responsibility Segregation
- 책임
- 구성 요소의 역할
- 예) 클래스, 함수, 모듈, 서버, DB, 컨테이너
- 분리
- 역할에 따라 구성 요소 나누기
CQRS가 왜 좋다는 걸까?
위 이미지는 CQRS의 예를 간단하게 나타낸 것이다.
코드가 중복되는 느낌과 개발이 느려지는 느낌인데 CQRS는 뭐가 좋다는걸까?
명령과 조회에 단일 모델을 사용하는 경우
한 모델에 이것 저것 기능을 추가하니 코드가 뒤섞였다.
-
코드 역할/책임 모호
-
의미/가독성 등 나빠짐
-
유지보수성이 떨어짐
Member 클래스는 더 이상 Member 테이블에 대응하는 모델이 아닌
로그인 로직, Order 테이블과도 엮여있다.
가장 나쁜 부분은 기능에 따라 사용하는 필드가 달라진다는 것이다.
단일 모델로 복잡해지는 예시) JPA
기능에 따라 연관을 로딩하는 방식이 달라져야 한다.
이렇게 단일 모델을 유지하려고 노력하다 보면 다른 부분에서 복잡한 일이 발생한다.
1) 명령과 쿼리는 다루는 데이터가 다르기 때문이다.
- 명령 → 한 영역의 데이터
- 쿼리 → 여러 영역의 데이터
2) 명령과 쿼리는 코드 변경 빈도, 사용자에 따라서도 다르다.
- 예시
- 백오피스의 주문 목록 조회 기능
- 사용자의 주문 기능
변경 빈도가 다른 기능이 한 코드에 있으면 서로 다른 이유로 코드가 바뀌고
이는 곧 책임의 크기가 적당하지 않다는 것이다.
(단일 책임 원칙을 따르지 않는 코드가 생성되는 것)
3) 기능마다 성능 요구가 다르다.
- 기능마다 트패픽 패턴, 성능 요구 다르다.
- 사용자의 상품 목록 조회, 상품 상세 조회
- 백오피스의 판매 수치
- 기능마다 서로 다른 성능 향상 방법 필요
- 단일 모델로는 다양한 성능 향상 기법 적용이 어려울 수 있다.
명령과 쿼리를 구분하자.
명령과 쿼리를 위한 모델을 분리하면 모델의 모호함이 없어진다.
명령 영역의 모델과 쿼리 영역의 모델이 무엇을 표현하고 있는지 명확해져 코드 가독성과 유지보수성이 좋아질 가능성이 높아진다.
예를들어 쿼리는 캐시, 명령은 비동기를 사용하는 방식으로 성능 향상 기법을 다르게 적용하는 것도 가능해진다.