feat: 가상화 문서들 추가

This commit is contained in:
DongHyeonka
2026-09-10 08:54:05 +09:00
parent e9f6a93327
commit 43e1aadef0
695 changed files with 153404 additions and 12754 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,191 @@
{
"version": "1.1",
"title": "컬렉션 하나만 fetch join하면 전송 행이 자식 수만큼 늘어난다",
"question": "컬렉션 하나만 fetch join했을 때 DB가 전달하는 행은 왜 늘어나는가?",
"type": "data-flow",
"direction": "LR",
"audience": [
"JPA 조회 전략을 고르는 백엔드 개발자"
],
"summary": "조인이 부모를 자식 수만큼 반복해 전송하고, 결과 리스트는 루트 중복 제거로 줄어들어 전송량이 가려진다.",
"alt": "feed_items와 highlights가 fetch join으로 합쳐져 전송 조인 행이 되고, 그 행이 결과 리스트로 갈 때만 루트 엔티티가 중복 제거되는 흐름.",
"long_description": "왼쪽에서 feed_items와 highlights 두 테이블이 highlights fetch join으로 들어간다. 조인은 부모 행을 자식 수만큼 반복한 전송 조인 행을 만든다. 그 행이 결과 리스트로 넘어갈 때 Hibernate가 루트 엔티티를 중복 제거하므로 리스트 크기만 줄고 전송 단계의 카테시안은 남는다.",
"composition": {
"profile": "component-flow",
"diagram_only": true,
"reference_ids": [
"payment-event-flow"
],
"rationale": "두 테이블에서 조인을 거쳐 전송 행과 결과 리스트로 이어지는 방향이 있는 데이터 경로이고, 그 경로의 어느 구간에서 행이 늘고 어느 구간에서 줄어드는지가 물음이다.",
"focus_node": "transferred-rows"
},
"groups": [],
"nodes": [
{
"id": "feed-items",
"label": "feed_items",
"kind": "store",
"role": "store",
"shape": "cylinder",
"description": "부모 테이블",
"evidence": [
{
"start_line": 713,
"end_line": 714
}
],
"assumption": false
},
{
"id": "highlights",
"label": "highlights",
"kind": "store",
"role": "store",
"shape": "cylinder",
"description": "자식 테이블",
"evidence": [
{
"start_line": 713,
"end_line": 714
}
],
"assumption": false
},
{
"id": "fetch-join",
"label": "highlights fetch join",
"kind": "service",
"role": "service",
"shape": "box",
"description": "컬렉션 하나만 fetch join한 루트 쿼리",
"evidence": [
{
"start_line": 713,
"end_line": 715
}
],
"assumption": false
},
{
"id": "transferred-rows",
"label": "전송 조인 행",
"kind": "queue",
"role": "queue",
"shape": "box",
"details": [
"Σ highlights"
],
"emphasis": "primary",
"description": "DB가 애플리케이션에 전달한 조인 카디널리티",
"evidence": [
{
"start_line": 714,
"end_line": 715
},
{
"start_line": 732,
"end_line": 736
}
],
"assumption": false
},
{
"id": "result-list",
"label": "결과 리스트",
"kind": "sink",
"role": "sink",
"shape": "box",
"details": [
"루트 엔티티 중복 제거"
],
"description": "Hibernate 6+ 가 루트를 dedup한 뒤의 목록",
"evidence": [
{
"start_line": 717,
"end_line": 719
}
],
"assumption": false
}
],
"edges": [
{
"id": "parent-into-join",
"from": "feed-items",
"to": "fetch-join",
"label": "부모 행",
"kind": "read",
"style": "solid",
"evidence": [
{
"start_line": 713,
"end_line": 714
}
],
"assumption": false
},
{
"id": "child-into-join",
"from": "highlights",
"to": "fetch-join",
"label": "자식 행",
"kind": "read",
"style": "solid",
"evidence": [
{
"start_line": 713,
"end_line": 714
}
],
"assumption": false
},
{
"id": "join-multiplies",
"from": "fetch-join",
"to": "transferred-rows",
"label": "카테시안 곱",
"kind": "transfer",
"style": "solid",
"evidence": [
{
"start_line": 713,
"end_line": 715
},
{
"start_line": 732,
"end_line": 734
}
],
"assumption": false
},
{
"id": "dedup-to-list",
"from": "transferred-rows",
"to": "result-list",
"label": "루트 dedup",
"kind": "transform",
"style": "dashed",
"evidence": [
{
"start_line": 717,
"end_line": 719
}
],
"assumption": false
}
],
"legend": [],
"metadata": {
"rationale": "쿼리 수가 아니라 전송 행수가 늘어난 자리를 보여야 하므로, 테이블에서 결과 리스트까지의 데이터 경로를 한 단계 추상화로 그린다."
},
"source_context": {
"document": "docs/n+1liner/final/document.md",
"document_sha256": "385ca44db5bf763cb1ff28a67d531d68876402b35d21dc54f2bc702e8bda0053",
"anchor": {
"kind": "heading",
"value": "9.3 실패 ② 컬렉션 하나만 fetch join → 카테시안으로 전송 행수 증가",
"line": 711
}
},
"id": "cartesian-row-multiplication"
}