CQRS Boundary

쓰기 모델은 규칙을 지키고, 읽기 모델은 조회에 맞게 재구성한다

CQRS는 Command와 Query 클래스를 나누는 데서 끝나지 않는다. 변경 규칙, 이벤트 전파, Projection 재생성 가능성을 함께 설계해야 한다.

01 Command

상태 변경 의도

입력 검증 뒤 aggregate가 불변식을 검사하고 변경을 확정한다.

02 Event

변경 사실 기록

성공한 변경만 이벤트나 outbox에 남겨 후속 처리를 유도한다.

03 Projection

조회 모델 갱신

화면/API에 맞춘 read model을 만들고 지연과 재처리 경로를 관리한다.

구분 해야 할 일 섞이면 생기는 문제 NestJS 위치
Command변경 요청 권한, 유효성, 도메인 규칙, 트랜잭션 조회 최적화 코드가 쓰기 규칙을 오염시킴 CommandBus, CommandHandler
Event변경 결과 projection 갱신, 외부 통지, 재처리 단위 이벤트가 로그처럼 흐려져 복구 기준을 잃음 EventBus, outbox worker
Query조회 요청 필터, 정렬, 조인, 캐시, 검색 인덱스 읽기 최적화 때문에 쓰기 모델이 비대해짐 QueryBus, QueryHandler
지연 허용 쓰기 직후 조회가 잠시 늦어도 되는가

허용되지 않으면 read model 갱신을 동기화하거나 CQRS 범위를 줄인다.

재생성 Projection을 다시 만들 수 있는가

이벤트 로그나 원천 테이블 없이 캐시만 있으면 운영 복구가 어렵다.

비용 단순 CRUD보다 얻는 이점이 큰가

복잡한 도메인 규칙이나 읽기 부하가 없다면 분리 비용이 더 크다.

핵심: CQRS의 A급 설계는 “버스 사용 여부”가 아니라 쓰기 규칙, 이벤트, 조회 모델의 책임 경계가 실제 장애 상황에서도 추적되는지로 판단한다.