Files
2nd/10_Wiki/Topic_Programming/Architecture/Mediator Topology.md
T
Antigravity Agent 9148c358d0 docs(10_Wiki): 위키 전체 재구성 — Topic_* 폴더를 4개 카테고리로 통합 + 대규모 중복 제거
Topic_Agent/Topic_Blog/Topics/Topics_Biz/Topics_Meeting/Topics_Rag의 마크다운 지식 문서를
Topic_General/Topic_Programming/Topic_Graphic/Topic_Business 4개 카테고리로 재분류.

- 중복 제거: frontmatter의 status:duplicate/merged + duplicate_of/redirect_to 필드로
  자기 자신을 중복으로 선언한 리다이렉트 stub 1032개 제거, 완전 동일 내용 파일 472개 제거,
  동일 파일명·다른 내용 충돌 시 더 큰(완전한) 버전만 유지(162개 제거) — 총 1639개 중복 제거.
- 분류: 폴더 단위로 명확한 항목(AI_and_ML/Coding/Architecture 등 → Programming,
  Comfyui/Visual_Effects → Graphic, Topics_Biz/Topics_Meeting/사업 등 → Business,
  Poetic_Blog_Writing/창의성/Game_Design 등 → General)은 폴더 우선순위로,
  나머지 혼재 폴더(Topic_Agent/Topic_Blog/Topics 루트/Thinking & Reasoning/Other/UI_UX_Assets)는
  title/tags 키워드 스코어링으로 파일 단위 분류(불명확한 경우 General로 폴백).
  원본 폴더명은 "From_*" 서브폴더로 보존해 추적 가능성 유지.
- 최종 배치: Programming 2784 / General 1608 / Graphic 285 / Business 249 = 4926개 문서.
- 에이전트 운영 상태(.astra/.agent/.obsidian/sessions/memory/_company/docs/lessons/_shared/src)는
  지식 콘텐츠가 아니므로 재분류 대상에서 제외하고 원위치 유지.
- Topics/Topic_email(상위 보호 폴더 Topic_email과 파일명 100% 중복) 삭제 — 보호 폴더 자체는 미변경.
- 완전히 비게 된 Topic_Agent/Topic_Blog/Topics_Biz/Topics_Rag 폴더 제거.
2026-07-05 00:33:48 +09:00

8.8 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-mediator-topology Mediator Topology 10_Wiki/Topics verified self
Event Mediator Topology
Mediator-Based Event-Driven Architecture
none A 0.9 applied
event-driven
architecture-topology
orchestration
2026-05-10 pending
language framework
typescript temporal

Mediator Topology

매 한 줄

"매 central orchestrator 가 매 multi-step event flow 를 직접 지휘". Mark Richards, Software Architecture Patterns — Event-Driven Architecture 의 두 topology 중 하나 (다른 하나는 Broker). Mediator 는 매 sequence + error handling + transactional rollback 이 필요한 매 complex workflow 에 적합. 2026 의 modern 구현: Temporal, AWS Step Functions, Camunda 8, Netflix Conductor.

매 핵심

매 Mediator vs Broker (Richards 의 dichotomy)

  • Broker: 매 chain of events, decentralized, 매 service 가 매 다음 step 결정. Pub/sub. 매 simple, fast, hard-to-orchestrate complex workflow.
  • Mediator: 매 central event mediator 가 매 process 를 orchestrate. 매 sequence 명시, 매 error handling 중앙화. 매 complex but observable.

매 Mediator components

  1. Event Queue: incoming initial events.
  2. Event Mediator: 매 process orchestrator (workflow engine).
  3. Event Channel: mediator → processor 의 dispatch.
  4. Event Processor: 매 single step 실행 (idempotent worker).

매 응용 (when to use mediator)

  1. Order fulfillment (validate → pay → reserve → ship → notify).
  2. Loan approval (multi-stage with human-in-loop).
  3. Subscription onboarding.
  4. ETL/data pipeline with retries and DLQ.
  5. SAGA pattern compensation orchestration.

매 trade-off vs Broker

  • More observable: 매 mediator 의 single source of truth for workflow state.
  • More coupled: 매 mediator 의 process knowledge — 매 evolution 시 central change.
  • Lower throughput: 매 mediator 의 single point.
  • Easier to reason: 매 sequence 가 명시 — debugging.

💻 패턴

1. Temporal workflow (mediator, 2026 standard)

// activities.ts (event processors)
export async function validateOrder(o: Order) { /* ... */ }
export async function chargePayment(o: Order) { /* ... */ }
export async function reserveInventory(o: Order) { /* ... */ }
export async function ship(o: Order) { /* ... */ }
export async function notify(userId: string) { /* ... */ }

// workflow.ts (mediator)
import { proxyActivities } from "@temporalio/workflow";
import type * as activities from "./activities";

const acts = proxyActivities<typeof activities>({
  startToCloseTimeout: "1 minute",
  retry: { maximumAttempts: 5 },
});

export async function orderWorkflow(order: Order) {
  await acts.validateOrder(order);
  try {
    await acts.chargePayment(order);
    await acts.reserveInventory(order);
    await acts.ship(order);
  } catch (err) {
    // SAGA compensation
    await acts.refundPayment(order).catch(() => {});
    await acts.releaseInventory(order).catch(() => {});
    throw err;
  }
  await acts.notify(order.userId);
}

2. AWS Step Functions (managed mediator)

