The keycloak project ended with four open questions that design could not
settle. A two-VM lab was built to answer them by measurement, and this is
that material: 26 experiments, 125 raw command outputs, 22 browser captures.
Follows the import procedure in README.md.
source/ the originating repository verbatim — 78 documents, 28 SVGs,
8 manifests, plus .source-revision recording the commit
final/ the SSOT
document.md 729 lines written from the 29 experiment documents, not
concatenated: what was predicted, what was measured, and
where the measurement itself was wrong
evidence/raw 125 outputs, flattened to <experiment>__<file> because
the originals collided (01-baseline.txt appeared three
times) and the audit only globs the top level
evidence/meta one per raw file; command and exitCode are null and the
README says why rather than inventing them
evidence/browser 22 captures
assets/ three diagrams through techviz
.techviz/ their VizSpecs
A separate project rather than an addition to keycloak: the B-layer answers
that project's four questions, but the A, C and D layers are about cluster
failure, SSO and operations, and one document.md should hold one subject.
The four question records there can point here through 관계.
Recorded rather than papered over: only three of the 28 diagrams were
remade. The repository forbids hand-drawn SVG and forbids titles inside the
canvas; all 28 originals carry both, so converting them is redrawing, not
reformatting. They stay in source/ and the gap is written into the document.
verify-pipeline.py passes. audit-records.py reports no issues.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
16 KiB
schemaVersion, exampleOnly, generationAllowed, project, sourceDocument, sourceDocumentSha256, sourceRevision, generatedAt
| schemaVersion | exampleOnly | generationAllowed | project | sourceDocument | sourceDocumentSha256 | sourceRevision | generatedAt |
|---|---|---|---|---|---|---|---|
| 1 | true | false | backend-clean-architecture | final/document.md | <example-only> | <example-only> | <example-only> |
Root Tree Example
이 파일은 구조 예시다. 실제
/shared/codebase/backend-clean-architecture분석을 수행해 만든 결과가 아니므로 downstream 문서 생성에 사용하지 않는다. 실제 프로젝트에서는 동일한 형식으로 source anchor와 evidence를 채우고 readiness를 판정한다.
PROJECT backend-clean-architecture
TOPIC JPA 피드 조회 성능 jpa-feed-query-performance
├── CASE │ ├── DTO 변환 과정에서 발생한 Highlight 컬렉션 N+1 │ ├── 필드 접근 없이 발생한 EAGER ToOne N+1 │ ├── Fetch Join으로 N+1을 해결하다 만난 MultiBag과 행 폭증 │ ├── Collection Fetch Join Pagination의 In-memory Paging │ ├── Projection 이후에도 1,509행을 읽은 Row Over-fetch │ └── Visibility OR이 Keyset Index를 깨뜨린 문제 │ ├── REFERENCE │ ├── JPA N+1 정량 진단 기준 │ ├── Fetch Type과 Fetch Strategy 구분 │ ├── Fetch Join · Batch · Projection 선택 기준 │ ├── Top-N-per-group 선택 기준 │ ├── Keyset Pagination 설계 기준 │ ├── Feed Visibility Query Pattern │ └── PostgreSQL Query Plan 측정 기준 │ ├── OPEN QUESTION │ ├── Highlight 없는 FeedItem을 허용할 것인가 │ ├── Round Trip과 Row Volume을 독립 측정할 것인가 │ ├── ANALYZE 이후 Cardinality Estimate는 어떻게 달라지는가 │ ├── feed_visible을 Production CQRS로 승격할 것인가 │ └── 실제 동시 트래픽에서도 이 구조가 안정적인가 │ └── DECISION ├── Query Plan은 실제 PostgreSQL에서 측정한다 ├── Query Strategy는 FeedQueryPort 뒤에서 소유한다 ├── Collection Fetch Join과 Pagination을 같이 사용하지 않는다 ├── Entity Graph 조회에는 Batch Fetch를 사용한다 ├── 화면 조회는 Read Projection을 사용한다 ├── Feed Pagination은 Keyset을 사용한다 └── 현재 Read Model은 CQRS-lite로 유지한다
Node Specifications
CASE — DTO 변환 과정에서 발생한 Highlight 컬렉션 N+1
- slug:
highlight-collection-n-plus-one - readiness:
BLOCKED - source:
final/document.md#컬렉션-n1-정량화
- code:
<actual source path/symbol from analyzed project>
- evidence:
<actual raw/query-plan/test evidence path>
- classification:
상세 분석에서 이 제목에 해당하는 구체적 발생 조건, 관측 결과, 진단 순서가 확인될 때 Case가 된다. - missing-verification:
example only — 실제 project source/evidence 확인 필요 - relations:
<related Reference/Question/Decision slug and reason>
CASE — 필드 접근 없이 발생한 EAGER ToOne N+1
- slug:
eager-to-one-n-plus-one - readiness:
BLOCKED - source:
final/document.md#user-page-연관-숨은-추가-쿼리-정량화
- code:
<actual source path/symbol from analyzed project>
- evidence:
<actual raw/query-plan/test evidence path>
- classification:
상세 분석에서 이 제목에 해당하는 구체적 발생 조건, 관측 결과, 진단 순서가 확인될 때 Case가 된다. - missing-verification:
example only — 실제 project source/evidence 확인 필요 - relations:
<related Reference/Question/Decision slug and reason>
CASE — Fetch Join으로 N+1을 해결하다 만난 MultiBag과 행 폭증
- slug:
fetch-join-multibag-row-explosion - readiness:
BLOCKED - source:
final/document.md#fetch-join을-적용하며-확인한-두-가지-문제
- code:
<actual source path/symbol from analyzed project>
- evidence:
<actual raw/query-plan/test evidence path>
- classification:
상세 분석에서 이 제목에 해당하는 구체적 발생 조건, 관측 결과, 진단 순서가 확인될 때 Case가 된다. - missing-verification:
example only — 실제 project source/evidence 확인 필요 - relations:
<related Reference/Question/Decision slug and reason>
CASE — Collection Fetch Join Pagination의 In-memory Paging
- slug:
collection-fetch-join-in-memory-pagination - readiness:
BLOCKED - source:
final/document.md#컬렉션-fetch-join-페이징
- code:
<actual source path/symbol from analyzed project>
- evidence:
<actual raw/query-plan/test evidence path>
- classification:
상세 분석에서 이 제목에 해당하는 구체적 발생 조건, 관측 결과, 진단 순서가 확인될 때 Case가 된다. - missing-verification:
example only — 실제 project source/evidence 확인 필요 - relations:
<related Reference/Question/Decision slug and reason>
CASE — Projection 이후에도 1,509행을 읽은 Row Over-fetch
- slug:
projection-row-over-fetch - readiness:
BLOCKED - source:
final/document.md#dto-프로젝션
- code:
<actual source path/symbol from analyzed project>
- evidence:
<actual raw/query-plan/test evidence path>
- classification:
상세 분석에서 이 제목에 해당하는 구체적 발생 조건, 관측 결과, 진단 순서가 확인될 때 Case가 된다. - missing-verification:
example only — 실제 project source/evidence 확인 필요 - relations:
<related Reference/Question/Decision slug and reason>
CASE — Visibility OR이 Keyset Index를 깨뜨린 문제
- slug:
visibility-or-breaks-keyset-index - readiness:
BLOCKED - source:
final/document.md#가시성-조건
- code:
<actual source path/symbol from analyzed project>
- evidence:
<actual raw/query-plan/test evidence path>
- classification:
상세 분석에서 이 제목에 해당하는 구체적 발생 조건, 관측 결과, 진단 순서가 확인될 때 Case가 된다. - missing-verification:
example only — 실제 project source/evidence 확인 필요 - relations:
<related Reference/Question/Decision slug and reason>
REFERENCE — JPA N+1 정량 진단 기준
- slug:
jpa-n-plus-one-quantitative-diagnosis - readiness:
BLOCKED - source:
final/document.md#컬렉션-n1-정량화
- classification:
관련 Case를 다시 서술하지 않고 다른 조회 문제에도 적용할 수 있는 판단 기준이 상세 분석에서 확인될 때 Reference가 된다. - scope:
<actual applicability derived from analysis> - exceptions:
<actual exceptions or none> - relations:
<originating Case/Decision and reason>
REFERENCE — Fetch Type과 Fetch Strategy 구분
- slug:
fetch-type-vs-fetch-strategy - readiness:
BLOCKED - source:
final/document.md#최초-구현과-첫-관찰
- classification:
관련 Case를 다시 서술하지 않고 다른 조회 문제에도 적용할 수 있는 판단 기준이 상세 분석에서 확인될 때 Reference가 된다. - scope:
<actual applicability derived from analysis> - exceptions:
<actual exceptions or none> - relations:
<originating Case/Decision and reason>
REFERENCE — Fetch Join · Batch · Projection 선택 기준
- slug:
fetch-join-batch-projection-selection - readiness:
BLOCKED - source:
final/document.md#배치-페치
- classification:
관련 Case를 다시 서술하지 않고 다른 조회 문제에도 적용할 수 있는 판단 기준이 상세 분석에서 확인될 때 Reference가 된다. - scope:
<actual applicability derived from analysis> - exceptions:
<actual exceptions or none> - relations:
<originating Case/Decision and reason>
REFERENCE — Top-N-per-group 선택 기준
- slug:
top-n-per-group-selection - readiness:
BLOCKED - source:
final/document.md#top-n-per-group
- classification:
관련 Case를 다시 서술하지 않고 다른 조회 문제에도 적용할 수 있는 판단 기준이 상세 분석에서 확인될 때 Reference가 된다. - scope:
<actual applicability derived from analysis> - exceptions:
<actual exceptions or none> - relations:
<originating Case/Decision and reason>
REFERENCE — Keyset Pagination 설계 기준
- slug:
keyset-pagination-design - readiness:
BLOCKED - source:
final/document.md#keyset-vs-offset
- classification:
관련 Case를 다시 서술하지 않고 다른 조회 문제에도 적용할 수 있는 판단 기준이 상세 분석에서 확인될 때 Reference가 된다. - scope:
<actual applicability derived from analysis> - exceptions:
<actual exceptions or none> - relations:
<originating Case/Decision and reason>
REFERENCE — Feed Visibility Query Pattern
- slug:
feed-visibility-query-pattern - readiness:
BLOCKED - source:
final/document.md#가시성-조건
- classification:
관련 Case를 다시 서술하지 않고 다른 조회 문제에도 적용할 수 있는 판단 기준이 상세 분석에서 확인될 때 Reference가 된다. - scope:
<actual applicability derived from analysis> - exceptions:
<actual exceptions or none> - relations:
<originating Case/Decision and reason>
REFERENCE — PostgreSQL Query Plan 측정 기준
- slug:
postgresql-query-plan-measurement - readiness:
BLOCKED - source:
final/document.md#측정-환경과-데이터셋
- classification:
관련 Case를 다시 서술하지 않고 다른 조회 문제에도 적용할 수 있는 판단 기준이 상세 분석에서 확인될 때 Reference가 된다. - scope:
<actual applicability derived from analysis> - exceptions:
<actual exceptions or none> - relations:
<originating Case/Decision and reason>
OPEN QUESTION — Highlight 없는 FeedItem을 허용할 것인가
- slug:
allow-feed-item-without-highlight - readiness:
BLOCKED - source:
final/document.md#확인된-문제와-이후-검증할-가설
- known:
<grounded fact from detailed analysis>
- unknown:
<specific unresolved uncertainty>
- next-verification:
<concrete experiment/measurement/decision input> - decision-criterion:
<condition that would close the question> - relations:
<related Case/Reference/Decision and reason>
OPEN QUESTION — Round Trip과 Row Volume을 독립 측정할 것인가
- slug:
measure-round-trip-and-row-volume-separately - readiness:
BLOCKED - source:
final/document.md#측정-환경과-데이터셋
- known:
<grounded fact from detailed analysis>
- unknown:
<specific unresolved uncertainty>
- next-verification:
<concrete experiment/measurement/decision input> - decision-criterion:
<condition that would close the question> - relations:
<related Case/Reference/Decision and reason>
OPEN QUESTION — ANALYZE 이후 Cardinality Estimate는 어떻게 달라지는가
- slug:
cardinality-estimate-after-analyze - readiness:
BLOCKED - source:
final/document.md#postgresql-query-plan-측정
- known:
<grounded fact from detailed analysis>
- unknown:
<specific unresolved uncertainty>
- next-verification:
<concrete experiment/measurement/decision input> - decision-criterion:
<condition that would close the question> - relations:
<related Case/Reference/Decision and reason>
OPEN QUESTION — feed_visible을 Production CQRS로 승격할 것인가
- slug:
promote-feed-visible-to-production-cqrs - readiness:
BLOCKED - source:
final/document.md#cqrs-lite-읽기-모델
- known:
<grounded fact from detailed analysis>
- unknown:
<specific unresolved uncertainty>
- next-verification:
<concrete experiment/measurement/decision input> - decision-criterion:
<condition that would close the question> - relations:
<related Case/Reference/Decision and reason>
OPEN QUESTION — 실제 동시 트래픽에서도 이 구조가 안정적인가
- slug:
stability-under-concurrent-traffic - readiness:
BLOCKED - source:
final/document.md#다음-단계
- known:
<grounded fact from detailed analysis>
- unknown:
<specific unresolved uncertainty>
- next-verification:
<concrete experiment/measurement/decision input> - decision-criterion:
<condition that would close the question> - relations:
<related Case/Reference/Decision and reason>
DECISION — Query Plan은 실제 PostgreSQL에서 측정한다
- slug:
measure-query-plan-on-postgresql - readiness:
NEEDS_DECISION - decision-status:
NOT_DECIDED - source:
final/document.md#측정-환경과-데이터셋
- decision-evidence:
<ADR/commit/PR/config + recorded rationale/user-supplied decision>
- grounds:
<Case or Reference that supports the choice>
- classification:
상세 분석에 실제 프로젝트 선택의 근거가 확인될 때만 READY로 바뀐다. 기술적으로 합리적인 권고만으로 Decision을 만들지 않는다. - relations:
<related nodes and reason>
DECISION — Query Strategy는 FeedQueryPort 뒤에서 소유한다
- slug:
query-strategy-behind-feed-query-port - readiness:
NEEDS_DECISION - decision-status:
NOT_DECIDED - source:
final/document.md#조회-전략은-포트-뒤-어댑터의-책임
- decision-evidence:
<ADR/commit/PR/config + recorded rationale/user-supplied decision>
- grounds:
<Case or Reference that supports the choice>
- classification:
상세 분석에 실제 프로젝트 선택의 근거가 확인될 때만 READY로 바뀐다. 기술적으로 합리적인 권고만으로 Decision을 만들지 않는다. - relations:
<related nodes and reason>
DECISION — Collection Fetch Join과 Pagination을 같이 사용하지 않는다
- slug:
no-collection-fetch-join-with-pagination - readiness:
NEEDS_DECISION - decision-status:
NOT_DECIDED - source:
final/document.md#컬렉션-fetch-join-페이징
- decision-evidence:
<ADR/commit/PR/config + recorded rationale/user-supplied decision>
- grounds:
<Case or Reference that supports the choice>
- classification:
상세 분석에 실제 프로젝트 선택의 근거가 확인될 때만 READY로 바뀐다. 기술적으로 합리적인 권고만으로 Decision을 만들지 않는다. - relations:
<related nodes and reason>
DECISION — Entity Graph 조회에는 Batch Fetch를 사용한다
- slug:
batch-fetch-for-entity-graph - readiness:
NEEDS_DECISION - decision-status:
NOT_DECIDED - source:
final/document.md#배치-페치
- decision-evidence:
<ADR/commit/PR/config + recorded rationale/user-supplied decision>
- grounds:
<Case or Reference that supports the choice>
- classification:
상세 분석에 실제 프로젝트 선택의 근거가 확인될 때만 READY로 바뀐다. 기술적으로 합리적인 권고만으로 Decision을 만들지 않는다. - relations:
<related nodes and reason>
DECISION — 화면 조회는 Read Projection을 사용한다
- slug:
read-projection-for-screen-query - readiness:
NEEDS_DECISION - decision-status:
NOT_DECIDED - source:
final/document.md#dto-프로젝션
- decision-evidence:
<ADR/commit/PR/config + recorded rationale/user-supplied decision>
- grounds:
<Case or Reference that supports the choice>
- classification:
상세 분석에 실제 프로젝트 선택의 근거가 확인될 때만 READY로 바뀐다. 기술적으로 합리적인 권고만으로 Decision을 만들지 않는다. - relations:
<related nodes and reason>
DECISION — Feed Pagination은 Keyset을 사용한다
- slug:
keyset-for-feed-pagination - readiness:
NEEDS_DECISION - decision-status:
NOT_DECIDED - source:
final/document.md#keyset-vs-offset
- decision-evidence:
<ADR/commit/PR/config + recorded rationale/user-supplied decision>
- grounds:
<Case or Reference that supports the choice>
- classification:
상세 분석에 실제 프로젝트 선택의 근거가 확인될 때만 READY로 바뀐다. 기술적으로 합리적인 권고만으로 Decision을 만들지 않는다. - relations:
<related nodes and reason>
DECISION — 현재 Read Model은 CQRS-lite로 유지한다
- slug:
keep-cqrs-lite-read-model - readiness:
NEEDS_DECISION - decision-status:
NOT_DECIDED - source:
final/document.md#cqrs-lite-읽기-모델
- decision-evidence:
<ADR/commit/PR/config + recorded rationale/user-supplied decision>
- grounds:
<Case or Reference that supports the choice>
- classification:
상세 분석에 실제 프로젝트 선택의 근거가 확인될 때만 READY로 바뀐다. 기술적으로 합리적인 권고만으로 Decision을 만들지 않는다. - relations:
<related nodes and reason>