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>
2.9 KiB
2.9 KiB
id, kind, slug, title, topic, topicName, project, status, studio, decisionStatus
| id | kind | slug | title | topic | topicName | project | status | studio | decisionStatus |
|---|---|---|---|---|---|---|---|---|---|
| 30a37f34-b406-4061-b924-e22e0be0c3bf | PROJECT_DECISION | read-projection-for-screen-query | 화면 조회는 Read Projection을 사용한다 | jpa-feed-query-performance | JPA 피드 조회 성능 | Liner N + 1문제 | 게시 전 | https://hyeonworks.com/studio/documents/30a37f34-b406-4061-b924-e22e0be0c3bf/edit | PROPOSED |
화면 조회는 Read Projection을 사용한다
화면에 내보내는 조회는 엔티티를 하이드레이트하지 않고 필요한 스칼라 값만 캐리어로 받는다. 엔티티 그래프 조회는 쓰기 경로에 남기고 읽기 경로는 프로젝션으로 분리한다.
근거
- Projection 이후에도 1,509행을 읽은 Row Over-fetch 프로젝션의 효과와 남은 비용을 확인한 기록이다.
- Fetch Join · Batch · Projection 선택 기준 배치와 프로젝션이 서로 다른 비용을 줄인다는 기준이다.
- Query Strategy는 FeedQueryPort 뒤에서 소유한다 이 구현을 감춘 경계다.
결정문
화면 조회 경로에서는 필요한 컬럼만 선택해 캐리어 record로 받는다. 영속 엔티티를 만들지 않는다.
부모와 자식을 각각 스칼라로 조회하고 애플리케이션에서 조립한다. 이 구현은 조회 포트 뒤에 둔다.
판단 이유
배치를 적용한 뒤에도 엔티티는 통째로 하이드레이트됐다. 페이지 20건을 조회하는데 부모와 연관을 합해 천 개가 넘는 영속 객체가 올라왔다. 화면에는 일부 컬럼만 필요했다.
캐리어 생성자 표현식은 영속 엔티티 대신 스칼라 값으로 record를 만든다. 1차 캐시, 더티체킹, 지연 프록시가 생기지 않는다. 컬럼을 읽기 위한 조인이 있어도 그 대상 엔티티를 만들지 않는다.
측정에서 하이드레이트한 엔티티가 0이 됐고 발행 쿼리도 데이터 규모와 관계없이 두 개로 고정됐다. 부모 스칼라 쿼리와 자식 IN 쿼리다.
이 효과는 배치 설정 여부와 무관하게 성립한다. 배치는 왕복을 줄이고 프로젝션은 적재를 없앤다. 두 전략은 서로를 대신하지 않는다.
영향
- 반환 형태가 화면 요구에 묶인다. 화면이 바뀌면 캐리어와 쿼리도 바뀐다.
- 여러 컬렉션을 담는 응답은 생성자 표현식 한 번으로 만들 수 없다. 부모와 자식을 따로 조회해 조립해야 한다.
- 프로젝션의 이득은 실행계획에서 확인되지 않는다. 필요한 컬럼만 골라도 계획의 행폭 추정치는 오히려 넓어질 수 있다. 엔티티 로드 수로 확인해야 한다.
- 자식 조회의 행수는 프로젝션이 줄이지 않는다. 부모당 상한이 필요하면 별도 SQL 형태로 풀어야 한다.
- 읽기 경로와 쓰기 경로의 모델이 갈린다. 같은 저장소를 쓰더라도 조회 전용 계약이 하나 늘어난다.