Files
technical-visualization-haness/examples/work/payment/spec.json
T
2026-07-24 16:31:12 +09:00

252 lines
6.7 KiB
JSON

{
"version": "1.1",
"id": "payment-request",
"title": "승인된 결제는 주문 상태 갱신 후 이벤트로 확산된다",
"question": "결제 요청은 어디를 거쳐 저장되고 승인 후 어떤 이벤트를 발행하는가?",
"type": "data-flow",
"direction": "LR",
"audience": [
"신규 백엔드 개발자",
"운영 엔지니어"
],
"summary": "인증된 결제 요청은 주문을 PENDING으로 저장하고 결제 승인을 받은 뒤 PAID로 갱신되어 payment.approved 이벤트로 전달된다.",
"alt": "클라이언트 결제 요청이 인증 게이트웨이와 체크아웃 API를 거쳐 PostgreSQL, 결제 제공자, 이벤트 버스로 흐르는 데이터 흐름도.",
"long_description": "왼쪽에서 오른쪽으로 읽는다. 클라이언트가 HTTPS 결제 요청을 인증 게이트웨이에 보내고, 검증된 요청이 체크아웃 API로 전달된다. 체크아웃 API는 PostgreSQL에 PENDING 주문을 기록하고 결제 제공자 API에 승인을 요청한다. 승인 응답을 받으면 같은 주문을 PAID로 갱신하고 payment.approved 이벤트를 이벤트 버스에 발행한다.",
"source_context": {
"document": "examples/docs/payment-flow.md",
"document_sha256": "d1449d2ad322f11e735bf5c98ee33311d03ff893ef91eb97b5422f6cc04b0e7c",
"anchor": {
"kind": "marker",
"value": "payment-request",
"line": 15
}
},
"groups": [],
"nodes": [
{
"id": "client",
"label": "클라이언트",
"kind": "actor",
"description": "로그인 세션과 장바구니 식별자를 가지고 결제를 요청한다.",
"evidence": [
{
"start_line": 7,
"end_line": 7
},
{
"start_line": 11,
"end_line": 11
}
],
"assumption": false,
"role": "source",
"shape": "actor"
},
{
"id": "auth-gateway",
"label": "인증 게이트웨이",
"kind": "security",
"description": "세션을 검증하고 유효한 요청만 체크아웃 API로 전달한다.",
"evidence": [
{
"start_line": 7,
"end_line": 7
},
{
"start_line": 11,
"end_line": 11
}
],
"assumption": false,
"role": "service",
"shape": "box"
},
{
"id": "checkout-api",
"label": "체크아웃 API",
"kind": "service",
"description": "주문 상태를 저장하고 결제 승인 및 이벤트 발행을 조정한다.",
"evidence": [
{
"start_line": 7,
"end_line": 7
},
{
"start_line": 11,
"end_line": 13
}
],
"assumption": false,
"role": "service",
"shape": "box",
"emphasis": "primary"
},
{
"id": "orders-db",
"label": "PostgreSQL 주문 저장소",
"kind": "database",
"description": "주문을 PENDING으로 기록하고 승인 후 PAID로 갱신한다.",
"evidence": [
{
"start_line": 13,
"end_line": 13
}
],
"assumption": false,
"role": "store",
"shape": "database"
},
{
"id": "payment-provider",
"label": "결제 제공자 API",
"kind": "service",
"description": "체크아웃 API의 결제 승인 요청을 처리하고 승인 응답을 반환한다.",
"evidence": [
{
"start_line": 13,
"end_line": 13
}
],
"assumption": false,
"role": "service",
"shape": "box"
},
{
"id": "event-bus",
"label": "이벤트 버스",
"kind": "queue",
"description": "승인된 결제를 payment.approved 이벤트로 수신한다.",
"evidence": [
{
"start_line": 13,
"end_line": 13
}
],
"assumption": false,
"role": "sink",
"shape": "queue"
}
],
"edges": [
{
"id": "client-request",
"from": "client",
"to": "auth-gateway",
"label": "HTTPS 결제 요청",
"kind": "request",
"evidence": [
{
"start_line": 11,
"end_line": 11
}
],
"assumption": false
},
{
"id": "validated-request",
"from": "auth-gateway",
"to": "checkout-api",
"label": "검증된 요청 전달",
"kind": "request",
"evidence": [
{
"start_line": 11,
"end_line": 11
}
],
"assumption": false
},
{
"id": "create-pending",
"from": "checkout-api",
"to": "orders-db",
"label": "PENDING 주문 기록",
"kind": "data",
"evidence": [
{
"start_line": 13,
"end_line": 13
}
],
"assumption": false
},
{
"id": "authorization-request",
"from": "checkout-api",
"to": "payment-provider",
"label": "승인 요청",
"kind": "request",
"evidence": [
{
"start_line": 13,
"end_line": 13
}
],
"assumption": false
},
{
"id": "authorization-approved",
"from": "payment-provider",
"to": "checkout-api",
"label": "승인 응답",
"kind": "response",
"evidence": [
{
"start_line": 13,
"end_line": 13
}
],
"assumption": false,
"style": "dashed"
},
{
"id": "mark-paid",
"from": "checkout-api",
"to": "orders-db",
"label": "PAID 상태 갱신",
"kind": "data",
"evidence": [
{
"start_line": 13,
"end_line": 13
}
],
"assumption": false
},
{
"id": "publish-approved",
"from": "checkout-api",
"to": "event-bus",
"label": "payment.approved 발행",
"kind": "publish",
"evidence": [
{
"start_line": 13,
"end_line": 13
}
],
"assumption": false,
"style": "dashed",
"emphasis": "primary"
}
],
"legend": [
{
"symbol": "점선 화살표",
"meaning": "이벤트 발행 경로"
}
],
"metadata": {
"rationale": "독자의 질문이 요청·저장·승인·이벤트의 이동 경로이므로 데이터 흐름도를 선택했다. 실패 경로는 별도 섹션이므로 이 그림의 주 경로에서 제외했다."
},
"composition": {
"profile": "component-flow",
"diagram_only": true,
"reference_ids": [
"payment-event-flow"
],
"rationale": "요청, 상태 저장, 승인 응답, 이벤트 발행이 하나의 방향성 있는 처리 경로를 이루므로 component-flow를 사용한다.",
"focus_node": "checkout-api"
}
}