Files
document-haness/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.svg
T

96 lines
7.8 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="707" height="605" viewBox="0 0 707 605" role="img" aria-labelledby="diagram-title diagram-description">
<title id="diagram-title">열린 질문 네 개가 닿은 곳</title>
<desc id="diagram-description">Q1은 저장소를 밖으로 빼면 다중 인스턴스와 재시작은 풀리지만 기본키에 session id가 없어 덮어쓰기와 정리 문제가 남는다는 답이다. Q2는 refresh 경쟁이 감지되면 client session이 지워져 이긴 요청의 새 token도 쓸 수 없다는 답이다. Q3는 Application Session과 OAuth2AuthorizedClient의 조회 키가 달라 각각 저장소를 결정해야 한다는 답이다. Q4는 위조 헤더가 permitAll echo까지 도착해도 JWT 보호 경로는 401이었고, 헤더 삭제 처방은 미적용이며 IdP claim 변경은 재인증 전까지 반영되지 않는다는 답이다.</desc>
<metadata>{&quot;techviz&quot;:{&quot;spec_version&quot;:&quot;1.1&quot;,&quot;id&quot;:&quot;open-questions-answered&quot;,&quot;profile&quot;:&quot;component-flow&quot;},&quot;source_context&quot;:{&quot;document&quot;:&quot;docs/keycloak-session-store/final/document.md&quot;,&quot;document_sha256&quot;:&quot;28aef96a2bbb94fbb10ade26a71238fee62a5a4d9fa6e7749ae98cfd0a65e560&quot;,&quot;anchor&quot;:{&quot;kind&quot;:&quot;heading&quot;,&quot;value&quot;:&quot;열린 질문 네 개에 대한 답&quot;,&quot;line&quot;:1221}},&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" />
</marker>
<style>
:root { color-scheme: light; }
text { font-family: Inter, Pretendard, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #111827; }
.canvas { fill: #ffffff; }
.group-box { fill: #ffffff; stroke: #9ca3af; stroke-width: 1.4; stroke-dasharray: 7 5; }
.group-label-bg { fill: #ffffff; }
.group-label { font-size: 13px; font-weight: 650; fill: #374151; }
.edge { fill: none; stroke: #374151; stroke-width: 1.8; stroke-linejoin: round; stroke-linecap: round; marker-end: url(#arrow); }
.edge.style-dashed, .edge.semantic-dashed, .edge.assumption { stroke-dasharray: 7 5; }
.edge.style-dotted { stroke-dasharray: 2 5; }
.edge.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
.edge.emphasis-muted { stroke: #9ca3af; }
.edge.emphasis-warning, .edge.kind-failure, .edge.kind-error { stroke: #dc2626; stroke-width: 2.2; }
.edge-label-bg { fill: #ffffff; }
.edge-label { font-size: 12px; font-weight: 560; text-anchor: middle; }
.node-shape { fill: #ffffff; stroke: #4b5563; stroke-width: 1.7; }
.node-shape.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
.node-shape.emphasis-muted { stroke: #9ca3af; fill: #f9fafb; }
.node-shape.emphasis-warning { stroke: #d97706; stroke-width: 2; fill: #fffdf5; }
.node-shape.kind-database, .node-shape.kind-datastore, .node-shape.kind-storage { fill: #f8fafc; }
.node-shape.kind-queue, .node-shape.kind-event, .node-shape.kind-topic { fill: #fafafa; }
.node-shape.assumption { stroke-dasharray: 4 4; }
.storage-bottom, .controller-divider { fill: none; stroke: #4b5563; stroke-width: 1.4; }
.controller-led { fill: #4b5563; }
.actor-symbol { fill: none; stroke: #4b5563; stroke-width: 1.8; stroke-linecap: round; }
.actor-symbol.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
.node-label { font-size: 14px; font-weight: 650; text-anchor: middle; }
.node-role { font-size: 10px; letter-spacing: 0.04em; text-anchor: middle; fill: #6b7280; }
.node-detail-divider { stroke: #d1d5db; stroke-width: 1; }
.node-detail { font-size: 11px; fill: #374151; }
.assumption-badge { font-size: 9px; font-weight: 700; fill: #92400e; }
.failure-mark { stroke: #dc2626; stroke-width: 4; stroke-linecap: round; }
.lifeline { stroke: #9ca3af; stroke-width: 1.2; stroke-dasharray: 5 5; }
.timeline-axis { stroke: #374151; stroke-width: 1.8; marker-end: url(#arrow); }
.timeline-stem { stroke: #6b7280; stroke-width: 1.3; }
.timeline-marker { fill: #ffffff; stroke: #374151; stroke-width: 1.7; }
.timeline-marker.primary { fill: #2563eb; stroke: #2563eb; }
.timeline-marker.warning { fill: #dc2626; stroke: #dc2626; }
.timeline-label { font-size: 13px; font-weight: 650; text-anchor: middle; }
.timeline-detail { font-size: 11px; fill: #4b5563; text-anchor: middle; }
</style>
</defs>
<rect class="canvas" width="707" height="605" />
<polyline class="edge kind-request style-solid emphasis-normal" points="223.0,288.0 329.2,288.0 329.2,95.5 435.5,95.5" data-evidence="1225-1225" />
<rect class="edge-label-bg" x="331.2" y="177.7" width="44.0" height="22" rx="3" />
<text class="edge-label" x="353.2" y="192.7"></text>
<polyline class="edge kind-request style-solid emphasis-normal" points="223.0,302.7 334.5,302.7 334.5,238.5 446.0,238.5" data-evidence="1226-1226" />
<rect class="edge-label-bg" x="336.5" y="256.6" width="44.0" height="22" rx="3" />
<text class="edge-label" x="358.5" y="271.6"></text>
<polyline class="edge kind-request style-solid emphasis-normal" points="223.0,317.3 325.8,317.3 325.8,381.5 428.5,381.5" data-evidence="1227-1227" />
<rect class="edge-label-bg" x="327.8" y="335.4" width="44.0" height="22" rx="3" />
<text class="edge-label" x="349.8" y="350.4"></text>
<polyline class="edge kind-request style-solid emphasis-normal" points="223.0,332.0 303.0,332.0 303.0,524.5 383.0,524.5" data-evidence="1228-1228" />
<rect class="edge-label-bg" x="305.0" y="414.3" width="44.0" height="22" rx="3" />
<text class="edge-label" x="327.0" y="429.3"></text>
<g id="node-questions">
<rect class="node-shape kind-component emphasis-primary role-source" data-evidence="1223-1228" x="70.0" y="274.5" width="153.0" height="71.0" rx="7" />
<text class="node-label" x="146.5" y="301.5">열린 질문 네 개</text>
<line class="node-detail-divider" x1="84.0" y1="322.5" x2="209.0" y2="322.5" />
<text class="node-detail" x="86.0" y="339.5">Q1 · Q2 · Q3 · Q4</text>
</g>
<g id="node-q1">
<rect class="node-shape kind-process emphasis-warning role-target" data-evidence="1225-1225" x="435.5" y="60.0" width="174.0" height="71.0" rx="7" />
<text class="node-label" x="522.5" y="87.0">Q1 · 저장소와 스키마</text>
<line class="node-detail-divider" x1="449.5" y1="108.0" x2="595.5" y2="108.0" />
<text class="node-detail" x="451.5" y="125.0">외부 저장소 · 세션 id 없는 PK</text>
</g>
<g id="node-q2">
<rect class="node-shape kind-process emphasis-warning role-target" data-evidence="1226-1226" x="446.0" y="203.0" width="153.0" height="71.0" rx="7" />
<text class="node-label" x="522.5" y="230.0">Q2 · 회전 경쟁</text>
<line class="node-detail-divider" x1="460.0" y1="251.0" x2="585.0" y2="251.0" />
<text class="node-detail" x="462.0" y="268.0">이긴 새 token도 사용 불가</text>
</g>
<g id="node-q3">
<rect class="node-shape kind-process emphasis-normal role-target" data-evidence="1227-1227" x="428.5" y="346.0" width="188.0" height="71.0" rx="7" />
<text class="node-label" x="522.5" y="373.0">Q3 · 조회 키 분리</text>
<line class="node-detail-divider" x1="442.5" y1="394.0" x2="602.5" y2="394.0" />
<text class="node-detail" x="444.5" y="411.0">session id · principal</text>
</g>
<g id="node-q4">
<rect class="node-shape kind-process emphasis-warning role-target" data-evidence="1228-1228" x="383.0" y="489.0" width="279.0" height="71.0" rx="7" />
<text class="node-label" x="522.5" y="516.0">Q4 · Edge 신뢰 경계</text>
<line class="node-detail-divider" x1="397.0" y1="537.0" x2="648.0" y2="537.0" />
<text class="node-detail" x="399.0" y="554.0">permitAll 200 · JWT 401 · 삭제 처방 미검증</text>
</g>
</svg>