CQRS
CQRS 의 개념
Command Query Responsibility Segregation, 아키텍처 설계 중 “쓰기” 작업과 “읽기” 작업을 분리하도록 설계하는 방법입니다.
이를 통해 쓰기, 읽기 각 작업에 특화된 기술을 적용하여 성능적 이점을 얻는 것을 가장 큰 목표로 합니다.
가장 약한 CQRS 로는 코드적으로 쓰기 기능과 읽기 기능을 분리하는 것 부터 시작해,
쓰기 전용과 읽기 전용으로 데이터 저장소를 분리하는 강한 CQRS 까지 있습니다.
CQRS 용어 뜯어보기
- Command : 시스템의 상태를 변경하는 Create, Update, Delete 작업. 즉, 쓰기 작업
- Query : 데이터를 조회하는 작업. 즉, 읽기 작업
- Responsibility : 책임
- Segregation : 분리
Command(쓰기) Query(읽기) 작업 책임 분리 시스템 아키텍처 패턴
도식으로 알아보기
본 CQRS 는 가장 강한 단계의 CQRS 로, 쓰기 저장소와 읽기 저장소가 분리된 예시입니다.
(1) Command (C/U/D) 요청이 발생함
(2) Command 작업이 비즈니스 로직에 따라 실행됨
(3) Write DB (쓰기 저장소) 에 반영됨
(4) 특정 조건, 이벤트에 따라 Write DB 내용을 Read DB 전송
(5) Write DB 의 내용이 Read DB 에 적용됨
(6) Query (읽기) 요청이 발생함
(7) Read DB 를 향해 Query 작업이 실행됨
Command 와 Query
Command (쓰기 작업)
Create(생성), Update(수정), Delete(삭제) 와 같이 상태를 변경하는 작업
목적 : 비즈니스 규칙에 따라 시스템 상태를 일관되게 변경하는 것
예시 : 상품 등록, 주문 생성, 결제 처리, 상품 재고 수정 등
Command 에 대한 데이터 모델은 아직까지고 RDBMS 가 대세
Query (읽기 작업)
Select(조회) 와 같이 데이터를 읽는 작업
목적 : 필요한 정보를 효율적(빠르고, 정확하게) 검색하고 표현하는 것
상품 목록 조회, 주문 내역 확인, 검색 결과 표시 등
CQRS의 등장 배경과 도입 이유
(1) Command 작업과 Query 작업의 비대칭성
- 일반적인 서비스에서는 Query 작업의 빈도가 Command 작업의 빈도보다 훨씬 많음
- 예를 들어 온라인 쇼핑몰에서는 상품 등록의 빈도보다 상품 목록 조회 빈도가 훨씬 많음
- 때문에 Query 작업에서 얻을 수 있는 성능적 이득의 크기가 Command 보다 클 확률이 높음
(2) Command 성능과 Query 성능의 트레이드오프
구분 | Command 작업 | Query 작업 |
---|---|---|
설명 | 쓰기 작업 | 읽기 작업 |
목표 | 상태 변경 | 데이터 제공 (상태 변화 없음) |
중요 포인트 | - ACID 가 중요 - 트랜잭션 보장 - 강한 논리적 일관성 - 지속성 |
- 빠른 응답 시간 - 높은 처리량 - 수평적인 확장성 |
최적화 방향 | - 정규화 - 인덱싱 최소화 |
- 반정규화 - 최대한 많은 인덱싱 |
일관성 | - 논리적 일관성이 절대적으로 중요 | - 작업, 시점에 따라 일관성 강도 유연하게 가능 |
데이터 모델 | - 정규화된 도메인 모델 | 비정규화된 뷰 모델 |
- Command 작업과 Query 작업의 최적화 방향이 다름
- Command : 정규화, 최소한의 인덱싱(인덱싱 작업 최소화)
- Query : 반정규화(Join 최소화), 최대한의 다중 인덱싱
- 즉, Command 와 Query 최적화는 트레이드 오프의 관계
예시 : 정규화 (쇼핑몰 주문정보)
Command : 상품 정보, 고객 정보, 주문 정보 등으로 나눠 정규화 하는 것이 최적화의 방향
Query : 데이터가 정규화 될 수록 많은 Join 이 요구됨 -> 성능의 저하
예시 : 인덱싱
Query : 데이터에 많은 인덱싱이 될 수록 빠른 조회가 가능
Command : 인덱싱이 많아질 수록 인덱싱 작업에 소요되는 시간 증가
(3) 모놀리식 아키텍처에서 트랜잭션 락
- 모놀리식 아키텍처에서는 시스템 전반이 단일 공유 데이터베이스를 사용
- 따라서 Command 작업과 Query 작업도 동일한 데이터 모델을 바라봄
- 무결성을 위한 트랜잭션 락으로 인해 하나의 작업 중 다른 작업이 대기하는 한계
(4) Query 특화 데이터 저장소
- Query 작업에 특화된 데이터 저장소/방법 존재 : 검색 엔진, NoSQL, 캐시…
- 이들은 특정 읽기 작업 유형에 최적화된 Query 성능을 보일 수 있게 설계됨
- 하지만 Command 와 함께 단일 데이터 모델을 사용할 경우 위외 같은 저장소 사용 불가
- 결국 얻을 수 있는 Query 의 성능적 이득을 놓치게 되는 악영향으로 돌아옴
(5) 단일 책임 원칙
- Command 와 Query 는 근본적으로 다른 특성을 가진 작업임
- 둘이 동일 데이터 모델을 사용할 경우, 한 쪽의 변경사항이 다른 쪽에 불필요한 영향을 주게 됨
- 이는 단일 책임 원칙에 위배되는 형태
(6) 데이터 모델 분리의 필요성
- 도메인이 복잡해지면서 Command 와 Query 데이터 모델 분리의 필요성이 높아짐
- 또한 Command 보다 Query 쪽의 요구사항과 비즈니스로직의 변경 빈도가 훨씬 많음
- 단일책임원칙 관점으로도 둘을 분리하는 것에서 얻는 이득이 있을 수 있음
CQRS 의 장단점
장점
장점 | 설명 |
---|---|
확장성의 향상 | 읽기/쓰기 작업을 독립적으로 확장할 수 있음 |
성능 최적화 | 각 작업 유형에 맞는 데이터 모델과 기술을 선택할 수 있음 |
기술 다양성 | 목적에 맞는 다양한 데이터 저장소를 선택해 활용할 수 있음 |
복잡성 관리 | 관심사 분리를 통해 코드 복잡성을 감소시킬 수 있음 |
단점
단점 | 설명 |
---|---|
복잡성 증가 | 시스템 관리 관점에서의 복잡성이 증가될 수 있음 |
Reference
Wanted 커리어 프리온보딩 - 2-4년차 백엔드를 위한 CQRS 패턴과 실시간 데이터 처리
Comments