2022-11-16-TIL
2022-11-16-TIL
Today I Learned
CQRS
CQRS(Command Query Responsibility Segregation)는 데이터를 바꾸는 쪽(command)과 읽는 쪽(query)에 서로 다른 모델을 쓰는 패턴이다. Martin Fowler는 정보를 갱신할 때 쓰는 모델과 읽을 때 쓰는 모델을 다르게 가져가는 것이라고 정의하고, Greg Young이 처음 설명한 개념이라고 소개한다. 이름은 Bertrand Meyer의 CQS(Command Query Separation)에서 왔다(Fowler: CQRS). CQS는 객체의 메서드를 상태를 바꾸지 않고 결과만 돌려주는 query와, 상태를 바꾸지만 값을 돌려주지 않는 command로 나누라는 원칙이다(Fowler: CommandQuerySeparation). 메서드 수준의 이 구분을 모델과 저장소 수준까지 넓힌 것이 CQRS다.
왜 나누는지는 Microsoft의 설명이 구체적이다. 하나의 모델로 읽기와 쓰기를 모두 처리하면 다음 문제가 생긴다(Azure Architecture Center: CQRS pattern).
- 읽을 때 필요한 형태와 쓸 때 필요한 형태가 달라 모델이 어정쩡해진다.
- 같은 데이터에 읽기와 쓰기가 몰려 락 경합이 생긴다.
- 조회 화면에 맞춘 복잡한 쿼리가 쓰기 모델의 성능까지 끌어내린다.
CQRS에서 command는 “예약 상태를 RESERVED로 바꾼다”가 아니라 “객실을 예약한다”처럼 업무 의도를 담고, 검증과 도메인 로직을 거친다. query는 데이터를 절대 바꾸지 않고 화면에 맞는 DTO만 돌려준다. 단계는 두 가지로 나눌 수 있다. 한 데이터베이스를 쓰면서 코드상 모델만 나누는 방식과, 읽기 전용 저장소를 따로 두고 쓰기 쪽이 발행한 이벤트로 읽기 저장소를 갱신하는 방식이다.
1
2
3
4
5
[Client] --command--> [Write Model] --> [Write DB]
|
event
v
[Client] <--query--- [Read Model] <-- [Read DB (조회용 뷰)]
저장소를 나누면 읽기 쪽은 쓰기 직후의 변경을 바로 보지 못할 수 있다(최종 일관성). 메시지 실패, 중복, 재시도도 처리해야 한다. 그래서 두 문서 모두 도메인이 단순하고 CRUD로 충분한 곳에는 맞지 않는다고 말한다. Fowler는 특히 시스템 전체가 아니라 복잡도나 성능 요구가 큰 일부 영역에만 적용하라고 경고한다.
“You should be very cautious about using CQRS.”
- https://justhackem.wordpress.com/2016/09/17/what-is-cqrs/
- https://learn.microsoft.com/en-us/azure/architecture/patterns/cqrs
댓글
아직 댓글이 없습니다