refactor: 문서 개선 중

This commit is contained in:
donghyeon-ka
2026-09-21 14:30:55 +09:00
parent c93cdea150
commit 805a18f486
1497 changed files with 525837 additions and 59152 deletions
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로 바꾸면 그룹 이름이 잘리고 소유 구역 비교가 더 어려워져, 값의 진행 방향과 세 소유 구역을 한 줄에 유지하는 편이 독해에 낫다."
}
}
}