{ "version": "1.1", "id": "session-sharing-path", "title": "세션 공유가 실제로 지나는 경로", "question": "두 Keycloak 노드가 같은 세션을 아는 것은 무엇 때문인가", "type": "architecture", "direction": "LR", "audience": [ "Keycloak 을 다중 노드로 운영하는 백엔드 엔지니어" ], "summary": "두 Keycloak 노드가 서로를 발견하는 경로는 JGROUPS_PING이고, 다른 노드의 세션을 아는 실제 공유 경로는 PostgreSQL OFFLINE_USER_SESSION이다.", "alt": "Keycloak replica 두 개에서 JGROUPS_PING으로는 멤버 발견이, OFFLINE_USER_SESSION으로는 세션 저장과 조회가 갈라지는 두 경로.", "long_description": "keycloak-0과 keycloak-1은 JGROUPS_PING을 통해 서로를 발견하지만 sessions cache 엔트리를 서로 복제하지 않는다. 다른 노드가 만든 세션을 알아야 할 때는 PostgreSQL OFFLINE_USER_SESSION을 직접 읽는다. discovery와 session sharing은 같은 데이터베이스 안에서도 다른 책임이다.", "source_context": { "document": "docs/keycloak-session-store/final/document.md", "document_sha256": "28aef96a2bbb94fbb10ade26a71238fee62a5a4d9fa6e7749ae98cfd0a65e560", "anchor": { "kind": "heading", "value": "그런데 첫 실험에서 전제가 무너졌다", "line": 64 } }, "composition": { "profile": "component-flow", "diagram_only": true, "reference_ids": [ "payment-event-flow" ], "rationale": "두 replica를 반복해서 그리지 않고 Keycloak replica 집합에서 발견 테이블과 세션 테이블로 갈리는 두 책임을 분리한다." }, "groups": [], "nodes": [ { "id": "replicas", "label": "Keycloak replica 2개", "kind": "service", "role": "source", "emphasis": "primary", "description": "keycloak-0과 keycloak-1은 각자 sessions cache를 갖고 같은 PostgreSQL을 사용한다.", "details": [ "keycloak-0 · keycloak-1", "sessions cache는 각자" ], "evidence": [ { "start_line": 75, "end_line": 81 } ], "assumption": false }, { "id": "discovery", "label": "JGROUPS_PING", "kind": "datastore", "role": "target", "emphasis": "normal", "description": "노드 discovery와 membership을 위한 테이블이다. 세션 엔트리 복제 경로가 아니다.", "details": [ "노드 둘 등록", "discovery만 담당" ], "evidence": [ { "start_line": 75, "end_line": 75 } ], "assumption": false }, { "id": "session-store", "label": "OFFLINE_USER_SESSION", "kind": "datastore", "role": "target", "emphasis": "primary", "description": "다른 노드가 만든 세션을 직접 읽는 실제 공유 경로다.", "details": [ "keycloak-0 INSERT", "keycloak-1 SELECT" ], "evidence": [ { "start_line": 78, "end_line": 81 } ], "assumption": false } ], "edges": [ { "id": "discovery-path", "from": "replicas", "to": "discovery", "label": "멤버 발견", "kind": "write", "evidence": [ { "start_line": 75, "end_line": 75 } ], "assumption": false }, { "id": "session-path", "from": "replicas", "to": "session-store", "label": "세션 저장 · 조회", "kind": "data", "evidence": [ { "start_line": 78, "end_line": 81 } ], "assumption": false } ], "legend": [], "metadata": { "rationale": "replica 두 개를 각각 두 저장소와 연결하면 선만 교차하고 핵심이 흐려진다. replica 집합에서 발견과 세션 공유 책임이 갈라지는 것으로 압축했다." } }