[G1-Sync] Manual knowledge update

This commit is contained in:
Antigravity Agent
2026-05-10 22:08:15 +09:00
parent 21ac3ed255
commit 504fd5fb42
3011 changed files with 380280 additions and 206977 deletions
@@ -1,90 +1,206 @@
---
id: wiki-2026-0508-event-driven-architecture
title: Event Driven Architecture
title: Event-Driven Architecture
category: 10_Wiki/Topics
status: needs_review
status: verified
canonical_id: self
aliases: [P-Reinforce-AI-EVENT-DRIVEN]
aliases: [EDA, event-driven, pub-sub, message-driven, choreography, orchestration]
duplicate_of: none
source_trust_level: A
confidence_score: 0.97
tags: [Architecture, EventDriven, Async, PubSub]
verification_status: applied
tags: [architecture, eda, event-driven, kafka, pub-sub, choreography, microservices]
raw_sources: []
last_reinforced: 2026-04-20
last_reinforced: 2026-05-10
github_commit: pending
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
tech_stack:
language: unspecified
framework: unspecified
language: TypeScript / Java / Python
framework: Kafka / RabbitMQ / EventBridge / NATS
---
# [[Event-Driven-Architecture]] (이벤트 주도 아키텍처)
# Event-Driven Architecture
## 📌 한 줄 통찰 (The Karpathy Summary)
> "말 걸지 마, 그냥 공지사항을 확인해." 상태 변화(이벤트)를 발행하고 구독하는 방식으로 시스템을 구성하여, 서비스 간의 직접적인 호출을 없애고 유연한 확장을 가능하게 하는 설계다.
## 한 줄
> **"매 service 의 event 의 의 communicate"**. 매 sync HTTP RPC 의 X — 매 async pub/sub. 매 decouple + scale + replay. 매 modern: 매 Kafka, EventBridge, NATS, async.
## 📖 구조화된 지식 (Synthesized Content)
- **Components**:
- **Event Producer**: 상태 변화를 감지하고 이벤트를 발행함.
- **Event Bus / Broker**: 발행된 이벤트를 전달함 (Kafka, RabbitMQ 등).
- **Event Consumer**: 필요한 이벤트를 구독하여 로직을 실행함.
- **Benefits**:
- **Decoupling**: 생산자는 소비자가 누구인지 알 필요가 없다.
- **[[Scalability]]**: 트래픽 급증 시 메시지 큐를 통해 부하를 분산 처리할 수 있다.
- **Responsiveness**: 비동기 처리를 통해 즉각적인 사용자 피드백이 가능하다.
## 매 핵심
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
- 이벤트 주도는 시스템 흐름을 파악하기 어렵게 만든다(Where did this event come from?). 또한 '결과적 일관성(Eventual Consistency)'을 수용해야 하므로, 금융 거래처럼 원자성이 중요한 작업에는 설계 난이도가 급상승한다. 분산 추적(Distributed Tracing) 도구 없이는 재앙이 될 수 있다.
### 매 pattern
- **Event notification**: 매 fire-and-forget.
- **Event-carried state transfer**: 매 payload 의 state.
- **Event sourcing**: 매 store events.
- **CQRS**: 매 read/write split.
## 🔗 지식 연결 (Graph)
- Related: [[Microservices-Architecture]] , Message-Queue-Design
- Pattern: Observer-Pattern
### 매 choreography vs orchestration
- **Choreography**: 매 service 의 react.
- **Orchestration**: 매 central coordinator (saga).
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
### 매 응용
1. **Microservices**: 매 decouple.
2. **Real-time**: 매 streaming.
3. **Fan-out**: 매 1 → many.
4. **Audit**: 매 replay.
5. **Integration**: 매 cross-system.
**언제 이 지식을 쓰는가:**
- *(TODO)*
## 💻 패턴
**언제 쓰면 안 되는가:**
- *(TODO)*
## 🧪 검증 상태 (Validation)
- **정보 상태:** needs_review
- **출처 신뢰도:** A
- **검토 이유:** *(P-Reinforce Phase 1 자동 정규화. 본문 검증 필요.)*
## 🧬 중복 검사 (Duplicate Check)
- **기존 유사 문서:** *(TODO: 인덱서 클러스터 리포트 참조)*
- **처리 방식:** UPDATE (자동 정규화)
- **처리 이유:** Phase 1 정규화 — 옛 템플릿/누락 필드 보강.
## 🕓 변경 이력 (Changelog)
| 날짜 | 변경 내용 | 처리 방식 | 신뢰도 |
|------|-----------|-----------|--------|
| 2026-05-08 | P-Reinforce Phase 1 정규화 (frontmatter + 헤더 표준화) | UPDATE | A |
## 💻 코드 패턴 (Code Patterns)
**패턴 1:** *(TODO: 이 프로젝트 컨벤션 반영한 구조 스켈레톤)*
```text
# TODO
### Kafka producer (Java)
```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);
});
```
## 🤔 의사결정 기준 (Decision Criteria)
### Kafka consumer (Python)
```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()))
```
**선택 A를 써야 할 때:**
- *(TODO)*
### Outbox (transactional publish)
```typescript
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
```
**선택 B를 써야 할 때:**
- *(TODO)*
### Schema registry (Avro)
```json
{
"type": "record",
"name": "OrderPlaced",
"fields": [
{ "name": "orderId", "type": "string" },
{ "name": "amount", "type": "long" },
{ "name": "currency", "type": "string", "default": "USD" }
]
}
```
**기본값:**
> *(TODO)*
### Saga orchestration
```typescript
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);
}
}
```
## ❌ 안티패턴 (Anti-Patterns)
### Choreography (each service reacts)
```typescript
// 매 inventory service
on('orders.placed', async event => {
const ok = await reserve(event.orderId);
publish(ok ? 'inventory.reserved' : 'inventory.failed', event);
});
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
// 매 shipping service
on('inventory.reserved', async event => {
await schedule(event.orderId);
publish('shipping.scheduled', event);
});
```
### DLQ (dead letter queue)
```python
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
```python
def idempotent_handler(event):
if redis.set(f'evt:{event.id}', '1', nx=True, ex=86400):
process(event)
# 매 else: skip duplicate
```
### Backpressure
```python
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
```typescript
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
- 부모: [[Architecture]] · [[Distributed-Systems]]
- 변형: [[Event Sourcing Pattern]] · [[CQRS]] · [[Saga-Pattern]]
- 응용: [[Kafka]] · [[NATS]] · [[EventBridge]]
- Adjacent: [[Outbox-Pattern]] · [[Schema-Registry]] · [[Microservices]]
## 🤖 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 |