본문 바로가기
GD's IT Lectures : 기초부터 시리즈/스프링부트(Spring Boot) 기초부터 ~

[스프링 부트(SpringBoot) : 고급] 이벤트 소싱 및 CQRS 패턴 적용

by GDNGY 2023. 5. 6.

6. 이벤트 소싱 및 CQRS 패턴 적용

이벤트 소싱은 애플리케이션의 상태 변경을 순차적으로 저장하는 방식이고, CQRS는 명령과 쿼리를 분리하여 시스템의 응답 속도와 확장성을 향상하는 패턴입니다. 여기에서는 이벤트 소싱과 CQRS의 개념, 그리고 스프링 부트에서 이 패턴들을 구현하는 방법에 대해 알아봅니다.

 

6.1. 이벤트 소싱 소개

이벤트 소싱(Event Sourcing)은 애플리케이션의 상태 변경을 순차적인 이벤트로 저장하는 방식입니다. 이벤트 소싱을 사용하면 애플리케이션의 과거 상태를 재구성할 수 있고, 이벤트를 기반으로 비즈니스 분석이 가능합니다. 이벤트 소싱의 주요 구성 요소는 다음과 같습니다.

 

  • 이벤트: 도메인 객체의 상태 변경을 나타내는 객체
  • 이벤트 저장소: 이벤트를 저장하는 저장소
  • 애그리거트: 이벤트를 적용하여 도메인 객체의 상태를 변경하는 객체

 

6.2. CQRS 패턴 소개

CQRS(Command Query Responsibility Segregation) 패턴은 명령과 쿼리를 분리하여 시스템의 응답 속도와 확장성을 향상하는 패턴입니다. 명령은 시스템의 상태를 변경하고, 쿼리는 상태를 조회합니다. CQRS 패턴은 다음과 같은 장점이 있습니다.

 

  • 확장성: 명령과 쿼리를 별도의 서비스로 분리하여 각 서비스를 독립적으로 확장할 수 있습니다.
  • 유연성: 명령과 쿼리의 처리 방식을 독립적으로 변경할 수 있습니다.

 

6.3. 스프링 부트에서 이벤트 소싱과 CQRS 구현

스프링 부트에서 이벤트 소싱과 CQRS 패턴을 구현하기 위해 Axon Framework와 같은 도구를 사용할 수 있습니다. 다음은 스프링 부트와 Axon을 사용하여 간단한 이벤트 소싱 및 CQRS 예제를 구현하는 방법입니다.

 

☞예제 코드 : 주문 관리 시스템

 

먼저, 의존성을 추가합니다.

<!-- pom.xml -->
<dependencies>
    <dependency>
        <groupId>org.axonframework</groupId>
        <artifactId>axon-spring-boot-starter</artifactId>
        <version>4.x.x</version>
    </dependency>
</dependencies>

 

다음으로, 이벤트, 명령, 쿼리 및 이벤트 핸들러를 정의합니다.

// 이벤트
public class OrderCreatedEvent {
    private final String orderId;
    private final BigDecimal amount;

    // 생성자 및 getter 생략
}

// 명령
public class CreateOrderCommand {
    private final String orderId;
    private final BigDecimal amount;

    // 생성자 및 getter 생략
}

// 쿼리
public class GetOrderByIdQuery {
    private final String orderId;

    // 생성자 및 getter 생략
}

// 이벤트 핸들러
@Component
public class OrderEventHandler {

    @EventHandler
    public void on(OrderCreatedEvent event) {
        // 이벤트를 처리하는 로직
    }
}

 

이제 애그리거트를 정의합니다.

@Aggregate
public class OrderAggregate {

    @AggregateIdentifier
    private String orderId;
    private BigDecimal amount;

    @CommandHandler
    public OrderAggregate(CreateOrderCommand command) {
        apply(new OrderCreatedEvent(command.getOrderId(), command.getAmount()));
    }

    @EventSourcingHandler
    public void on(OrderCreatedEvent event) {
        this.orderId = event.getOrderId();
        this.amount = event.getAmount();
    }
}

 

마지막으로, 명령과 쿼리를 처리하는 컨트롤러를 작성합니다.

@RestController
public class OrderController {

    private final CommandGateway commandGateway;
    private final QueryGateway queryGateway;

    public OrderController(CommandGateway commandGateway, QueryGateway queryGateway) {
        this.commandGateway = commandGateway;
        this.queryGateway = queryGateway;
    }

    @PostMapping("/orders")
    public CompletableFuture<String> createOrder(@RequestBody CreateOrderCommand command) {
        return commandGateway.send(command);
    }

    @GetMapping("/orders/{orderId}")
    public CompletableFuture<Order> getOrderById(@PathVariable String orderId) {
        return queryGateway.query(new GetOrderByIdQuery(orderId), Order.class);
    }
}

 

이 예제에서는 주문 관리 시스템을 구현하였습니다. 이벤트 소싱과 CQRS 패턴을 적용하여 애플리케이션의 확장성과 유연성을 높였습니다.

 

 

 

2023.05.06 - [프로그래밍/스프링부트(Spring Boot) 기초부터 ~] - [스프링 부트(SpringBoot) : 고급] 도메인 주도 설계(DDD)와 스프링 부트

 

[스프링 부트(SpringBoot) : 고급] 도메인 주도 설계(DDD)와 스프링 부트

5. 도메인 주도 설계(DDD)와 스프링 부트 도메인 주도 설계(DDD)를 사용하여 프로젝트를 개발하는 방법을 살펴봅니다. DDD는 도메인 전문가와 소프트웨어 개발자가 협력하여 복잡한 비즈니스 문제

gdngy.tistory.com

 

반응형

댓글