Files
document-haness/.agents/skills/deriving-tech-log-root-tree/references/example-root-tree.md
T
DongHyeonkaandClaude Opus 5 b2963105a8 docs(keycloak-session-store): import the session-storage lab as a new project
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>
2026-09-04 22:51:59 +09:00

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>