Files
2nd/10_Wiki/Topics/AI_and_ML/Event-Driven-Architecture.md
T
Antigravity Agent f8b21af4be Wiki cleanup: error-doc removal, dedup merge, link normalization
10_Wiki/Topics 대규모 정리:
- 오류 캡처/미완성 stub 문서 227개 제거
- 교차폴더 중복 43클러스터 병합 (63파일 → redirect)
- 링크명 정규화: 깨진 링크 수정·redirect 직결·개념 매핑 ~2,400건
- 카테고리 MOC 6개 신규 생성
- Graph 섹션 미해결 related-keyword 링크 10,058건 제거

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 23:52:15 +09:00

5.5 KiB

id, title, category, status, canonical_id, aliases, duplicate_of, source_trust_level, confidence_score, verification_status, tags, raw_sources, last_reinforced, github_commit, tech_stack
id title category status canonical_id aliases duplicate_of source_trust_level confidence_score verification_status tags raw_sources last_reinforced github_commit tech_stack
wiki-2026-0508-event-driven-architecture Event-Driven Architecture 10_Wiki/Topics verified self
EDA
event-driven
pub-sub
message-driven
choreography
orchestration
none A 0.97 applied
architecture
eda
event-driven
kafka
pub-sub
choreography
microservices
2026-05-10 pending
language framework
TypeScript / Java / Python Kafka / RabbitMQ / EventBridge / NATS

Event-Driven Architecture

매 한 줄

"매 service 의 event 의 의 communicate". 매 sync HTTP RPC 의 X — 매 async pub/sub. 매 decouple + scale + replay. 매 modern: 매 Kafka, EventBridge, NATS, async.

매 핵심

매 pattern

  • Event notification: 매 fire-and-forget.
  • Event-carried state transfer: 매 payload 의 state.
  • Event sourcing: 매 store events.
  • CQRS: 매 read/write split.

매 choreography vs orchestration

  • Choreography: 매 service 의 react.
  • Orchestration: 매 central coordinator (saga).

매 응용

  1. Microservices: 매 decouple.
  2. Real-time: 매 streaming.
  3. Fan-out: 매 1 → many.
  4. Audit: 매 replay.
  5. Integration: 매 cross-system.

💻 패턴

Kafka producer (Java)

KafkaProducer<String, String> p = new KafkaProducer<>(props);
p.send(new ProducerRecord<>("orders.placed", orderId, json), (md, ex) -> {
    if (ex != null) log.error("Failed", ex);
});

Kafka consumer (Python)

from confluent_kafka import Consumer
c = Consumer({'bootstrap.servers': 'kafka:9092', 'group.id': 'inventory', 'auto.offset.reset': 'earliest'})
c.subscribe(['orders.placed'])
while True:
    msg = c.poll(1.0)
    if msg and not msg.error():
        handle_order(json.loads(msg.value()))

Outbox (transactional publish)

async function placeOrder(o: Order) {
  await db.transaction(async tx => {
    await tx.orders.save(o);
    await tx.outbox.insert({ topic: 'orders.placed', payload: o, status: 'pending' });
  });
}
// 매 separate process polls outbox → Kafka

Schema registry (Avro)

{
  "type": "record",
  "name": "OrderPlaced",
  "fields": [
    { "name": "orderId", "type": "string" },
    { "name": "amount", "type": "long" },
    { "name": "currency", "type": "string", "default": "USD" }
  ]
}

Saga orchestration

class OrderSaga {
  async execute(orderId: string) {
    try {
      await reservePayment(orderId);
      await reserveInventory(orderId);
      await scheduleShipping(orderId);
    } catch (e) {
      await this.compensate(orderId);
      throw e;
    }
  }
  
  async compensate(orderId: string) {
    await releaseInventory(orderId);
    await refundPayment(orderId);
  }
}

Choreography (each service reacts)

// 매 inventory service
on('orders.placed', async event => {
  const ok = await reserve(event.orderId);
  publish(ok ? 'inventory.reserved' : 'inventory.failed', event);
});

// 매 shipping service
on('inventory.reserved', async event => {
  await schedule(event.orderId);
  publish('shipping.scheduled', event);
});

DLQ (dead letter queue)

def consume_with_dlq(topic, handler, max_retries=3):
    for msg in consumer:
        for attempt in range(max_retries):
            try:
                handler(msg)
                break
            except Exception as e:
                if attempt == max_retries - 1:
                    dlq.publish(msg, error=str(e))

Idempotency

def idempotent_handler(event):
    if redis.set(f'evt:{event.id}', '1', nx=True, ex=86400):
        process(event)
    # 매 else: skip duplicate

Backpressure

def consume_with_backpressure(consumer, max_in_flight=100):
    sem = Semaphore(max_in_flight)
    for msg in consumer:
        sem.acquire()
        thread = Thread(target=lambda m=msg: (process(m), sem.release()))
        thread.start()

Event versioning

type OrderPlacedV1 = { version: 1; orderId: string; amount: number };
type OrderPlacedV2 = { version: 2; orderId: string; amount: number; currency: string };

function migrate(e: OrderPlacedV1 | OrderPlacedV2): OrderPlacedV2 {
  if (e.version === 1) return { ...e, version: 2, currency: 'USD' };
  return e;
}

매 결정 기준

상황 Tool
High throughput Kafka
Cloud-native AWS EventBridge / SNS+SQS
Low latency NATS
Complex routing RabbitMQ
Simple pub/sub Redis Streams
Multi-step Saga (Temporal)

기본값: 매 Kafka + 매 schema registry + 매 outbox + 매 DLQ + 매 idempotency.

🔗 Graph

🤖 LLM 활용

언제: 매 microservice. 매 streaming. 매 decouple. 언제 X: 매 simple monolith. 매 strict transaction.

안티패턴

  • Sync inside async: 매 backpressure 의 break.
  • No schema: 매 break.
  • No DLQ: 매 stuck consumer.
  • No idempotency: 매 duplicate processing.
  • Choreography 의 over-use: 매 spaghetti.

🧪 검증 / 중복

  • Verified (Fowler EDA, Confluent, AWS Reference Architecture).
  • 신뢰도 A.

🕓 Changelog

날짜 변경
2026-04-20 Auto-reinforced
2026-05-08 Phase 1
2026-05-10 Manual cleanup — EDA + 매 Kafka / outbox / saga / DLQ / idempotency code