init: llm-wiki-haness 하네스 설계

This commit is contained in:
DongHyeonka
2026-07-24 14:21:35 +09:00
parent 42bf3db4fd
commit 6c53ded9cb
2436 changed files with 194486 additions and 1 deletions
@@ -0,0 +1,97 @@
<mxfile host="Claude Code" agent="ca-superpowers + diagram-standards v2 minimalist" version="24.0.0" type="device">
<diagram name="ca-skeleton-modules" id="modules">
<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="800" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="title" value="ca-skeleton — Gradle 모듈 의존성 (Clean Architecture)" 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="cmd → presentation → service → domain + cmd → infra → domain. domain 은 어디에도 의존하지 않는다." 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>
<!-- cmd (composition root) -->
<mxCell id="cmd" value="&lt;b&gt;cmd&lt;/b&gt;&#10;composition root" style="rounded=0;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="500" y="110" width="200" height="80" as="geometry" />
</mxCell>
<!-- Middle row: presentation, service, infra -->
<mxCell id="presentation" value="&lt;b&gt;presentation&lt;/b&gt;&#10;HTTP · DTO · Filter" style="rounded=0;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="160" y="260" width="200" height="80" as="geometry" />
</mxCell>
<mxCell id="service" value="&lt;b&gt;service&lt;/b&gt;&#10;UseCase · Command" style="rounded=0;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="500" y="260" width="200" height="80" as="geometry" />
</mxCell>
<mxCell id="infra" value="&lt;b&gt;infra&lt;/b&gt;&#10;JPA · Adapter" style="rounded=0;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="840" y="260" width="200" height="80" as="geometry" />
</mxCell>
<!-- domain (protagonist: pure) -->
<mxCell id="domain" value="&lt;b&gt;domain&lt;/b&gt;&#10;Java stdlib only" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#EFF6FF;strokeColor=#1F6FEB;strokeWidth=2.5;fontSize=12;fontFamily=Pretendard,Helvetica;fontColor=#1F6FEB;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="500" y="420" width="200" height="80" as="geometry" />
</mxCell>
<!-- EDGES (allowed dependencies) -->
<mxCell id="e-cmd-pres" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#57606A;strokeWidth=1.5;" edge="1" parent="1" source="cmd" target="presentation">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e-cmd-svc" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#57606A;strokeWidth=1.5;" edge="1" parent="1" source="cmd" target="service">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e-cmd-infra" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#57606A;strokeWidth=1.5;" edge="1" parent="1" source="cmd" target="infra">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e-pres-svc" value="" 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=#57606A;strokeWidth=1.5;" edge="1" parent="1" source="presentation" target="service">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e-pres-dom" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.2;entryY=0;entryDx=0;entryDy=0;strokeColor=#1F6FEB;strokeWidth=2.5;" edge="1" parent="1" source="presentation" target="domain">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e-svc-dom" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#1F6FEB;strokeWidth=2.5;" edge="1" parent="1" source="service" target="domain">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e-infra-dom" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.8;entryY=0;entryDx=0;entryDy=0;strokeColor=#1F6FEB;strokeWidth=2.5;" edge="1" parent="1" source="infra" target="domain">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<!-- CALLOUT -->
<mxCell id="callout" value="⚠️ &lt;b&gt;HARD-STOP — 금지된 의존&lt;/b&gt;&#10;&#10;✗ domain → Spring / JPA / HTTP / cloud SDK&#10;✗ service → infra 또는 presentation&#10;✗ presentation → infra (또는 JPA Entity 직접 사용)&#10;✗ infra → presentation 또는 controller DTO&#10;✅ ArchUnit + verifyCleanArchitectureDependencies 로 컴파일 타임 강제" 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="120" y="560" width="600" height="140" as="geometry" />
</mxCell>
<!-- LEGEND -->
<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="760" y="560" width="100" height="20" as="geometry" />
</mxCell>
<mxCell id="leg-domain" value="파란 박스 = domain (CA 의 심장 — 순수 Java)" 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="760" y="585" width="420" height="20" as="geometry" />
</mxCell>
<mxCell id="leg-blue-arrow" value="파란 굵은 화살 = → domain (CA 의 본질적 의존 방향)" 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="760" y="605" width="420" height="20" as="geometry" />
</mxCell>
<mxCell id="leg-gray" value="회색 가는 화살 = cmd / presentation→service (조립 의존)" style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=11;fontFamily=Pretendard,Helvetica;fontColor=#57606A;" vertex="1" parent="1">
<mxGeometry x="760" y="625" width="420" height="20" as="geometry" />
</mxCell>
<mxCell id="footer" value="v1 (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="750" width="200" height="20" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
@@ -0,0 +1,100 @@
<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>