CQRS는 Command and Query Responsibility Segregation(명령과 조회의 책임 분리)을 나타냅니다. 커맨드 ( Create - Insert, Update, Delete : 데이터를 변경) 와 쿼리 ( Select - Read : 데이터를 조회)의 책임을 분리한다는 것을 뜻합니다. CQRS는 네이밍에서 알 수 있듯이 명령과 쿼리의 역할을 구분 한다는 겁니다.
너무 단순하다고 생각될지 모르겠지만 이것이 전부입니다. 어쩌면 CQRS에 대한 오해는 CQRS가 생각보다 복잡하지 않기 때문일지도 모릅니다. 이 단순한 규칙이 몇 가지 응용기술과 조합되어 시스템에 적용되면 그 모습은 무척이나 다양합니다. 그만큼 CQRS를 설명하는 정보들이 표현하는 구현체의 모습이 제각각이고 여기서 혼란이 시작될 가능성이 있습니다.
Martin Fowler 형님께서 이미 2011년도에 이야기 하셨던, 등장한지는 조금 오래된 패턴입니다. Martin Fowler는 스택 자료구조의 pop() 연산을 예로 들었습니다. 참고주소 (참고로 버란트 마이어(Bertrand Meyer) 의 CQS가 CQRS의 출발 이었고, CQRS를 처음 소개한 이는 Greg Young 이라고 합니다.)
사업이 점점 번창하게 된다면, 전통적인 CRUD 아키텍처 기반에서 Application을 개발 및 운영하는 개발자들에게는 자연스레 Domain Model의 복잡도가 증가될 겁니다. 그리고 그로 인하여 히스토리를 간직해야할 유지보수 Cost는 지속적으로 증가하게 되며 Domain Model은 점점 설계 시 의도한 방향에서 벗어나게 될 겁니다. 모든 연산이 명령과 조회로 쉽게 양분되지는 않겠지요.
개념적으로 어려운 경우도 있고 동시성 등 기술적인 문제도 있습니다.
이런 일련의 변경사항과 흐름을 곰곰히 관찰해 보며, 단순 검색 및 조회만 하면되는 데이터를, 비즈니스 로직이 거대해지면서 CUD에 의해 변경되는 도메인모델들이 의미없이 늘어나며, 그 모델들을 조인해서 가져와야하는 단순 검색결과들 또한 거대해지게 됩니다.
그리고 그 해답으로 나온 것이 CQRS 입니다. 바로 명령을 처리하는 책임과 조회를 처리하는 책임을 분리 구현 하자는 취지가 바로 이것입니다. CQRS에서 명령은 시스템의 상태를 변경하는 작업을 의미하며 조회는 시스템의 상태를 반환하는 작업을 의미합니다. 정리하면, CQRS는 시스템의 상태를 변경하는 작업과 시스템의 상태를 반환하는 작업의 책임을 분리하는 것입니다.
전통적으로 사용하는 CRUD 모델의 경우 데이터를 갱신하기 위해서는 데이터 저장소에서 해당 데이터를 가져오는 작업이 필요합니다. 동시성 문제가 나타날수도 있고, 확장성을 낮추는 문제점을 지닌 지점이 되기 쉽습니다.
CQRS 의 경우 어떻게 보면 일련의 이벤트를 통해 데이터를 조작하는 접근방식이 될 수 있겠습니다. 데이터에 영향을 주는 모든 동작을 이벤트라는 저수준의 데이터로 관리하는 것으로 여러 문제를 해결할 수 있습니다.
Testing Your Message-Driven Application by Jakub Pilimon @ Spring I/O 2018
서울에서 SPRING ONE 세미나에 참석해서 집적 들어봤습니다. 그때는 우리 솔류션에 적용하기 힘들 것같다고 생각했는데, 어느순간 적용가능한 시점이 다가온거 같네요.
계속 반복해서 이야기하지만, 이름처럼 CQRS는 시스템에서 명령을 처리하는 책임과 조회를 처리하는 책임을 분리하는 것이 CQRS의 핵심입니다.
CQRS를 설명할 때 명령 처리기 패턴(Command Processor Pattern)을 얘기하기도 하고 다른 경우는 다계층 아키텍처(Multitier Architecture)나 이벤트 소싱(Event Sourcing)을 다룹니다. 이것들 모두와 DDD(Domain-Driven Design)를 조합하기도 합니다.
CQRS를 처음으로 소개한 Greg Young은 CQRS는 아주 단순한 패턴(“CQRS is a very simple pattern”)이라고 말했습니다. 경우에 따라 이미 실천하고 있을지도 모릅니다.