Files
llm-wiki/raw/diagrams/ca-skeleton/architecture-runtime-topology-2026-05-26.drawio

101 lines
9.3 KiB
Plaintext

<mxfile host="Claude Code" agent="ca-superpowers + diagram-standards v2 minimalist" version="24.0.0" type="device">
<diagram name="ca-skeleton-runtime-topology" id="runtime">
<mxGraphModel dx="1200" dy="700" grid="0" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1200" pageHeight="780" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="title" value="ca-skeleton — 런타임 토폴로지 (mandatory vs optional)" style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=20;fontStyle=1;fontFamily=Pretendard,Helvetica;fontColor=#1F2937;" vertex="1" parent="1">
<mxGeometry x="40" y="20" width="900" height="32" as="geometry" />
</mxCell>
<mxCell id="subtitle" value="앱이 기동하기 위해 반드시 있어야 하는 것 vs APP_ADAPTER_*_ENABLED=false 로 끌 수 있는 것" style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=12;fontStyle=0;fontFamily=Pretendard,Helvetica;fontColor=#6B7280;" vertex="1" parent="1">
<mxGeometry x="40" y="52" width="1000" height="20" as="geometry" />
</mxCell>
<!-- Application boundary (주인공) -->
<mxCell id="grp-app" value="Application (cmd composition root)" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#EFF6FF;strokeColor=#1F6FEB;strokeWidth=2.5;dashed=0;fontSize=12;fontStyle=1;fontFamily=Pretendard,Helvetica;fontColor=#1F6FEB;align=left;verticalAlign=top;spacingLeft=10;spacingTop=6;" vertex="1" parent="1">
<mxGeometry x="300" y="100" width="260" height="200" as="geometry" />
</mxCell>
<!-- External zone (점선 회색) -->
<mxCell id="grp-external" value="External (Internet)" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#F6F8FA;strokeColor=#D0D7DE;strokeWidth=1.5;dashed=1;fontSize=12;fontStyle=1;fontFamily=Pretendard,Helvetica;fontColor=#6B7280;align=left;verticalAlign=top;spacingLeft=10;spacingTop=6;" vertex="1" parent="1">
<mxGeometry x="880" y="100" width="240" height="200" as="geometry" />
</mxCell>
<mxCell id="client" value="&lt;b&gt;Client&lt;/b&gt;&#10;HTTP" style="rounded=8;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeColor=#57606A;strokeWidth=1.5;fontSize=12;fontFamily=Pretendard,Helvetica;fontColor=#24292F;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="100" y="180" width="120" height="60" as="geometry" />
</mxCell>
<!-- App (CA 내부 collapse: 단일 박스로) -->
<mxCell id="app" value="&lt;b&gt;App&lt;/b&gt;&#10;Spring Boot" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeColor=#1F6FEB;strokeWidth=2;fontSize=12;fontFamily=Pretendard,Helvetica;fontColor=#1F6FEB;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="340" y="170" width="180" height="90" as="geometry" />
</mxCell>
<!-- Mandatory: PostgreSQL -->
<mxCell id="db" value="&lt;b&gt;PostgreSQL&lt;/b&gt;&#10;mandatory" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;fillColor=#FFFFFF;strokeColor=#1F6FEB;strokeWidth=2;fontSize=11;fontFamily=Pretendard,Helvetica;fontColor=#1F6FEB;align=center;" vertex="1" parent="1">
<mxGeometry x="620" y="140" width="120" height="60" as="geometry" />
</mxCell>
<!-- Optional: Redis + Kafka (점선 + 주황) -->
<mxCell id="redis" value="&lt;b&gt;Redis&lt;/b&gt;&#10;optional" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;fillColor=#FFFFFF;strokeColor=#FB923C;strokeWidth=1.5;dashed=1;fontSize=11;fontFamily=Pretendard,Helvetica;fontColor=#9A3412;align=center;" vertex="1" parent="1">
<mxGeometry x="620" y="220" width="120" height="50" as="geometry" />
</mxCell>
<mxCell id="kafka" value="&lt;b&gt;Kafka&lt;/b&gt;&#10;optional" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;fillColor=#FFFFFF;strokeColor=#FB923C;strokeWidth=1.5;dashed=1;fontSize=11;fontFamily=Pretendard,Helvetica;fontColor=#9A3412;align=center;" vertex="1" parent="1">
<mxGeometry x="760" y="220" width="120" height="50" as="geometry" />
</mxCell>
<!-- External APIs (집합 — Email · Slack · Google) -->
<mxCell id="external-apis" value="&lt;b&gt;External APIs&lt;/b&gt;&#10;Email · Slack · Google" style="rounded=8;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeColor=#D0D7DE;strokeWidth=1.5;dashed=1;fontSize=12;fontFamily=Pretendard,Helvetica;fontColor=#6B7280;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="920" y="180" width="200" height="60" as="geometry" />
</mxCell>
<!-- EDGES -->
<mxCell id="e1" value="HTTPS REST" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;strokeColor=#1F6FEB;strokeWidth=2.5;fontSize=11;fontStyle=1;fontFamily=Pretendard,Helvetica;fontColor=#1F6FEB;" edge="1" parent="1" source="client" target="app">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e2" value="JDBC" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.3;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;strokeColor=#1F6FEB;strokeWidth=2.5;fontSize=11;fontStyle=1;fontFamily=Pretendard,Helvetica;fontColor=#1F6FEB;" edge="1" parent="1" source="app" target="db">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e3" value="RESP" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.7;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;strokeColor=#FB923C;strokeWidth=1.5;fontSize=11;fontFamily=Pretendard,Helvetica;fontColor=#9A3412;dashed=1;" edge="1" parent="1" source="app" target="redis">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e4" value="Kafka" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.9;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;strokeColor=#FB923C;strokeWidth=1.5;fontSize=11;fontFamily=Pretendard,Helvetica;fontColor=#9A3412;dashed=1;" edge="1" parent="1" source="app" target="kafka">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e5" value="HTTPS" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;strokeColor=#6B7280;strokeWidth=1.5;fontSize=11;fontFamily=Pretendard,Helvetica;fontColor=#6B7280;dashed=1;" edge="1" parent="1" source="app" target="external-apis">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<!-- CALLOUT (실제 trap) -->
<mxCell id="callout" value="⚠️ &lt;b&gt;optional 어댑터가 mandatory 처럼 동작&lt;/b&gt;&#10;&#10;service 에서 RedisCachePort 를 null 검사 없이 의존 →&#10;Redis OFF 시 NPE 로 앱 자체가 죽음. §11 위반.&#10;✅ optional adapter 는 fallback path 또는 Optional&lt;Port&gt; 로." style="rounded=8;whiteSpace=wrap;html=1;fillColor=#FEF2F2;strokeColor=#DC2626;strokeWidth=1.5;fontSize=11;fontFamily=Pretendard,Helvetica;fontColor=#7F1D1D;align=left;verticalAlign=top;spacingLeft=12;spacingTop=8;" vertex="1" parent="1">
<mxGeometry x="100" y="380" width="660" height="120" as="geometry" />
</mxCell>
<!-- LEGEND (3 항목 — §9 표준 컨벤션 외만) -->
<mxCell id="leg-title" value="Legend" style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=11;fontStyle=1;fontFamily=Pretendard,Helvetica;fontColor=#374151;" vertex="1" parent="1">
<mxGeometry x="100" y="540" width="100" height="20" as="geometry" />
</mxCell>
<mxCell id="leg-mand" value="파란 굵은 실선 = mandatory (없으면 기동 실패)" style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=11;fontFamily=Pretendard,Helvetica;fontColor=#1F6FEB;" vertex="1" parent="1">
<mxGeometry x="100" y="565" width="700" height="20" as="geometry" />
</mxCell>
<mxCell id="leg-opt" value="주황 점선 = optional internal adapter (Redis · Kafka — APP_ADAPTER_*_ENABLED=false 로 OFF 가능)" style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=11;fontFamily=Pretendard,Helvetica;fontColor=#9A3412;" vertex="1" parent="1">
<mxGeometry x="100" y="585" width="900" height="20" as="geometry" />
</mxCell>
<mxCell id="footer" value="v2 (minimalist) · 2026-05-26" style="text;html=1;strokeColor=none;fillColor=none;align=right;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=10;fontStyle=2;fontFamily=Pretendard,Helvetica;fontColor=#9CA3AF;" vertex="1" parent="1">
<mxGeometry x="900" y="730" width="200" height="20" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>