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
@@ -10,14 +10,14 @@ SPA, Keycloak, 브라우저 JavaScript memory, Resource Server가 왼쪽에서
## Elements and evidence
- **Public SPA** (service): Authorization Code와 PKCE를 직접 다루고 access JWT로 Resource Server를 호출하는 public OAuth client. Evidence: L144L148.
- **Browser JS memory** (database): Access, refresh, ID token을 실행 중 보관하며 reload 뒤에는 복구하지 않는 browser-side custody. Evidence: L148L150.
- **Keycloak** (service): SPA의 code 교환 상대이며 API가 검증하는 JWT 서명의 출처. Evidence: L144L146.
- **Resource Server** (service): Access JWT의 issuer, 시간 제약과 audience를 검증하는 API. Evidence: L144L150.
- **Public SPA** (service): Authorization Code와 PKCE를 직접 다루고 access JWT로 Resource Server를 호출하는 public OAuth client. Evidence: L168L172.
- **Browser JS memory** (database): Access, refresh, ID token을 실행 중 보관하며 reload 뒤에는 복구하지 않는 browser-side custody. Evidence: L172L174.
- **Keycloak** (service): SPA의 code 교환 상대이며 API가 검증하는 JWT 서명의 출처. Evidence: L168L170.
- **Resource Server** (service): Access JWT의 issuer, 시간 제약과 audience를 검증하는 API. Evidence: L168L174.
## Relationships
- **Keycloak → Public SPA:** access · refresh · ID token. Evidence: L144L148.
- **Public SPA → Keycloak:** Authorization Code + PKCE S256. Evidence: L144L146.
- **Public SPA → Browser JS memory:** token set 보관. Evidence: L148L150.
- **Public SPA → Resource Server:** memory-held access JWT · Bearer. Evidence: L144L150.
- **Keycloak → Public SPA:** access · refresh · ID token. Evidence: L168L172.
- **Public SPA → Keycloak:** Authorization Code + PKCE S256. Evidence: L168L170.
- **Public SPA → Browser JS memory:** token set 보관. Evidence: L172L174.
- **Public SPA → Resource Server:** memory-held access JWT · Bearer. Evidence: L168L174.
@@ -5,16 +5,16 @@
<root>
<mxCell id="0"/>
<mxCell id="1" parent="0"/>
<mxCell id="n_browser-spa" value="Public SPA&lt;br/&gt;spa-public&lt;br/&gt;PKCE S256" tooltip="Authorization Code와 PKCE를 직접 다루고 access JWT로 Resource Server를 호출하는 public OAuth client. | Evidence: L144-L148" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;strokeColor=#2563eb;strokeWidth=2;" vertex="1" parent="1">
<mxCell id="n_browser-spa" value="Public SPA&lt;br/&gt;spa-public&lt;br/&gt;PKCE S256" tooltip="Authorization Code와 PKCE를 직접 다루고 access JWT로 Resource Server를 호출하는 public OAuth client. | Evidence: L168-L172" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;strokeColor=#2563eb;strokeWidth=2;" vertex="1" parent="1">
<mxGeometry x="70.0" y="208.0" width="150.0" height="88.0" as="geometry"/>
</mxCell>
<mxCell id="n_api-resource-server" value="Resource Server&lt;br/&gt;issuer · time&lt;br/&gt;keycloak-pattern-api audience" tooltip="Access JWT의 issuer, 시간 제약과 audience를 검증하는 API. | Evidence: L144-L150" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
<mxCell id="n_api-resource-server" value="Resource Server&lt;br/&gt;issuer · time&lt;br/&gt;keycloak-pattern-api audience" tooltip="Access JWT의 issuer, 시간 제약과 audience를 검증하는 API. | Evidence: L168-L174" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="380.0" y="60.0" width="237.0" height="88.0" as="geometry"/>
</mxCell>
<mxCell id="n_browser-token-memory" value="Browser JS memory&lt;br/&gt;access · refresh · ID token&lt;br/&gt;persistent Web Storage 없음" tooltip="Access, refresh, ID token을 실행 중 보관하며 reload 뒤에는 복구하지 않는 browser-side custody. | Evidence: L148-L150" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
<mxCell id="n_browser-token-memory" value="Browser JS memory&lt;br/&gt;access · refresh · ID token&lt;br/&gt;persistent Web Storage 없음" tooltip="Access, refresh, ID token을 실행 중 보관하며 reload 뒤에는 복구하지 않는 browser-side custody. | Evidence: L172-L174" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="387.0" y="220.0" width="223.0" height="88.0" as="geometry"/>
</mxCell>
<mxCell id="n_keycloak" value="Keycloak" tooltip="SPA의 code 교환 상대이며 API가 검증하는 JWT 서명의 출처. | Evidence: L144-L146" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
<mxCell id="n_keycloak" value="Keycloak" tooltip="SPA의 code 교환 상대이며 API가 검증하는 JWT 서명의 출처. | Evidence: L168-L170" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="423.5" y="380.0" width="150.0" height="64.0" as="geometry"/>
</mxCell>
<mxCell id="e_keycloak-to-spa" value="access · refresh · ID token" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_keycloak" target="n_browser-spa">
@@ -2,22 +2,22 @@
"harness_version": "0.2.0",
"spec_id": "ap1-direct-architecture",
"spec_version": "1.1",
"spec_sha256": "ea8f3f861258a68eabe2e902fb8a5b85ce250a68ef5893eefa8701f1b8eb3627",
"spec_sha256": "b4cf9b9f65e7caca89b4efea39dbab413c71228f327acb8168e3f053e8bfe9c9",
"source_context": {
"document": "document.md",
"document_sha256": "df4d1a604c74e756672b5b40510abfedb8c67b39af280a5f51985ea9972f5371",
"document_sha256": "ea10df24b892e2c57123a37a4b4f0d821e4f394353e6746f50df6a48342353e9",
"anchor": {
"kind": "marker",
"value": "ap1-direct-architecture",
"line": 152
"line": 176
}
},
"outputs": [
"ap1-direct-architecture.svg",
"ap1-direct-architecture.drawio",
"ap1-direct-architecture.mmd",
"ap1-direct-architecture.d2",
"ap1-direct-architecture.dot",
"ap1-direct-architecture.drawio",
"ap1-direct-architecture.excalidraw",
"ap1-direct-architecture.alt.md"
],
@@ -2,7 +2,7 @@
<svg xmlns="http://www.w3.org/2000/svg" width="680" height="535" viewBox="0 0 680 535" role="img" aria-labelledby="diagram-title diagram-description">
<title id="diagram-title">AP1은 OAuth client와 token custody를 브라우저에 둔다</title>
<desc id="diagram-description">왼쪽의 public SPA가 Keycloak과 Authorization Code 및 PKCE S256 계약을 수행한다. Keycloak token 응답의 access, refresh, ID token은 브라우저 JavaScript memory에 놓이며, 그중 access JWT가 오른쪽 Resource Server의 검증 입력이 된다. Resource Server는 issuer, 시간 제약과 keycloak-pattern-api audience를 검증한다.</desc>
<metadata>{&quot;techviz&quot;:{&quot;spec_version&quot;:&quot;1.1&quot;,&quot;id&quot;:&quot;ap1-direct-architecture&quot;,&quot;profile&quot;:&quot;component-flow&quot;},&quot;source_context&quot;:{&quot;document&quot;:&quot;document.md&quot;,&quot;document_sha256&quot;:&quot;df4d1a604c74e756672b5b40510abfedb8c67b39af280a5f51985ea9972f5371&quot;,&quot;anchor&quot;:{&quot;kind&quot;:&quot;marker&quot;,&quot;value&quot;:&quot;ap1-direct-architecture&quot;,&quot;line&quot;:152}},&quot;evidence_policy&quot;:&quot;Each factual element cites source lines or is marked assumption.&quot;,&quot;diagram_only&quot;:true}</metadata>
<metadata>{&quot;techviz&quot;:{&quot;spec_version&quot;:&quot;1.1&quot;,&quot;id&quot;:&quot;ap1-direct-architecture&quot;,&quot;profile&quot;:&quot;component-flow&quot;},&quot;source_context&quot;:{&quot;document&quot;:&quot;document.md&quot;,&quot;document_sha256&quot;:&quot;ea10df24b892e2c57123a37a4b4f0d821e4f394353e6746f50df6a48342353e9&quot;,&quot;anchor&quot;:{&quot;kind&quot;:&quot;marker&quot;,&quot;value&quot;:&quot;ap1-direct-architecture&quot;,&quot;line&quot;:176}},&quot;evidence_policy&quot;:&quot;Each factual element cites source lines or is marked assumption.&quot;,&quot;diagram_only&quot;:true}</metadata>
<defs>
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" />
@@ -50,41 +50,41 @@
</style>
</defs>
<rect class="canvas" width="680" height="535" />
<polyline class="edge kind-response style-dashed emphasis-normal semantic-dashed" points="498.5,444.0 498.5,490.0 145.0,490.0 145.0,296.0" data-evidence="144-148" />
<polyline class="edge kind-response style-dashed emphasis-normal semantic-dashed" points="498.5,444.0 498.5,490.0 145.0,490.0 145.0,296.0" data-evidence="168-172" />
<rect class="edge-label-bg" x="148.3" y="448.0" width="198.9" height="22" rx="3" />
<text class="edge-label" x="247.8" y="463.0">access · refresh · ID token</text>
<polyline class="edge kind-request style-solid emphasis-normal" points="220.0,279.0 331.8,279.0 331.8,421.0 423.5,421.0" data-evidence="144-146" />
<polyline class="edge kind-request style-solid emphasis-normal" points="220.0,279.0 331.8,279.0 331.8,421.0 423.5,421.0" data-evidence="168-170" />
<rect class="edge-label-bg" x="198.2" y="326.0" width="219.0" height="22" rx="3" />
<text class="edge-label" x="307.8" y="341.0">Authorization Code + PKCE S256</text>
<polyline class="edge kind-data style-solid emphasis-normal" points="220.0,243.0 303.5,243.0 303.5,264.0 387.0,264.0" data-evidence="148-150" />
<polyline class="edge kind-data style-solid emphasis-normal" points="220.0,243.0 303.5,243.0 303.5,264.0 387.0,264.0" data-evidence="172-174" />
<rect class="edge-label-bg" x="278.3" y="239.5" width="98.4" height="22" rx="3" />
<text class="edge-label" x="327.5" y="254.5">token set 보관</text>
<polyline class="edge kind-request style-solid emphasis-primary" points="220.0,225.0 300.0,225.0 300.0,104.0 380.0,104.0" data-evidence="144-150" />
<polyline class="edge kind-request style-solid emphasis-primary" points="220.0,225.0 300.0,225.0 300.0,104.0 380.0,104.0" data-evidence="168-174" />
<rect class="edge-label-bg" x="211.1" y="150.5" width="225.7" height="22" rx="3" />
<text class="edge-label" x="324.0" y="165.5">memory-held access JWT · Bearer</text>
<g id="node-browser-spa">
<rect class="node-shape kind-service emphasis-primary role-source" data-evidence="144-148" x="70.0" y="208.0" width="150.0" height="88.0" rx="7" />
<rect class="node-shape kind-service emphasis-primary role-source" data-evidence="168-172" x="70.0" y="208.0" width="150.0" height="88.0" rx="7" />
<text class="node-label" x="145.0" y="235.0">Public SPA</text>
<line class="node-detail-divider" x1="84.0" y1="256.0" x2="206.0" y2="256.0" />
<text class="node-detail" x="86.0" y="273.0">spa-public</text>
<text class="node-detail" x="86.0" y="289.0">PKCE S256</text>
</g>
<g id="node-api-resource-server">
<rect class="node-shape kind-service emphasis-normal role-sink" data-evidence="144-150" x="380.0" y="60.0" width="237.0" height="88.0" rx="7" />
<rect class="node-shape kind-service emphasis-normal role-sink" data-evidence="168-174" x="380.0" y="60.0" width="237.0" height="88.0" rx="7" />
<text class="node-label" x="498.5" y="87.0">Resource Server</text>
<line class="node-detail-divider" x1="394.0" y1="108.0" x2="603.0" y2="108.0" />
<text class="node-detail" x="396.0" y="125.0">issuer · time</text>
<text class="node-detail" x="396.0" y="141.0">keycloak-pattern-api audience</text>
</g>
<g id="node-browser-token-memory">
<rect class="node-shape kind-database emphasis-normal role-store" data-evidence="148-150" x="387.0" y="220.0" width="223.0" height="88.0" rx="7" />
<rect class="node-shape kind-database emphasis-normal role-store" data-evidence="172-174" x="387.0" y="220.0" width="223.0" height="88.0" rx="7" />
<text class="node-label" x="498.5" y="247.0">Browser JS memory</text>
<line class="node-detail-divider" x1="401.0" y1="268.0" x2="596.0" y2="268.0" />
<text class="node-detail" x="403.0" y="285.0">access · refresh · ID token</text>
<text class="node-detail" x="403.0" y="301.0">persistent Web Storage 없음</text>
</g>
<g id="node-keycloak">
<rect class="node-shape kind-service emphasis-normal role-service" data-evidence="144-146" x="423.5" y="380.0" width="150.0" height="64.0" rx="7" />
<rect class="node-shape kind-service emphasis-normal role-service" data-evidence="168-170" x="423.5" y="380.0" width="150.0" height="64.0" rx="7" />
<text class="node-label" x="498.5" y="410.0">Keycloak</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB