CQRS Pattern

CQRS

Command Query Responsibility Segregation

  • 소프트웨어 아키텍처 패턴 중 하나

  • 데이터베이스 상호작용에 대한 패턴

  • 명령조회의 책임을 분리하는 원칙을 기반

  • 읽기(Query)쓰기(Command) 모델을 분리하는 것을 목표

기존 시스템 문제점

  • 조회와 명령을 하나의 모델에서 처리

  • 데이터 경합 발생

  • 복잡도 증가

CQRS 이점

  • 데이터의 변경(명령)과 조회(쿼리)를 서로 다른 모델로 분리 및 처리

  • 데이터 변경과 조회 간의 의존성 감소

  • 유연성과 확장성을 향상

  • 복잡한 도메인 모델이나 대규모 시스템에서 유용

  • 단순한 시스템에서는 오버엔지니어링

CQRS의 구성 요소

명령(Command)

  • 시스템의 상태를 변경하는 작업을 의미

  • 명령 모델은 데이터의 변경을 처리하고, 이벤트를 발생시켜 상태 변경을 통지한다.

쿼리(Query)

  • 시스템의 상태를 조회하는 작업을 의미

  • 쿼리 모델은 읽기 전용 데이터 저장소를 사용하여 데이터를 효율적으로 조회

이벤트(Event)

  • 시스템에서 발생하는 중요한 사건이나 상태 변경을 나타냄

  • 명령 모델에서 상태를 변경하면 해당 변경 사항을 이벤트로 기록

명령 핸들러(Command Handler)

  • 명령을 처리하는 로직을 담당하는 구성 요소

  • 명령을 받아 상태를 변경하고, 그에 따른 이벤트를 발생시킴

이벤트 핸들러(Event Handler)

  • 발생한 이벤트에 대한 로직을 처리하는 구성 요소

  • 이벤트가 발생하면 해당 이벤트를 수신하여 쿼리 모델을 업데이트

명령과 쿼리를 사용, 읽기 및 쓰기를 다른 모델로 구분

높은 격리 수준을 위해 쓰기, 읽기 데이터를 물리적으로 구분

Code

// 커맨드 모델
class Command {
  private String data;
  
  public Command(String data) {
    this.data = data;
  }
  
  public String getData() {
    return data;
  }
}

// 쿼리 모델
class Query {
  // 조회에 필요한 필드 및 메서드들...
}

// 명령 핸들러
class CommandHandler {
  public void handleCommand(Command command) {
    //명령을 처리하고 데이터베이스에 저장하는 로직
  }
}

// 조회 핸들러
class QueryHandler {
  public Query handleQuery() {
    // 조회를 처리하고 결과를 반환하는 로직
    return new Query()
  }
}

// CQRS 서비스
class CqrsService {
  private CommandHandler commandHandler;
  private QueryHandler queryHandler;
  
  public CqrsService(CommandHandler commandHandler, QueryHandler queryHandler) {
    this.commandHandler = commandHandler;
    this.queryHandler = queryHandler;
  }
  
  public void sendCommand(Command command) {
    commandHandler.handleCommand(command);
  }
  
  public Query sendQuery() {
    return queryHandler.handleQuery();
  }
}

// 클라이언트 코드

public class CqrsExample {
  public static void main(String[] args) {
    CommandHandler commandHandler = new CommandHandler();
    QueryHandler queryHandler = new QueryHandler();
    
    CqrsService cqrsService = new CqrsService(commandHandler, queryHandler);
    
    //명령 보내기
    Command command = new Command("Update data");
    cqrsService.sendCommand(command);
    
    //조회 보내기
    Query query = cqrsService.sendQuery();
    // 조회 결과를 사용하는 로직...
  }
}

Last updated