Skip to content

Commit 09fbb3b

Browse files
committed
docs(readme): 협업 수명 주기 및 관측성 시각적 증명 추가
피어 리뷰 피드백(비전-구현 간극, 관측성 추상성) 대응으로 README.ko.md에 두 섹션 추가: - 요구사항 변경 시 협업 수명 주기: ecommerce-ddd 샘플의 Order 취소 정책 확장 시나리오(Delivered 24h 내 취소 허용)로 사람/AI/프레임워크 역할 분담 구체화 - 새벽 2시 시각적 증명: 동일 Order 도메인의 InvalidOrderStatusTransition 실패를 JSON 로그 스니펫 + Mermaid 시퀀스 다이어그램으로 시각화하여 trace_id 3-Pillar 전파와 ctx.* 비즈니스 컨텍스트 증명
1 parent ae6efea commit 09fbb3b

1 file changed

Lines changed: 103 additions & 0 deletions

File tree

README.ko.md

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,43 @@ public sealed partial class Email : SimpleValueObject<string>
125125
>
126126
> 프레임워크가 모든 Command/Query에 자동으로 내장하는 **에러 자동 분류 + 구조화된 컨텍스트 로그 + 대시보드가** 코드의 상태를 사람의 언어로 번역합니다.
127127
128+
### 요구사항이 바뀌면? — 인간은 텍스트만, AI는 배관을 다시
129+
130+
> CS팀이 경쟁사 정책 대응을 위해 **"배송 완료 후 24시간 내 단순변심 취소 허용"을** 요청합니다. 기존 규칙은 `Pending/Confirmed` 상태에서만 취소 가능했습니다 ([ecommerce-ddd 샘플의 `Order.Cancel()`](./Docs.Site/src/content/docs/ko/samples/ecommerce-ddd/index.md)).
131+
132+
| 항목 | Before | After |
133+
|------|--------|-------|
134+
| 허용 상태 전이 | `Pending/Confirmed → Cancelled` | 위 규칙 + `Delivered → Cancelled` (단, `DeliveredAt + 24h > now` & `reason = ChangeOfMind`) |
135+
| `Cancel` 메서드 시그니처 | `Cancel() : Fin<Unit>` | `Cancel(CancellationReason reason) : Fin<Unit>` |
136+
| Domain Event | `CancelledEvent(OrderId, OrderLines)` | 위 + `CancellationReason Reason` 필드 |
137+
| 신규 Union 타입 || `CancellationReason = ChangeOfMind \| CustomerIssue \| Fraud` |
138+
139+
**3단계 협업 흐름**:
140+
141+
1. **사람 (아키텍트)** — PRD `§Order.Cancellation`에 한 줄 추가:
142+
> "`Delivered` 상태도 배송 완료 후 24시간 내 단순변심 취소 허용"
143+
144+
2. **AI (`domain-develop` 스킬)** — 아래 5개 산출물을 자동 생성·갱신:
145+
- `OrderStatus.AllowedTransitions``("Delivered", Seq("Cancelled"))` 추가
146+
- `CancellationReason` Union 타입 신규 생성 (3-variant sealed record)
147+
- `Order.Cancel()`에 시간 조건 Specification 주입
148+
- `CancelledEvent``CancellationReason` 필드 확장
149+
- 경계값 단위 테스트 자동 추가 (`23h59m` / `24h00m` / `24h01m`)
150+
151+
3. **프레임워크 (3중 검증 게이트)** — 빌드 타임에 회귀 자동 차단:
152+
- 아키텍처 규칙 테스트: Union `sealed`·record 불변성·`Fin<T>` 반환 검증
153+
- 기존 계약 회귀 테스트: `Pending/Confirmed → Cancelled` 경로가 깨지지 않는지 재확인
154+
- 타입 시스템: `Cancel()` 호출부의 컴파일 타임 시그니처 강제
155+
156+
> **개발자는 `Order.Cancel()` 내부의 `Fin<Unit>` 파이프라인을 열지 않습니다.**
157+
> 텍스트 요구사항만 수정하세요. 상태 전이 규칙·Union 추가·이벤트 확장·테스트 재생성은 AI가 담당하고, 아키텍처 무결성은 [21개 이상의 규칙 테스트가](#게이트-1-아키텍처-규칙-테스트--구조적-무결성) 보장합니다.
158+
159+
| 역할 | 담당 | 이 시나리오에서 |
160+
|------|------|----------------|
161+
| **개발자** | 아키텍트 — 비즈니스 규칙·경계 결정 | "배송 완료 24시간 내 취소" 정책을 텍스트로 정의 |
162+
| **AI 에이전트** | 배관공 — 상태머신·Union·이벤트·테스트 재생성 | `OrderStatus` 확장, `CancellationReason` 생성, 테스트 자동 추가 |
163+
| **프레임워크** | 안전망 — 구조적 회귀 차단 | 아키텍처·타입·기존 계약 자동 검증 |
164+
128165
## AI가 문제를 돌파하는 방법
129166

130167
### 문제에서 코드까지 — AI가 연결하는 구조
@@ -443,6 +480,72 @@ Functorium은 OpenTelemetry 기반의 통합 관측성(Logging, Metrics, Tracing
443480

444481
Application 레이어(EventId 1001–1004)와 Adapter 레이어(EventId 2001–2004)가 **동일한 `request.*` / `response.*` / `error.*` 네이밍을** 사용하므로, 하나의 대시보드 쿼리로 전체 요청 흐름을 추적할 수 있습니다.
445482

483+
### 새벽 2시, 실제로 화면에 무엇이 보이는가
484+
485+
앞서 [요구사항 변경 시나리오](#요구사항이-바뀌면--인간은-텍스트만-ai는-배관을-다시)에서 적용한 "Delivered 24시간 내 취소 허용" 정책이 운영 중 경계값에서 어떻게 실패하는지 시각화합니다.
486+
487+
> `POST /orders/{id}/cancel` (reason=`ChangeOfMind`). 주문은 **25시간 전**에 배송 완료됨 → 24시간 윈도우 초과. 예외는 던져지지 않고, `error.type = "expected"`로 분류된 구조화된 실패 응답이 반환됩니다.
488+
489+
**로그에 남는 것** (Seq·Grafana Loki 등에서 실제로 이렇게 기록됩니다):
490+
491+
```json
492+
{
493+
"@t": "2026-04-20T02:14:33.0421Z",
494+
"EventId": 1002,
495+
"request.category": "OrderManagement",
496+
"request.name": "CancelOrderCommand",
497+
"request_id": "01HXK8Z6Q3N9V7B4M2C1D5E8F0",
498+
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
499+
"ctx.order_id": "01HXK5M2P8X7...",
500+
"ctx.customer_id": "01HXK5M2P8Y1...",
501+
"ctx.order_status_from": "Delivered",
502+
"ctx.order_status_to": "Cancelled",
503+
"ctx.cancellation_reason": "ChangeOfMind",
504+
"ctx.hours_since_delivery": 25,
505+
"error.type": "expected",
506+
"error.codes": ["DomainErrors.Order.InvalidOrderStatusTransition"],
507+
"error.message": "Cancel window (24h) exceeded for ChangeOfMind",
508+
"elapsed_ms": 7,
509+
"status": "Failed"
510+
}
511+
```
512+
513+
**3-Pillar에 같은 `trace_id` / `request_id`로 전파되는 흐름**:
514+
515+
```mermaid
516+
sequenceDiagram
517+
participant C as Client
518+
participant EP as FastEndpoint
519+
participant PL as UsecasePipeline
520+
participant AG as Order Aggregate
521+
participant OT as OpenTelemetry SDK
522+
523+
C->>EP: POST /orders/{id}/cancel
524+
EP->>PL: trace_id=4bf9... + request_id=01HXK...
525+
PL->>AG: Cancel(reason=ChangeOfMind)
526+
AG-->>PL: Fin.Fail(InvalidOrderStatusTransition)
527+
PL->>OT: Log (EventId=1002, error.type="expected")
528+
PL->>OT: Metric (usecase_failed{error_type="expected"}+1)
529+
PL->>OT: Trace span(status=ERROR, tags: ctx.order_id, ctx.hours_since_delivery=25)
530+
PL-->>EP: FinResponse.Fail (HTTP 409)
531+
EP-->>C: error_code="DomainErrors.Order.InvalidOrderStatusTransition"
532+
533+
Note over OT: 세 Pillar 모두 동일 trace_id/request_id 공유<br/>→ 단일 필터로 Logs·Metrics·Traces 교차 추적
534+
```
535+
536+
**전통적 예외 모델 vs Functorium `Fin` 모델**:
537+
538+
| 전통 예외 모델 (OOP) | Functorium `Fin` 모델 |
539+
|---|---|
540+
| `throw new InvalidOperationException(...)` | `Fin.Fail<Unit>(DomainError.For<Order>(...))` |
541+
| 스택 트레이스(소음) | `error.codes[]` + `ctx.*` (시그널) |
542+
| 프로세스 흐름 단절 위험 | 타입 안전한 실패 값 — 흐름 유지 |
543+
| 로그 수동 재조립 필요 | `request_id`·`trace_id` 자동 전파 |
544+
| 비즈니스 에러·시스템 장애 혼재 | `error.type ∈ {expected, exceptional, aggregate}` 자동 분류로 대시보드 필터 가능 |
545+
546+
> **"스택 트레이스가 없다 = 디버깅 불가능"은 거짓입니다.**
547+
> 프레임워크는 스택 트레이스 대신 `error.codes` 배열과 `ctx.*` 비즈니스 컨텍스트로 **어떤 도메인 규칙이 어떤 상태에서 왜 깨졌는지를** 기록합니다. `ctx.hours_since_delivery=25`를 보는 순간 근본 원인이 명확해집니다. 같은 `request_id`로 Logs·Metrics·Traces 세 화면을 동일 사건 기준으로 필터링할 수 있습니다.
548+
446549
상세 사양과 가이드는 문서 사이트에서 확인할 수 있습니다:
447550
- [Observability Specification](./Docs.Site/src/content/docs/spec/08-observability.md) — Field/Tag 구조, ctx.* 3-Pillar Enrichment, Meter/Instrument 사양
448551
- [Logging Guide](./Docs.Site/src/content/docs/guides/observability/19-observability-logging.md) — 구조화된 로깅 상세 가이드

0 commit comments

Comments
 (0)