refactor: 문서 개선 중
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,164 @@
|
||||
{
|
||||
"version": "1.1",
|
||||
"id": "composition-root-seam",
|
||||
"title": "테스트가 끊긴 곳과 실제 런타임이 지나는 합성 루트",
|
||||
"question": "게이트웨이 테스트와 화면 테스트가 통과했는데 왜 합성 루트의 credential 결함은 운영에서만 드러났는가?",
|
||||
"type": "component",
|
||||
"direction": "LR",
|
||||
"audience": [
|
||||
"프론트엔드 개발자",
|
||||
"테스트 설계자"
|
||||
],
|
||||
"summary": "화면 테스트는 게이트웨이를 스텁하고 게이트웨이 테스트는 실행기를 스텁해서, 실제 런타임만 지나는 합성 루트의 credential 결정이 두 테스트에서 빠졌다.",
|
||||
"alt": "화면, 게이트웨이, 합성 루트의 credential 결정, 실제 런타임 어댑터가 이어진 경로. 화면에는 게이트웨이 스텁, 게이트웨이에는 실행기 스텁이 표시되고 합성 루트가 테스트 공백으로 강조되어 있다.",
|
||||
"long_description": "왼쪽에서 오른쪽으로 실제 런타임 경로를 읽는다. 화면에서 게이트웨이로 가고 합성 루트에서 credential을 결정한 뒤 실제 런타임 어댑터가 배포된 백엔드의 실제 404 본문을 읽는다. 화면 테스트는 게이트웨이를 스텁하고 게이트웨이 테스트는 실행기를 스텁했기 때문에 가운데 합성 루트의 credential 결정은 두 테스트가 지나지 않았다.",
|
||||
"source_context": {
|
||||
"document": "docs/TechLog/final/document.md",
|
||||
"document_sha256": "c3a7de37b778fff7b6ea555a3ad7338c91c6fb15d685e7734f89472b4924d955",
|
||||
"anchor": {
|
||||
"kind": "heading",
|
||||
"value": "7. 테스트가 지나지 않는 이음매",
|
||||
"line": 690
|
||||
}
|
||||
},
|
||||
"composition": {
|
||||
"profile": "component-flow",
|
||||
"diagram_only": true,
|
||||
"reference_ids": [
|
||||
"payment-event-flow"
|
||||
],
|
||||
"rationale": "본문은 화면·게이트웨이 테스트가 스텁에서 끊기는 반면 실제 런타임 어댑터가 합성 루트의 credential 결정을 지나가는 경로를 설명한다.",
|
||||
"focus_node": "composition-root"
|
||||
},
|
||||
"groups": [],
|
||||
"nodes": [
|
||||
{
|
||||
"id": "screen",
|
||||
"label": "화면",
|
||||
"kind": "component",
|
||||
"role": "source",
|
||||
"details": [
|
||||
"화면 테스트: gateway stub"
|
||||
],
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 740,
|
||||
"end_line": 742
|
||||
},
|
||||
{
|
||||
"start_line": 770,
|
||||
"end_line": 771
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "gateway",
|
||||
"label": "Gateway",
|
||||
"kind": "service",
|
||||
"role": "service",
|
||||
"details": [
|
||||
"gateway 테스트: executor stub"
|
||||
],
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 766,
|
||||
"end_line": 771
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "composition-root",
|
||||
"label": "Composition Root",
|
||||
"kind": "component",
|
||||
"role": "service",
|
||||
"details": [
|
||||
"credential decision",
|
||||
"테스트 공백"
|
||||
],
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 748,
|
||||
"end_line": 767
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "warning"
|
||||
},
|
||||
{
|
||||
"id": "runtime-adapter",
|
||||
"label": "Runtime Adapter + 404",
|
||||
"kind": "service",
|
||||
"role": "sink",
|
||||
"details": [
|
||||
"실제 어댑터",
|
||||
"배포된 백엔드 404 본문"
|
||||
],
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 769,
|
||||
"end_line": 771
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"id": "screen-gateway",
|
||||
"from": "screen",
|
||||
"to": "gateway",
|
||||
"label": "요청",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 740,
|
||||
"end_line": 742
|
||||
},
|
||||
{
|
||||
"start_line": 766,
|
||||
"end_line": 771
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "gateway-root",
|
||||
"from": "gateway",
|
||||
"to": "composition-root",
|
||||
"label": "runtime 조립",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 766,
|
||||
"end_line": 771
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "root-adapter",
|
||||
"from": "composition-root",
|
||||
"to": "runtime-adapter",
|
||||
"label": "credential 판정",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 755,
|
||||
"end_line": 767
|
||||
},
|
||||
{
|
||||
"start_line": 769,
|
||||
"end_line": 771
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
}
|
||||
],
|
||||
"legend": [],
|
||||
"metadata": {
|
||||
"rationale": "테스트 두 개를 별도 카드로 다시 그리지 않고 실제 런타임 경로에 각 테스트가 어디에서 스텁되는지 details로 표시했다.",
|
||||
"layout_note": "선형 4단계라 LR을 유지한다. 테스트가 끊기는 두 지점과 가운데 composition-root 공백을 한 시야에서 비교하는 것이 목적이다."
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -5,23 +5,28 @@
|
||||
"question": "계약은 앵커 주소를 적어 두었는데 방문자는 왜 404 를 만났는가?",
|
||||
"type": "sequence",
|
||||
"direction": "TB",
|
||||
"audience": ["백엔드 개발자", "프론트엔드 개발자"],
|
||||
"audience": [
|
||||
"백엔드 개발자",
|
||||
"프론트엔드 개발자"
|
||||
],
|
||||
"summary": "만드는 쪽 두 곳이 계약과 다른 슬래시 주소를 만들었고, 그 주소가 게시 시점에 저장돼 방문자에게 그대로 나갔다.",
|
||||
"alt": "계약, 게시 시점 경로 생성, 저장 테이블, 조회 시점 경로 생성, 방문자, 공개 라우트 여섯 참가자 사이에서 주소가 만들어져 저장되고 방문 시 404 로 끝나는 순서도.",
|
||||
"long_description": "위에서 아래로 여섯 번의 이동이 있다. 계약 ProjectDecisionItem 은 공개 주소가 decisions#{slug} 앵커라고 규정한다. 게시 시점의 PublicPaths.forKind 는 그 대신 decisions/{slug} 를 만들어 public_resource_projection 에 저장한다. 조회 시점의 PublicSql.pathOf 가 저장된 주소를 읽고 방문자에게 링크로 내보낸다. 방문자가 그 주소를 요청하면 공개 라우트에는 projects/{slug}/decisions 하나뿐이라 맞는 라우트가 없고 404 가 돌아온다.",
|
||||
"source_context": {
|
||||
"document": "document.md",
|
||||
"document_sha256": "93b9fec4884efa0e6231de07dc27e2b0ac36c9052d3720e28d102d9747ac4f8f",
|
||||
"document": "docs/TechLog/final/document.md",
|
||||
"document_sha256": "c3a7de37b778fff7b6ea555a3ad7338c91c6fb15d685e7734f89472b4924d955",
|
||||
"anchor": {
|
||||
"kind": "marker",
|
||||
"value": "decision-path-404",
|
||||
"line": 673
|
||||
"line": 916
|
||||
}
|
||||
},
|
||||
"composition": {
|
||||
"profile": "sequence",
|
||||
"diagram_only": true,
|
||||
"reference_ids": ["payment-approval-sequence"],
|
||||
"reference_ids": [
|
||||
"payment-approval-sequence"
|
||||
],
|
||||
"rationale": "본문은 주소가 계약에서 규정되고, 게시 시점에 만들어져 저장되고, 조회 시점에 읽혀 방문자에게 나가고, 방문했을 때 404 가 되는 순서를 적는다. 「주소가 게시 시점에 굳는다」가 이 결함의 핵심이라 시점의 순서가 그림의 뼈대여야 한다."
|
||||
},
|
||||
"nodes": [
|
||||
@@ -31,7 +36,12 @@
|
||||
"kind": "participant",
|
||||
"role": "participant",
|
||||
"description": "공개 주소를 앵커로 규정한 OpenAPI 계약.",
|
||||
"evidence": [{ "start_line": 676, "end_line": 678 }],
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 919,
|
||||
"end_line": 921
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
@@ -39,10 +49,17 @@
|
||||
"label": "PublicPaths.forKind",
|
||||
"kind": "participant",
|
||||
"role": "participant",
|
||||
"details": ["게시 시점"],
|
||||
"details": [
|
||||
"게시 시점"
|
||||
],
|
||||
"emphasis": "warning",
|
||||
"description": "게시할 때 공개 주소를 만드는 코드.",
|
||||
"evidence": [{ "start_line": 677, "end_line": 678 }],
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 919,
|
||||
"end_line": 921
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
@@ -51,7 +68,12 @@
|
||||
"kind": "participant",
|
||||
"role": "participant",
|
||||
"description": "만들어진 주소가 저장되는 투영 테이블.",
|
||||
"evidence": [{ "start_line": 682, "end_line": 683 }],
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 925,
|
||||
"end_line": 926
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
@@ -59,10 +81,17 @@
|
||||
"label": "PublicSql.pathOf",
|
||||
"kind": "participant",
|
||||
"role": "participant",
|
||||
"details": ["조회 시점"],
|
||||
"details": [
|
||||
"조회 시점"
|
||||
],
|
||||
"emphasis": "warning",
|
||||
"description": "조회할 때 공개 주소를 만드는 코드.",
|
||||
"evidence": [{ "start_line": 677, "end_line": 678 }],
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 919,
|
||||
"end_line": 921
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
@@ -71,7 +100,12 @@
|
||||
"kind": "actor",
|
||||
"role": "participant",
|
||||
"description": "「다음에 읽을 것」 링크를 따라간 사람.",
|
||||
"evidence": [{ "start_line": 670, "end_line": 671 }],
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 913,
|
||||
"end_line": 914
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
@@ -79,9 +113,16 @@
|
||||
"label": "공개 라우트",
|
||||
"kind": "participant",
|
||||
"role": "participant",
|
||||
"details": ["/projects/{slug}/decisions 하나뿐"],
|
||||
"details": [
|
||||
"/projects/{slug}/decisions 하나뿐"
|
||||
],
|
||||
"description": "결정에는 상세 화면이 없어 라우트가 하나뿐이다.",
|
||||
"evidence": [{ "start_line": 675, "end_line": 676 }],
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 918,
|
||||
"end_line": 919
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
}
|
||||
],
|
||||
@@ -93,7 +134,12 @@
|
||||
"label": "…/decisions#{slug} 로 규정",
|
||||
"kind": "request",
|
||||
"order": 1,
|
||||
"evidence": [{ "start_line": 676, "end_line": 678 }],
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 919,
|
||||
"end_line": 921
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
@@ -104,7 +150,16 @@
|
||||
"kind": "request",
|
||||
"order": 2,
|
||||
"emphasis": "warning",
|
||||
"evidence": [{ "start_line": 675, "end_line": 678 }],
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 919,
|
||||
"end_line": 921
|
||||
},
|
||||
{
|
||||
"start_line": 925,
|
||||
"end_line": 926
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
@@ -114,7 +169,12 @@
|
||||
"label": "저장된 주소 조회",
|
||||
"kind": "response",
|
||||
"order": 3,
|
||||
"evidence": [{ "start_line": 682, "end_line": 683 }],
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 919,
|
||||
"end_line": 926
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
@@ -124,7 +184,12 @@
|
||||
"label": "같은 형태로 링크 전달",
|
||||
"kind": "response",
|
||||
"order": 4,
|
||||
"evidence": [{ "start_line": 677, "end_line": 678 }],
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 913,
|
||||
"end_line": 921
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
@@ -134,7 +199,12 @@
|
||||
"label": "…/decisions/{slug} 요청",
|
||||
"kind": "request",
|
||||
"order": 5,
|
||||
"evidence": [{ "start_line": 670, "end_line": 675 }],
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 913,
|
||||
"end_line": 919
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
@@ -145,7 +215,12 @@
|
||||
"kind": "response",
|
||||
"order": 6,
|
||||
"emphasis": "warning",
|
||||
"evidence": [{ "start_line": 670, "end_line": 675 }],
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 913,
|
||||
"end_line": 919
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
}
|
||||
],
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,155 @@
|
||||
{
|
||||
"version": "1.1",
|
||||
"id": "record-kind-fanout",
|
||||
"title": "새 CONCEPT 종류가 세 영역의 손 목록으로 퍼진 구조",
|
||||
"question": "CONCEPT 하나를 추가했는데 왜 계약·백엔드·프론트엔드 여러 위치를 동시에 고쳐야 했는가?",
|
||||
"type": "dependency",
|
||||
"direction": "LR",
|
||||
"audience": [
|
||||
"프론트엔드 개발자",
|
||||
"백엔드 개발자",
|
||||
"계약 설계자"
|
||||
],
|
||||
"summary": "종류를 손으로 나열한 코드가 여러 영역에 흩어져 있어 CONCEPT 하나가 프론트엔드 9곳, 백엔드 1곳, 계약 3곳에서 따로 빠졌다.",
|
||||
"alt": "새 CONCEPT 노드에서 프론트엔드 손 목록, 백엔드 손 목록, 계약 enum 세 갈래로 퍼지는 팬아웃 그림. 각 갈래에는 실제 누락 건수 9, 1, 3이 적혀 있다.",
|
||||
"long_description": "왼쪽의 새 CONCEPT가 세 갈래로 퍼진다. 프론트엔드에는 게이트웨이 분기, 매퍼, 필터 같은 손 목록이 아홉 곳 있었고, 백엔드에는 PublicSql.pathOf 한 곳이 빠졌다. 계약에는 CatalogEntry.kind, ResolvedRelation.targetKind, RelatedEntry.type 세 enum 누락이 있었다. 아래 본문 표가 열세 위치를 정확히 나열하고, 그림은 왜 한 종류 변경이 세 영역으로 퍼졌는지만 보여 준다.",
|
||||
"source_context": {
|
||||
"document": "docs/TechLog/final/document.md",
|
||||
"document_sha256": "c3a7de37b778fff7b6ea555a3ad7338c91c6fb15d685e7734f89472b4924d955",
|
||||
"anchor": {
|
||||
"kind": "heading",
|
||||
"value": "3. 손으로 나열한 목록이 새 종류를 삼킨다",
|
||||
"line": 311
|
||||
}
|
||||
},
|
||||
"composition": {
|
||||
"profile": "component-flow",
|
||||
"diagram_only": true,
|
||||
"reference_ids": [
|
||||
"payment-event-flow"
|
||||
],
|
||||
"rationale": "정확한 열세 위치는 이미 표가 있으므로, 그림은 새 종류 하나에서 계약·백엔드·프론트엔드로 퍼지는 의존 방향만 보여 준다.",
|
||||
"focus_node": "concept"
|
||||
},
|
||||
"groups": [],
|
||||
"nodes": [
|
||||
{
|
||||
"id": "concept",
|
||||
"label": "CONCEPT",
|
||||
"kind": "message",
|
||||
"role": "source",
|
||||
"details": [
|
||||
"새 Record Kind"
|
||||
],
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 316,
|
||||
"end_line": 331
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary"
|
||||
},
|
||||
{
|
||||
"id": "frontend",
|
||||
"label": "Frontend 손 목록",
|
||||
"kind": "component",
|
||||
"role": "service",
|
||||
"details": [
|
||||
"9곳",
|
||||
"gateway · mapper · filter"
|
||||
],
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 335,
|
||||
"end_line": 345
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "backend",
|
||||
"label": "Backend 손 목록",
|
||||
"kind": "component",
|
||||
"role": "service",
|
||||
"details": [
|
||||
"1곳",
|
||||
"PublicSql.pathOf"
|
||||
],
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 345,
|
||||
"end_line": 349
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "contract",
|
||||
"label": "Contract enums",
|
||||
"kind": "component",
|
||||
"role": "sink",
|
||||
"details": [
|
||||
"3곳",
|
||||
"CatalogEntry.kind",
|
||||
"ResolvedRelation.targetKind",
|
||||
"RelatedEntry.type"
|
||||
],
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 346,
|
||||
"end_line": 352
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"id": "to-frontend",
|
||||
"from": "concept",
|
||||
"to": "frontend",
|
||||
"label": "kind 추가",
|
||||
"kind": "data",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 330,
|
||||
"end_line": 345
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "to-backend",
|
||||
"from": "concept",
|
||||
"to": "backend",
|
||||
"label": "kind 추가",
|
||||
"kind": "data",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 345,
|
||||
"end_line": 349
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "to-contract",
|
||||
"from": "concept",
|
||||
"to": "contract",
|
||||
"label": "enum 추가",
|
||||
"kind": "data",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 346,
|
||||
"end_line": 352
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
}
|
||||
],
|
||||
"legend": [],
|
||||
"metadata": {
|
||||
"rationale": "13개의 동일한 카드 대신 세 영역으로만 묶는다. 정확한 누락 위치와 증상은 본문 표가 유지한다."
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,198 @@
|
||||
{
|
||||
"version": "1.1",
|
||||
"id": "route-fanout",
|
||||
"title": "라우트 하나가 건드리는 손 목록과 검출 시점",
|
||||
"question": "새 라우트 하나가 어디까지 퍼지고, 빠뜨린 항목은 어느 시점에 처음 드러나는가?",
|
||||
"type": "dependency",
|
||||
"direction": "LR",
|
||||
"audience": [
|
||||
"프론트엔드 개발자",
|
||||
"배포 파이프라인 유지보수자"
|
||||
],
|
||||
"summary": "Route Contract에서 런타임·빌드·CI·nginx 쪽 손 목록으로 갈라지고, 누락은 빌드 매니페스트·배포 직전·배포 뒤 서로 다른 시점에 드러난다.",
|
||||
"alt": "새 Route가 Route Contract를 거쳐 Runtime 계약, 배포 전 검사, Edge 서빙 세 묶음으로 갈라지는 팬아웃 그림. 각 묶음에는 누락이 처음 드러나는 시점이 적혀 있다.",
|
||||
"long_description": "왼쪽의 새 Route가 Route Contract로 들어간 뒤 세 갈래로 퍼진다. Runtime 계약에는 runtime 등록과 메시지 카탈로그가 있다. 배포 전 검사에는 vite chunk 이름 표와 접근성 증거·아티팩트 기준선·gate digest가 묶여 있고 누락은 빌드 매니페스트 또는 배포 직전에 드러난다. Edge 서빙 규칙 누락은 하드 로드나 새로고침 때 배포 뒤 404로 드러난다.",
|
||||
"source_context": {
|
||||
"document": "docs/TechLog/final/document.md",
|
||||
"document_sha256": "c3a7de37b778fff7b6ea555a3ad7338c91c6fb15d685e7734f89472b4924d955",
|
||||
"anchor": {
|
||||
"kind": "heading",
|
||||
"value": "8. 라우트를 하나 더하면 함께 울리는 손 목록",
|
||||
"line": 814
|
||||
}
|
||||
},
|
||||
"composition": {
|
||||
"profile": "query-fanout",
|
||||
"diagram_only": true,
|
||||
"reference_ids": [
|
||||
"metrics-query-fanout"
|
||||
],
|
||||
"rationale": "본문의 핵심은 새 Route 하나가 여러 손 목록으로 퍼지는 fan-out이다. 정확한 여덟 위치는 표가 맡고, 그림은 네 소유 묶음과 검출 시점 차이를 보여 준다.",
|
||||
"focus_node": "route-contract"
|
||||
},
|
||||
"groups": [],
|
||||
"nodes": [
|
||||
{
|
||||
"id": "route",
|
||||
"label": "새 Route",
|
||||
"kind": "request",
|
||||
"role": "query",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 816,
|
||||
"end_line": 821
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "route-contract",
|
||||
"label": "Route Contract",
|
||||
"kind": "component",
|
||||
"role": "router",
|
||||
"details": [
|
||||
"tech-log-route-contract.ts"
|
||||
],
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 819,
|
||||
"end_line": 831
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary"
|
||||
},
|
||||
{
|
||||
"id": "runtime",
|
||||
"label": "Runtime 계약",
|
||||
"kind": "component",
|
||||
"role": "store",
|
||||
"details": [
|
||||
"route-runtime-contract",
|
||||
"메시지 카탈로그",
|
||||
"검출: 실행 경로"
|
||||
],
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 824,
|
||||
"end_line": 826
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "predeploy",
|
||||
"label": "배포 전 검사",
|
||||
"kind": "component",
|
||||
"role": "store",
|
||||
"details": [
|
||||
"vite chunk 표 · 빌드 매니페스트",
|
||||
"접근성 증거 · 아티팩트 기준선 · gate digest",
|
||||
"검출: 빌드 / 배포 직전"
|
||||
],
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 828,
|
||||
"end_line": 831
|
||||
},
|
||||
{
|
||||
"start_line": 854,
|
||||
"end_line": 877
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "nginx",
|
||||
"label": "Edge serving",
|
||||
"kind": "component",
|
||||
"role": "store",
|
||||
"details": [
|
||||
"nginx serving contract",
|
||||
"검출: 배포 뒤 404"
|
||||
],
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 827,
|
||||
"end_line": 827
|
||||
},
|
||||
{
|
||||
"start_line": 834,
|
||||
"end_line": 852
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"id": "register",
|
||||
"from": "route",
|
||||
"to": "route-contract",
|
||||
"label": "등록",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 819,
|
||||
"end_line": 831
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "runtime-edge",
|
||||
"from": "route-contract",
|
||||
"to": "runtime",
|
||||
"label": "반영",
|
||||
"kind": "data",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 824,
|
||||
"end_line": 826
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "predeploy-edge",
|
||||
"from": "route-contract",
|
||||
"to": "predeploy",
|
||||
"label": "대조",
|
||||
"kind": "data",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 828,
|
||||
"end_line": 831
|
||||
},
|
||||
{
|
||||
"start_line": 854,
|
||||
"end_line": 877
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "nginx-edge",
|
||||
"from": "route-contract",
|
||||
"to": "nginx",
|
||||
"label": "서빙 패턴",
|
||||
"kind": "data",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 827,
|
||||
"end_line": 827
|
||||
},
|
||||
{
|
||||
"start_line": 834,
|
||||
"end_line": 852
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
}
|
||||
],
|
||||
"legend": [],
|
||||
"metadata": {
|
||||
"rationale": "8개 항목을 같은 카드로 반복하지 않고, 독자가 먼저 알아야 할 fan-out과 검출 시점만 묶었다. 정확한 항목 수와 커밋별 수치는 본문 표에 남긴다.",
|
||||
"layout_note": "세 fan-out 가지를 한 화면에 유지한다. 9px shared-edge-run advisory가 남더라도 의미상 간선이 다른 노드를 통과하지 않는지 overlap 검사와 PNG preview에서 재확인한다."
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,153 @@
|
||||
{
|
||||
"version": "1.1",
|
||||
"id": "summary-drop-path",
|
||||
"title": "summary가 세 경계에서 사라진 경로",
|
||||
"question": "계약과 DB에 있던 summary가 공개 relation 목록까지 오지 못한 세 유실 지점은 어디였는가?",
|
||||
"type": "data-flow",
|
||||
"direction": "LR",
|
||||
"audience": [
|
||||
"프론트엔드 개발자",
|
||||
"계약 설계자"
|
||||
],
|
||||
"summary": "계약에는 summary가 있었지만 flattenRelations가 담지 않았고, ResolvedRelation에는 칸이 없었고, 화면 목록으로 넘길 때 다시 버렸다.",
|
||||
"alt": "Contract summary에서 flattenRelations, ResolvedRelation, 화면 목록으로 이어지는 흐름. 세 중간 지점에 DROP 1, 칸 없음, DROP 3이 표시되어 있다.",
|
||||
"long_description": "왼쪽 Contract에는 summary가 있다. flattenRelations가 그 값을 담지 않아 첫 번째로 끊긴다. 다음 ResolvedRelation 계약에는 summary 칸 자체가 없어 두 번째로 막힌다. 그 칸을 추가한 뒤에도 화면 목록으로 넘길 때 값을 버려 세 번째로 끊겼다. 최종 수정에서는 세 경계를 모두 이어 공개 relation 목록까지 summary가 도착하게 했다.",
|
||||
"source_context": {
|
||||
"document": "docs/TechLog/final/document.md",
|
||||
"document_sha256": "c3a7de37b778fff7b6ea555a3ad7338c91c6fb15d685e7734f89472b4924d955",
|
||||
"anchor": {
|
||||
"kind": "heading",
|
||||
"value": "5. 계약에 자리가 없어 값이 경계에서 사라진다",
|
||||
"line": 516
|
||||
}
|
||||
},
|
||||
"composition": {
|
||||
"profile": "component-flow",
|
||||
"diagram_only": true,
|
||||
"reference_ids": [
|
||||
"payment-event-flow"
|
||||
],
|
||||
"rationale": "본문 자체가 계약에서 화면 목록까지 summary가 지나가는 순서를 네 단계로 적고 세 유실 지점을 명시한다.",
|
||||
"focus_node": "resolved-relation"
|
||||
},
|
||||
"groups": [],
|
||||
"nodes": [
|
||||
{
|
||||
"id": "contract",
|
||||
"label": "Contract summary",
|
||||
"kind": "message",
|
||||
"role": "source",
|
||||
"details": [
|
||||
"summary 있음"
|
||||
],
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 540,
|
||||
"end_line": 547
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "flatten",
|
||||
"label": "flattenRelations",
|
||||
"kind": "component",
|
||||
"role": "service",
|
||||
"details": [
|
||||
"DROP #1"
|
||||
],
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 544,
|
||||
"end_line": 547
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "warning"
|
||||
},
|
||||
{
|
||||
"id": "resolved-relation",
|
||||
"label": "ResolvedRelation",
|
||||
"kind": "component",
|
||||
"role": "service",
|
||||
"details": [
|
||||
"summary 칸 없음",
|
||||
"additionalProperties: false"
|
||||
],
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 546,
|
||||
"end_line": 552
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "warning"
|
||||
},
|
||||
{
|
||||
"id": "screen-list",
|
||||
"label": "화면 relation 목록",
|
||||
"kind": "component",
|
||||
"role": "sink",
|
||||
"details": [
|
||||
"DROP #3"
|
||||
],
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 547,
|
||||
"end_line": 552
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "warning"
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"id": "to-flatten",
|
||||
"from": "contract",
|
||||
"to": "flatten",
|
||||
"label": "summary",
|
||||
"kind": "data",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 544,
|
||||
"end_line": 545
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "to-model",
|
||||
"from": "flatten",
|
||||
"to": "resolved-relation",
|
||||
"label": "렌더 모델",
|
||||
"kind": "data",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 545,
|
||||
"end_line": 550
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "to-screen",
|
||||
"from": "resolved-relation",
|
||||
"to": "screen-list",
|
||||
"label": "화면 전달",
|
||||
"kind": "data",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 546,
|
||||
"end_line": 552
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
}
|
||||
],
|
||||
"legend": [],
|
||||
"metadata": {
|
||||
"rationale": "상위 Concept의 11경계 그림과 겹치지 않도록 이번 사고에서 실제로 summary가 끊긴 세 지점만 그린다.",
|
||||
"layout_note": "네 경계를 한 줄로 따라가는 사고 경로라 LR을 유지한다. 이 그림은 전체 11경계가 아니라 세 유실 지점만 좁힌다."
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -13,12 +13,12 @@
|
||||
"alt": "왼쪽부터 topic, topic_variant, record_variant 로 이어지고 record_variant 가 document·open_question·project_decision 세 테이블을 가리키는 구조도.",
|
||||
"long_description": "왼쪽에 topic 이 있고 variant_label 로 축의 이름을 스스로 정한다. 그 오른쪽에 topic_variant 가 있고 SPA, Mediator, BFF, Forward-Auth 같은 축의 값들을 담는다. 그 오른쪽에 record_variant 가 있고 어느 기록이 어느 축에 걸리는지를 종류와 아이디의 쌍으로 적는다. record_variant 는 오른쪽의 document, open_question, project_decision 세 테이블을 가리키는데, 기록이 종류마다 다른 테이블에 살기 때문에 외래키를 걸지 못하고 쌍으로만 가리킨다.",
|
||||
"source_context": {
|
||||
"document": "document.md",
|
||||
"document_sha256": "93b9fec4884efa0e6231de07dc27e2b0ac36c9052d3720e28d102d9747ac4f8f",
|
||||
"document": "docs/TechLog/final/document.md",
|
||||
"document_sha256": "c3a7de37b778fff7b6ea555a3ad7338c91c6fb15d685e7734f89472b4924d955",
|
||||
"anchor": {
|
||||
"kind": "marker",
|
||||
"value": "topic-variant-model",
|
||||
"line": 1064
|
||||
"line": 1375
|
||||
}
|
||||
},
|
||||
"composition": {
|
||||
@@ -38,8 +38,8 @@
|
||||
"role": "zone",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 1071,
|
||||
"end_line": 1073
|
||||
"start_line": 1382,
|
||||
"end_line": 1384
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
@@ -58,12 +58,12 @@
|
||||
"description": "주제. 축의 이름을 주제가 정한다.",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 1057,
|
||||
"end_line": 1059
|
||||
"start_line": 1368,
|
||||
"end_line": 1370
|
||||
},
|
||||
{
|
||||
"start_line": 1067,
|
||||
"end_line": 1068
|
||||
"start_line": 1377,
|
||||
"end_line": 1379
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
@@ -80,12 +80,12 @@
|
||||
"description": "축의 값들.",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 1060,
|
||||
"end_line": 1060
|
||||
"start_line": 1371,
|
||||
"end_line": 1371
|
||||
},
|
||||
{
|
||||
"start_line": 1047,
|
||||
"end_line": 1048
|
||||
"start_line": 1358,
|
||||
"end_line": 1359
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
@@ -103,12 +103,12 @@
|
||||
"description": "어느 기록이 어느 축에 걸리는지 적는 자리. 외래키를 걸지 못한다.",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 1061,
|
||||
"end_line": 1061
|
||||
"start_line": 1372,
|
||||
"end_line": 1372
|
||||
},
|
||||
{
|
||||
"start_line": 1071,
|
||||
"end_line": 1073
|
||||
"start_line": 1382,
|
||||
"end_line": 1384
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
@@ -123,8 +123,8 @@
|
||||
"description": "기록 테이블 하나.",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 1071,
|
||||
"end_line": 1072
|
||||
"start_line": 1382,
|
||||
"end_line": 1384
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
@@ -139,8 +139,8 @@
|
||||
"description": "기록 테이블 하나.",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 1071,
|
||||
"end_line": 1072
|
||||
"start_line": 1382,
|
||||
"end_line": 1384
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
@@ -155,8 +155,8 @@
|
||||
"description": "기록 테이블 하나.",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 1071,
|
||||
"end_line": 1072
|
||||
"start_line": 1382,
|
||||
"end_line": 1384
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
@@ -172,8 +172,8 @@
|
||||
"style": "solid",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 1057,
|
||||
"end_line": 1060
|
||||
"start_line": 1368,
|
||||
"end_line": 1371
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
@@ -187,8 +187,8 @@
|
||||
"style": "solid",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 1060,
|
||||
"end_line": 1061
|
||||
"start_line": 1371,
|
||||
"end_line": 1372
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
@@ -202,8 +202,8 @@
|
||||
"style": "dashed",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 1061,
|
||||
"end_line": 1073
|
||||
"start_line": 1372,
|
||||
"end_line": 1384
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
@@ -217,8 +217,8 @@
|
||||
"style": "dashed",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 1061,
|
||||
"end_line": 1073
|
||||
"start_line": 1372,
|
||||
"end_line": 1384
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
@@ -232,8 +232,8 @@
|
||||
"style": "dashed",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 1061,
|
||||
"end_line": 1073
|
||||
"start_line": 1372,
|
||||
"end_line": 1384
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
@@ -249,4 +249,4 @@
|
||||
"rationale": "축에 걸리지 않은 기록이 공통 기록이 된다는 규칙과 editorial 칸(thesis·summary·conclusion) 이야기는 같은 절의 문장으로 남긴다. 그림은 자리와 참조 방향만 담는다.",
|
||||
"profile_deviation": "techviz references 가 고른 후보(two-zone-pipeline, sequence, comparison) 밖의 프로필이다. 이 절에는 시간 순서도 두 구역도 비교 대상도 없어 후보로는 그릴 수 없었다."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -11,15 +11,15 @@
|
||||
"아키텍처 검토자"
|
||||
],
|
||||
"summary": "열한 개의 경계를 지나는 자리별로 묶으면 저장 둘, 백엔드 조립 넷, 전선 하나, 프론트엔드 조립 셋, 화면 하나다.",
|
||||
"alt": "저장·백엔드 조립·HTTP envelope·프론트엔드 조립·화면 다섯 묶음을 tech-log-backend·전선·tech-log-frontend 세 구역으로 나눠 이은 흐름도. 묶음마다 그 안에 든 경계 수가 2·4·1·3·1 로 적혀 있다.",
|
||||
"alt": "열한 개 경계를 저장·백엔드 조립·전선·프론트엔드 조립·화면의 다섯 구간으로 묶고, tech-log-backend·HTTP·tech-log-frontend 소유 구역을 함께 표시한 흐름도.",
|
||||
"long_description": "왼쪽에서 오른쪽으로 읽는다. tech-log-backend 구역에 저장 묶음과 백엔드 조립 묶음이 있고 각각 경계 둘과 넷을 담는다. 전선 구역에는 HTTP envelope 하나가 있다. tech-log-frontend 구역에는 프론트엔드 조립 묶음과 화면 컴포넌트가 있고 각각 경계 셋과 하나다. 다 더하면 열한 개이고, 각 경계의 이름은 그림 위 목록에 있다.",
|
||||
"source_context": {
|
||||
"document": "document.md",
|
||||
"document_sha256": "93b9fec4884efa0e6231de07dc27e2b0ac36c9052d3720e28d102d9747ac4f8f",
|
||||
"document": "docs/TechLog/final/document.md",
|
||||
"document_sha256": "c3a7de37b778fff7b6ea555a3ad7338c91c6fb15d685e7734f89472b4924d955",
|
||||
"anchor": {
|
||||
"kind": "marker",
|
||||
"value": "value-boundaries",
|
||||
"line": 82
|
||||
"line": 85
|
||||
}
|
||||
},
|
||||
"composition": {
|
||||
@@ -235,6 +235,7 @@
|
||||
"metadata": {
|
||||
"rationale": "각 경계의 이름은 바로 위 목록이 이미 순서대로 적는다. 그림은 그 열한 개가 어느 소유 구역에 몇 개씩 놓이는지만 담는다.",
|
||||
"profile_deviation": "techviz references 가 고른 후보 밖의 프로필이다. 후보 셋으로는 사슬을 그릴 수 없어 component-flow 로 갔고 lint 는 0 error 로 통과했다.",
|
||||
"layout_note": "LR 로 둔다. TB 는 aspect-ratio 경고를 없애지만 그룹 이름이 잘리고(tech-log-fro) 오른쪽이 비어, 읽기에는 LR 이 낫다. 남는 경고는 advisory 다."
|
||||
"layout_note": "LR 로 둔다. TB 는 aspect-ratio 경고를 없애지만 그룹 이름이 잘리고(tech-log-fro) 오른쪽이 비어, 읽기에는 LR 이 낫다. 남는 경고는 advisory 다.",
|
||||
"advisory_acceptance": "LR aspect-ratio advisory를 허용한다. TB로 바꾸면 그룹 이름이 잘리고 소유 구역 비교가 더 어려워져, 값의 진행 방향과 세 소유 구역을 한 줄에 유지하는 편이 독해에 낫다."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user