digraph techviz { graph [rankdir=LR, splines=ortho, nodesep=0.55, ranksep=0.85]; node [fontname=Helvetica, fontsize=11, margin="0.18,0.12", style="rounded,filled", fillcolor=white, color="#2d4357", penwidth=1.5]; edge [fontname=Helvetica, fontsize=10, color="#364b5f", penwidth=1.4, arrowsize=0.75]; subgraph cluster_0 { label="로그인 구간"; style="rounded,dashed"; color="#66788a"; n0 [label="Keycloak", shape=box, style="rounded,filled"]; n1 [label="AP2 mediator", shape=box, style="rounded,filled"]; n2 [label="AP3 BFF · 로그인", shape=box, style="rounded,filled"]; n3 [label="AP4 oauth2-proxy", shape=box, style="rounded,filled"]; } subgraph cluster_1 { label="애플리케이션 요청 구간"; style="rounded,dashed"; color="#66788a"; n4 [label="AP2 브라우저", shape=box, style="rounded,dashed,filled"]; n5 [label="AP3 BFF · API", shape=box, style="rounded,filled"]; n6 [label="AP4 Nginx", shape=box, style="rounded,filled"]; n7 [label="보호 자원", shape=box, style="rounded,filled"]; } n0 -> n1 [label="code → token", style=solid]; n0 -> n2 [label="code → token", style=solid]; n0 -> n3 [label="OIDC code 교환", style=solid]; n1 -> n4 [label="owner 분리", style=solid]; n2 -> n5 [label="동일 BFF", style=solid]; n3 -> n6 [label="auth 결과", style=solid]; n4 -> n7 [label="Bearer", style=solid]; n5 -> n7 [label="Bearer", style=solid]; n6 -> n7 [label="identity header", style=solid]; }