AI Store에서 AI코딩으로 만들어진 앱을 만나보세요!
지금 바로 방문하기

이벤트 기반 아키텍처(Event-Driven Architecture)로 Rails 앱 개선하기

카테고리

프로그래밍/소프트웨어 개발

서브카테고리

웹 개발

대상자

Rails 앱 개발자, 중간 이상의 경험을 가진 개발자, 비동기 처리와 복잡한 앱 아키텍처에 관심 있는 개발자

핵심 요약

  • 트라디셔널한 요청-응답 패턴의 단점

- after_commit 콜백 체인으로 인한 비즈니스 로직의 과도한 결합

- 테스트 복잡성 증가 (10개 이상의 오브젝트 스텁 필요)

- HTTP 요청 타임아웃으로 인한 비동기 처리 한계

  • 이벤트 기반 아키텍처(EDA)의 핵심 장점

- OrderPaid 같은 이벤트로 컴포넌트 분리 (예: Rails.configuration.event_store.publish(event))

- 비동기 처리로 인한 30초 요청 타임아웃 문제 해결

- 이벤트 재생 (예: event_store.read.stream("Order$#{order.id}"))

  • 실무 적용 팁

- rails-event_store 사용 시 TestClient로 CI 테스트

- Karafka로 Kafka 기반의 스케일링과 내구성 활용

- 이벤트 스키마 검증 (JSON::Validator.validate!(SCHEMA, data))

섹션별 세부 요약

1. 트라디셔널한 요청-응답 패턴의 문제점

  • user.update!(...) 호출로 인한 5개의 사이드 이펙트 트리거로 인한 복잡성
  • after_commit 콜백 체인의 스파게티 코드 심화
  • 서비스 오브젝트에 "한 가지 더" 기능 추가로 인한 결합도 증가
  • 예제 코드:

```ruby

def checkout_order

order.process_payment! # 직접 제어

order.send_receipt! # 더 많은 직접 제어

order.update_inventory! # 누가 이걸 호출했나?

end

```

2. 이벤트 기반 아키텍처(EDA)의 이점

  • 이벤트 발행으로 인한 컴포넌트 분리 (예: OrderPaid.new(order_id: order.id))
  • 비동기 처리로 인한 HTTP 요청 타임아웃 문제 해결
  • 이벤트 재생을 통한 디버깅 (예: event_store.read.stream("Order$#{order.id}"))
  • 이벤트 스키마 검증으로 중복 처리 방지 (예: JSON::Validator.validate!(SCHEMA, data))

3. 이벤트 저장소(RailsEventStore) 활용

  • 이벤트를 정의하고 발행하는 예:

```ruby

class OrderPaid < RailsEventStore::Event

def self.strict(data)

new(data.merge(metadata: { timestamp: Time.now }))

end

end

event = OrderPaid.strict(order_id: 123)

Rails.configuration.event_store.publish(event)

```

  • 이벤트 구독자 설정 예:

```ruby

Rails.configuration.event_store.subscribe(Payments::OnOrderPaid.new, to: [OrderPaid])

```

4. Karafka로 Kafka 기반 아키텍처 구현

  • Kafka 설정 예:

```ruby

class KarafkaApp < Karafka::App

setup do |config|

config.kafka = { 'bootstrap.servers': 'kafka:9092' }

end

end

```

  • 이벤트 소비자 예:

```ruby

module Payments

class OrdersPaidConsumer < Karafka::BaseConsumer

def consume

params_batch.each do |order|

CreditCard.charge(order[:id])

end

end

end

end

```

5. 간단한 이벤트 버스(Dry::Events) 활용

  • 이벤트 발행/구독 예:

```ruby

AppEventBus.broadcast("order.paid", order_id: 123)

AppEventBus.subscribe("order.paid") do |event|

Payments::CreditCardProcessor.call(event[:order_id])

end

```

  • 장점: DB/Kafka 의존 없이 간단한 앱에 적합

6. 이벤트 저장소의 장단점

  • 장점: ActiveRecord와의 강한 통합, 내장 이벤트 소싱
  • 단점: Ruby만 지원 (다국어 이벤트 불가)
  • 사용 시기: 서비스 간 메시징이 필요한 앱

7. Karafka의 장단점

  • 장점: Kafka의 내구성/스케일링, 다국어 지원 (Java 서비스도 가능)
  • 단점: 운영 복잡성 (Kafka 클러스터 관리 필요)
  • 사용 시기: 가볍게 결합이 필요한 경우

8. 이벤트 기반 아키텍처의 한계

  • 단순 CRUD 앱: 과도한 복잡성
  • 저지연 요구: 이벤트 처리로 인한 밀리초 추가 지연
  • 운영 팀 없음: Kafka는 Heroku에서 간단히 실행 불가

9. 이벤트 기반 아키텍처 도입 단계

  1. 작은 규모부터 시작: 하나의 콜백 체인을 이벤트로 대체
  2. RES 도입: 이벤트 지속성 관리
  3. 스케일 확장: 서비스 경계를 넘어갈 때 Kafka 도입

결론

  • 실무 적용 팁:

- rails-event_storeTestClient로 CI 테스트

- EDA는 트렌드가 아닌 100개 이상의 기능 추가 시 시스템이 무너지지 않는 아키텍처

- 이벤트 스키마 검증이벤트 재생을 통해 중복 처리 방지 및 디버깅 효율성 향상

- Kafka 사용 시: 운영 복잡성 고려, 다국어 지원이 필요한 경우에 적합

- 간단한 앱: Dry::Events로 DB/Kafka 없이 간편하게 이벤트 처리 가능