refactor(topics): 멀티 에이전트용 지식 재편 — _Common(공통 기본기) + Domain_* 구조
에이전트 8종(대화형/프로그래머 C·S/디자이너/설계자/기획자/QA/PD/PM)에게 [공통 기본 능력 + 롤별 Specialty] 2층으로 지식을 주입하기 위한 재분류. 문서 내용·포맷은 무수정, 폴더 이동만 (6,372개 문서 수 보존 확인). - Topic_Programming → Domain_Programming (내부 구조 보존) - Topic_Graphic → Domain_Design - Topic_Business → Domain_Product - Topic_General → Domain_General - _Common 신설: Math(구 Topic_Math_Specialty), Reasoning(구 General/From_Thinking & Reasoning), Reasoning_Creativity(구 General/From_창의성), Communication(Poetic_Blog_Writing + From_writing) - 타 도메인의 From_* 폴더는 유지 (출처 표기일 뿐, 이미 도메인에 맞게 분류된 문서) - 빈 폴더 정리 (memory/procedures) - 에이전트→폴더 매핑은 workspace의 .astra/agent-knowledge-map.json (9개 에이전트) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,206 @@
|
||||
---
|
||||
id: wiki-2026-0508-event-driven-architecture
|
||||
title: Event-Driven Architecture
|
||||
category: 10_Wiki/Topics
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [EDA, event-driven, pub-sub, message-driven, choreography, orchestration]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.97
|
||||
verification_status: applied
|
||||
tags: [architecture, eda, event-driven, kafka, pub-sub, choreography, microservices]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
tech_stack:
|
||||
language: TypeScript / Java / Python
|
||||
framework: 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)
|
||||
```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)
|
||||
```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)
|
||||
```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
|
||||
```
|
||||
|
||||
### Schema registry (Avro)
|
||||
```json
|
||||
{
|
||||
"type": "record",
|
||||
"name": "OrderPlaced",
|
||||
"fields": [
|
||||
{ "name": "orderId", "type": "string" },
|
||||
{ "name": "amount", "type": "long" },
|
||||
{ "name": "currency", "type": "string", "default": "USD" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 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);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 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);
|
||||
});
|
||||
|
||||
// 매 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]]
|
||||
- 응용: [[Kafka]] · [[NATS]]
|
||||
- Adjacent: [[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 |
|
||||
Reference in New Issue
Block a user