{
  "StartAt": "Validate",
  "States": {
    "Validate": { "Type": "Task", "Resource": "...:validate", "Next": "Charge" },
    "Charge":   { "Type": "Task", "Resource": "...:charge",
                  "Catch": [{ "ErrorEquals": ["PaymentError"], "Next": "Refund" }],
                  "Next": "Reserve" },
    "Reserve":  { "Type": "Task", "Resource": "...:reserve", "Next": "Ship" },
    "Ship":     { "Type": "Task", "Resource": "...:ship",     "Next": "Notify" },
    "Notify":   { "Type": "Task", "Resource": "...:notify",   "End": true },
    "Refund":   { "Type": "Task", "Resource": "...:refund",   "Next": "Fail" },
    "Fail":     { "Type": "Fail" }
  }
}

3. Camunda 8 (BPMN mediator)

<!-- order.bpmn (visual model, executable) -->
<bpmn:process id="orderProcess">
  <bpmn:startEvent id="OrderReceived" />
  <bpmn:serviceTask id="Validate" zeebe:type="validate-order" />
  <bpmn:serviceTask id="Charge"  zeebe:type="charge-payment" />
  <bpmn:exclusiveGateway id="ChargeOk?" />
  <bpmn:serviceTask id="Reserve" zeebe:type="reserve-inventory" />
  <!-- ... compensation events for SAGA -->
</bpmn:process>

4. Custom mediator (lightweight)

type Step<S> = { name: string; run: (s: S) => Promise<S>; compensate?: (s: S) => Promise<void> };

class Mediator<S> {
  constructor(private steps: Step<S>[]) {}

  async execute(initial: S): Promise<S> {
    const completed: Step<S>[] = [];
    let state = initial;
    try {
      for (const step of this.steps) {
        state = await step.run(state);
        completed.push(step);
      }
      return state;
    } catch (err) {
      // SAGA compensate in reverse
      for (const step of completed.reverse()) {
        await step.compensate?.(state).catch(() => {});
      }
      throw err;
    }
  }
}

const orderMediator = new Mediator<Order>([
  { name: "validate", run: validateOrder },
  { name: "charge", run: chargePayment, compensate: refundPayment },
  { name: "reserve", run: reserveInventory, compensate: releaseInventory },
  { name: "ship", run: ship },
]);

5. Broker (contrast — for comparison)

// No central mediator. Each service publishes its own next event.
// order-service: emits "order.validated"
// payment-service: subscribes "order.validated" → publishes "order.paid"
// inventory-service: subscribes "order.paid" → publishes "inventory.reserved"
// shipping-service: subscribes "inventory.reserved" → publishes "order.shipped"
//
// Pros: decoupled, scalable
// Cons: workflow knowledge scattered, hard to add/reorder steps

6. Compensation pattern (SAGA)

// Within mediator, each step has forward + compensating action
const steps = [
  { do: chargePayment,       undo: refundPayment },
  { do: reserveInventory,    undo: releaseInventory },
  { do: scheduleShipment,    undo: cancelShipment },
];

async function saga<S>(state: S) {
  const done: typeof steps = [];
  for (const s of steps) {
    try { await s.do(state); done.push(s); }
    catch {
      for (const d of done.reverse()) await d.undo(state).catch(() => {});
      throw new Error("saga compensated");
    }
  }
}

7. Idempotency (essential for mediator workers)

async function chargePayment(order: Order) {
  const idempotencyKey = `charge:${order.id}`;
  const existing = await db.idempotency.findOne(idempotencyKey);
  if (existing) return existing.result;

  const result = await stripe.charges.create({
    amount: order.amount,
    customer: order.customerId,
    idempotency_key: idempotencyKey,
  });
  await db.idempotency.put(idempotencyKey, result);
  return result;
}
// Mediator may retry → worker MUST be idempotent.

매 결정 기준

상황 Topology
<5 step linear flow, simple notify Broker (pub/sub).
Multi-step with rollback / SAGA Mediator.
Long-running (hours/days) workflow Mediator (Temporal/Step Functions).
Human approval steps Mediator (BPMN — Camunda).
High-throughput stream (>10k/s) Broker (Kafka).
Audit + visibility critical Mediator.
Loose coupling priority Broker.

기본값: complex business process 는 매 Mediator (Temporal). Simple notification/log 는 매 Broker (Kafka/SNS).

🔗 Graph

🤖 LLM 활용

언제: workflow architecture choice, SAGA design, multi-step business process modeling, retry/compensation strategy. 언제 X: 매 simple fire-and-forget event, 매 high-throughput streaming (broker preferred).

안티패턴

  • God mediator: 매 매 모든 process 가 매 single mediator 에 — 매 monolith of orchestration. 매 domain 별 분리.
  • Non-idempotent worker: 매 mediator retry → 매 double-charge / double-ship. 매 idempotency key 필수.
  • Mediator knows business rules: 매 if/else 분기 가 매 mediator 에 — workflow engine 의 limit. 매 decision 은 activity 로 push.
  • Sync mediator for slow steps: 매 mediator 가 매 slow IO 의 inline wait — 매 timeout. 매 async + signal/callback.
  • No timeout/retry policy: 매 hung workflow 의 매 stuck instance.
  • Compensation 누락: 매 SAGA 의 매 partial commit 의 매 inconsistent state.

🧪 검증 / 중복

  • Verified (Richards, Software Architecture Patterns O'Reilly 2015; Temporal docs; Hohpe & Woolf, Enterprise Integration Patterns — Process Manager).
  • 신뢰도 A.

🕓 Changelog

날짜 변경
2026-05-08 Phase 1
2026-05-10 Manual cleanup — Mediator vs Broker + Temporal/Step Functions/Camunda 2026 implementations