본문 바로가기
Language/Kotlin

Event Sourcing을 통한 함수형 프로그래밍의 적용

by 시니성 2023. 10. 13.

함수형 프로그래밍은 이뮤터블한 데이터와 순수 함수들을 사용해 프로그램을 표현하는 패러다임입니다. 한편, Event Sourcing은 이와 관련 깊은 관계를 가지고 있는 아키텍처 패턴입니다.

Event Sourcing이란?

Event Sourcing은 시스템의 상태가 아닌, 상태를 변화시키는 이벤트들을 저장하고, 이를 기반으로 시스템의 상태를 구축하는 패턴입니다. 주요 특징은 다음과 같습니다.

  • 이벤트 저장: 모든 상태 변화는 이벤트로 저장됩니다.
  • 상태 재구축: 현재 상태는 초기 상태에서 시작하여, 저장된 이벤트를 순차적으로 적용하여 재구축됩니다.
  • 이벤트 재생: 이벤트는 시스템의 다른 부분에서도 재생될 수 있어, 다양한 응답과 프로세스를 구현할 수 있습니다.

Event Sourcing의 장점

  • 이력 추적: 모든 상태 변화가 이벤트로 저장되기 때문에 완벽한 이력 관리가 가능합니다.
  • 상태 복구: 과거의 특정 시점으로 상태를 쉽게 롤백할 수 있습니다.
  • 비동기 처리: 이벤트 기반 아키텍처는 마이크로서비스와의 통신이나 비동기 처리와도 어울립니다.

가상 시나리오: 온라인 주문 시스템

한 온라인 상점에서 주문, 결제, 배송의 각 단계는 이벤트로 모델링 될 수 있습니다. 사용자의 모든 행동 (주문 생성, 주문 수정, 주문 취소 등)은 이벤트로써 저장되며, 이를 기반으로 주문의 현재 상태를 파악할 수 있습니다.

예시 코드: Kotlin으로 주문 이벤트 소싱 시스템 설계

// 1. 이벤트를 정의합니다. 모든 이벤트는 데이터를 변경시키는 행위입니다.
sealed class OrderEvent {
    data class OrderCreated(val orderId: String, val item: String, val price: Double) : OrderEvent()
    data class OrderPaid(val orderId: String) : OrderEvent()
    // 추가로 필요한 이벤트를 정의할 수 있습니다.
}

// 2. 상태를 정의합니다. 상태는 이벤트를 통해 변화하고, 이벤트 소싱을 통해 재구축됩니다.
data class OrderState(val orderId: String?, val item: String?, val price: Double?, val isPaid: Boolean) {
    companion object {
        // 초기 상태 정의
        val INITIAL = OrderState(null, null, null, false)
    }
}

// 3. 이벤트를 상태에 적용하는 로직을 정의합니다.
fun applyEvent(state: OrderState, event: OrderEvent): OrderState {
    // 각 이벤트 타입에 따라 상태를 변경합니다.
    return when(event) {
        is OrderEvent.OrderCreated -> state.copy(orderId = event.orderId, item = event.item, price = event.price)
        is OrderEvent.OrderPaid -> state.copy(isPaid = true)
    }
}

// 4. 이벤트 스트림을 통해 최종 상태를 구축합니다.
fun buildState(events: List<OrderEvent>): OrderState {
    // 이벤트 스트림을 순회하며 상태를 구축합니다.
    return events.fold(OrderState.INITIAL) { state, event -> applyEvent(state, event) }
}
  • 이벤트 정의: OrderEvent sealed 클래스를 통해 주문 관련 이벤트들을 정의합니다.
  • 상태 정의: OrderState 데이터 클래스를 통해 주문의 상태를 정의합니다.
  • 이벤트 적용: applyEvent 함수를 통해 상태에 이벤트를 적용, 새로운 상태를 반환합니다.
  • 상태 구축: buildState 함수를 통해 이벤트 스트림을 순회하며 최종 상태를 도출합니다.

이 시스템은 모든 사용자 행위를 이벤트로 저장함으로써, 언제든지 시스템의 상태를 재구축할 수 있습니다. 이를 통해 이력 관리, 오류 발생 시 상태 복구, 비동기적인 시스템 간 통신 등 여러 분야에서 이점을 얻을 수 있습니다. 이러한 Event Sourcing 패턴은 함수형 프로그래밍과 잘 어울리며, Kotlin을 사용해 간결하면서도 표현력 있는 시스템 구현을 가능케 합니다.