본문 바로가기
기술 공부

CQRS (Command and Query Responsibility Segregation)

by 랼랼 2025. 6. 6.

등록,수정,삭제(command)와 읽기(query)를 분리하여 성능 향상에 기여할 수 있다.

 

CQRS (Command and Query Responsibility Segregation) 는 Command 와 Query의 책임을 분리하는 아키텍쳐 패턴이다

  • Command: 데이터를 변경하는 작업 (예: 등록, 수정, 삭제)
  • Query: 데이터를 조회하는 작업 (예: 목록 보기, 상세 보기)

전통적인 CURD 방식은 하나의 모델이 읽기와 쓰기 모두를 처리하지만, CQRS는 이 책임을 나누어 더 명확한 구조로 제공한다.

command와 query를 나눔으로서의 상대적으로 자주 사용하는 query 분리함으로 테이블 join에 대한 부담을 줄여주고,

따라서 빠른 응답 시간과, 높은 트래픽(호출 빈도)에 대해 대응하기 좋다.

 

 

CQRS의 시스템 설계

  • 동기식 : 즉각적이고 강한 결합, 성능저하 및 장애가 전파 될 수 있다.
    - 직접 동기화 방식 : command 서비스에서 command를 처리하고, query 또한 동시에 처리한다
    - 간접 동기화 방식 : commnad 서비스에서 command를 처리하고, Model Sync에 업데이트를 요청하여 query 모델을 처리한다.
  • 비동기식 : 이벤트 큐를 이용한다.
         느슨한 결합, 장애 격리 가능, command 응답 속도 향상 , 일시적으로 데이터가 불일치 할 수 있고 복잡하다.
    - 어플리케이션 방식 : command 서비스에서 이벤트 큐에 이벤트를 발행한다.
    - CDC 이벤트 방식 : command 모델이 변경되면 로그 파일의 변경을 이벤트 큐가 감지한다.
    - Outbox 패턴 방식 : command 모델이 변경되고 변동사항을 outbox에 기록, outbox의 변경을 이벤트 큐가 감지한다.
    * 이벤트 큐를 구독하고 있는 Model Sync에 의해 query 모델이 처리된다.

이벤트

이벤트를 통해 query 정보가 업데이트 된다.

  • 멱등성 : 같은 이벤트를 여러번 작동 시켜도, 모두 동일한 결과가 나오게 된다.
       네트워크 장애, 중복 발생 등의 문제 상황에서도 일관된 결과를 유지 할 수 있다.
  • 자기완결성 : 이벤트는 모든 정보를 포함하고 있어야 한다.
       문제상황에서도 발신자 및 다른 DB에 의존하지 않고 독립적으로 이벤트를 처리할 수 있다.
  • 버전관리 : 이벤트 구조는 시간이 지남에 따라 변경 될 수 있음으로, 이전 버전이 호환되도록 설계하여야 한다.
  • 이벤트의 구성
    - 메타데이터 : 이벤트 자체에 대한 정보
    - 페이로드 : 비지니스 데이터
{
  "metadata": {
    "eventId": "abc-123",
    "eventType": "OrderCreated",
    "eventVersion": 1,
    "timestamp": "2025-06-06T09:30:00Z",
    "producer": "order-service"
  },
  "payload": {
    "orderId": "ORD-20250606-01",
    "userId": "USR-001",
    "items": [
      { "productId": "P001", "quantity": 2 }
    ],
    "totalAmount": 49000
  }
}

 

Query 모델의 선택

가장 최적화된 성능을 낼 수 있는 DB 선택이 중요하다. (해당 내용은 중요하다고 생각, 따로 기재 예정)

 

DLQ (Dead Letter Queue) 기반 재처리 메커니즘

 - 처리 실패 이벤트를 DLQ로 격리하여 저장한다.

 - 재처리 정책을 설정 하여(지연, 횟수제한) 구현하되, 데이터 최신성 평가가 필요하다.

 

 

CQRS 레벨

레벨 특징 쓰기 모델 읽기 정규화 사용
레벨 1
(논리적 분리)
Command/Query 코드 분리
동일한 DB/모델 사용
도메인 엔티티
(정규화 모델)
같은 모델 사용 정규화
레벨 2
(모델 분리)
읽기/쓰기 모델 분리 (모델 뷰 분리)
다른 DTO, 다른 테이블 사용 가능
도메인 모델
(정규화 우선)
ViewModel, DTO 비정규화 가능
(조인 줄이기, 성능 최적화)
레벨 3
(물리적 분리
 & 비동기 처리)
완전한 분리
Command→이벤트 발행
→ Query 갱신
DB도 분리
도메인 중심 모델
(정규화, 트랜잭션 중심)
조회 전용 DB
(View, NoSQL 등)
고도의 비정규화
빠른 응답을 위한 설계

 

반응형

댓글