283 lines
18 KiB
Markdown
283 lines
18 KiB
Markdown
---
|
|
title: N+1 Presentation Preparation Contract
|
|
source_type: project-note
|
|
status: raw
|
|
confidence: medium
|
|
tags: [project-note, nplus1-presentation-prep, learning, hibernate, hands-on-lab]
|
|
related_projects: [nplus1-presentation-prep, ca-tmpl]
|
|
created: 2026-07-20
|
|
last_reviewed: 2026-07-20
|
|
diagrams: [nplus1-presentation-prep/architecture-lab-loop-2026-07-20.drawio, sequence-api-replay-lab-mermaid]
|
|
architecture_review: 2026-07-20
|
|
status_label: active
|
|
project_revision: 1
|
|
semantic_surface_exclusions:
|
|
- artifact-registry|legacy hub has no project-local Artifact Registry; harness/source/typed-contracts.json is authoritative until migration
|
|
- contract-gate-registry|legacy hub has no project-local Contract/Gate Registry; harness/source/typed-contracts.json is authoritative until migration
|
|
- flow-stage-registry|legacy hub has no project-local Flow/Stage Registry; harness/source/typed-contracts.json is authoritative until migration
|
|
---
|
|
|
|
# N+1 Presentation Preparation Contract
|
|
|
|
> Layer: `raw/project-notes/` (primary, hub) → `/ingest` 후 검증된 사실만 `wiki/projects/`로 추출한다.
|
|
> 이 문서는 N+1 재현·측정·발표 준비 작업의 최상위 project hub이자 project decision/work-item SSOT다.
|
|
> `status_label`: `active`
|
|
|
|
## 1. 프로젝트 개요
|
|
|
|
- **한 줄 요약**: ca-tmpl의 feed 조회를 단계별로 재현하고, HTTP·PostgreSQL·Hibernate 관찰값을 근거 등급과 함께 설명할 수 있는 N+1 학습 랩을 만든다.
|
|
- **기간**: 2026-07-08 ~ 진행 중
|
|
- **현재 상태**: `active`
|
|
- **나의 역할 / Role**: 학습 랩 설계자·검증자·발표 준비자
|
|
- **저장소 / Repo**: ca-tmpl 로컬 저장소의 `lab/nplus1-highlight-feed`, `lab/nplus1-api-replay` Git branch를 사용한다. 원격 URL은 이 문서에서 확인하지 않았다.
|
|
|
|
## 2. 문제 정의
|
|
|
|
### 2.1 현재 상태의 문제
|
|
|
|
- 마지막 최적화 상태만 보면 lazy collection N+1부터 one-query read까지의 원인·선택·관찰값 변화를 순서대로 재현하기 어렵다.
|
|
- 테스트 결과만 읽으면 학습자가 HTTP 응답과 실제 PostgreSQL row를 함께 관찰하는 실행 경로가 드러나지 않는다.
|
|
- 로컬 측정 결과를 production 성능·배포 증거로 확대 해석할 위험이 있다.
|
|
|
|
### 2.2 왜 지금 해결해야 하는가
|
|
|
|
- **트리거**: N+1 주제를 구현 결과 나열이 아니라 재현 가능한 발표·학습 흐름으로 준비해야 한다.
|
|
- **비용**: 단계별 checkpoint와 근거 등급이 없으면 어떤 해법이 어떤 문제를 해결했는지 다시 검증하기 어렵다.
|
|
- **기회**: 동일한 관찰 루프를 반복하면 쿼리 수 최적화와 read-model 분리를 서로 다른 선택으로 비교할 수 있다.
|
|
|
|
### 2.3 성공 기준
|
|
|
|
- L1, L2, L3, L4, L5, L6, L14, L15, L16, Crown, L12의 정확히 11개 replay checkpoint가 guide와 대응한다.
|
|
- 각 checkpoint가 reset → HTTP → PostgreSQL 관찰 순서와 기대 관찰점을 가진다.
|
|
- local·Testcontainers·production 증거가 같은 등급으로 섞이지 않고 각 결과에 evidence grade가 기록된다.
|
|
- 두 직접 자식 branch가 아래 Work Item Registry의 pinned decision refs와 dependency를 그대로 상속한다.
|
|
|
|
<!-- section-id: architecture-components -->
|
|
## 3. 시스템 아키텍처
|
|
|
|
### 3.1 아키텍처 다이어그램 (draw.io XML)
|
|
|
|
**질문**: 학습자가 checkout한 N+1 checkpoint는 어떤 경로를 거쳐 검토 가능한 관찰 기록이 되는가?
|
|
|
|
![[raw/diagrams/nplus1-presentation-prep/architecture-lab-loop-2026-07-20.drawio]]
|
|
|
|
다이어그램은 Learner → Lab Checkpoint → Feed Module → PostgreSQL → Evidence Record → Presentation 경로를 나타낸다. 이는 정적 구조와 증거 승격 경계를 설명하며, 시간 순서의 세부 호출은 §4 Mermaid가 소유한다.
|
|
|
|
### 3.2 컴포넌트 책임 분담
|
|
|
|
| 컴포넌트 | 역할 | 기술 스택 | 의존하는 외부 |
|
|
|---|---|---|---|
|
|
| Learner | checkpoint를 checkout하고 관찰 절차를 실행한다 | Git, HTTP client, psql | 로컬 실행 환경 |
|
|
| Lab Checkpoint | 학습용 reset·feed 경로를 profile 안에서 노출한다 | Spring profile, HTTP API | Feed Module |
|
|
| Feed Module | checkpoint별 조회 전략을 실행한다 | Spring Data JPA, Hibernate | PostgreSQL |
|
|
| PostgreSQL | fixture row와 SQL 실행 결과를 제공한다 | PostgreSQL, Docker Compose/Testcontainers | 없음 |
|
|
| Evidence Record | 쿼리·entity load·row 관찰값과 등급을 기록한다 | Markdown, test report | 각 checkpoint 결과 |
|
|
|
|
### 3.3 외부 의존성
|
|
|
|
| 외부 시스템 | 용도 | 통신 방식 | 장애 시 영향 |
|
|
|---|---|---|---|
|
|
| Docker runtime | 로컬 PostgreSQL과 Compose/Testcontainers 실행 | local container API | DB 기반 replay와 integration evidence를 수집할 수 없다 |
|
|
| PostgreSQL | fixture·native query·row 확인 | JDBC, psql | SQL 관찰 단계가 실패하며 in-memory 결과로 대체하지 않는다 |
|
|
|
|
### 3.4 배포 다이어그램
|
|
|
|
운영 배포 토폴로지는 이 프로젝트의 검증 범위가 아니다. `lab` profile이 운영 환경에서 비활성이라는 deployment-level 증거는 아직 `needs-confirmation`이다.
|
|
|
|
<!-- section-id: runtime-flow -->
|
|
## 4. 핵심 시퀀스
|
|
|
|
<!-- section-id: sequence -->
|
|
### 4.1 API replay lab flow
|
|
|
|
**시나리오**: 학습자가 checkpoint를 checkout한 뒤 lab fixture를 reset하고 feed·DB·Hibernate 관찰값을 기록한다.
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
autonumber
|
|
actor Learner
|
|
participant API as Lab API
|
|
participant Feed as Feed Module
|
|
participant DB as PostgreSQL
|
|
participant Stats as Hibernate Statistics
|
|
|
|
Learner->>API: POST /api/lab/feed:reset {count}
|
|
alt lab profile active and input valid
|
|
API->>DB: replace marker-owned fixture
|
|
DB-->>API: row counts
|
|
API-->>Learner: 200 reset result
|
|
Learner->>API: GET /api/lab/feed
|
|
API->>Feed: execute checkpoint strategy
|
|
Feed->>DB: SELECT feed rows
|
|
DB-->>Feed: result rows
|
|
Feed->>Stats: read statement and load counts
|
|
Stats-->>Feed: observation values
|
|
Feed-->>API: feed and observations
|
|
API-->>Learner: 200 replay result
|
|
else lab profile inactive
|
|
API-->>Learner: 404 route not registered
|
|
else input outside guard
|
|
API-->>Learner: 400 VALIDATION_FAILED
|
|
end
|
|
```
|
|
|
|
성공 경로의 수치는 checkpoint마다 다르므로 프로젝트 문서가 하나의 고정 수치를 일반화하지 않는다. 관찰값은 각 branch의 Evidence 섹션에서 환경과 함께 판정한다.
|
|
|
|
## 5. 데이터 모델
|
|
|
|
별도 프로젝트 데이터 모델을 소유하지 않는다. ca-tmpl feed model과 `created_by = nplus1-lab` marker fixture를 사용하며, 이 문서는 단계·관찰·근거 등급 계약만 소유한다.
|
|
|
|
## 6. 기술 결정
|
|
|
|
| 결정 영역 | 선택 | 검토한 대안 | 채택 이유 | 트레이드오프 | 근거 자료 |
|
|
|---|---|---|---|---|---|
|
|
| 학습 루프 | Measure→Break→Diagnose→Fix→Re-measure→Generalize | 마지막 결과만 설명 | 각 단계의 원인·수정·재측정을 연결한다 | checkpoint와 관찰 기록 유지 비용이 생긴다 | [[raw/branch-notes/experiment-nplus1-highlight-feed]] |
|
|
| 실행 substrate | ca-tmpl production substrate + profile/sibling 격리 | 독립 예제 앱 | 실제 모듈 경계를 사용하면서 학습 경로를 정상 runtime과 분리한다 | profile 오활성 여부는 별도 배포 검증이 필요하다 | [[raw/branch-notes/experiment-nplus1-feed-api-replay]] |
|
|
| 증거 등급 | local·Testcontainers 결과는 `locally-verified` | 로컬 결과를 운영 결과로 표현 | 검증 환경이 증명하는 범위를 보존한다 | production 결론에는 추가 검증이 필요하다 | [[raw/official-docs/test-taxonomy-testcontainers-official]] |
|
|
| CQRS 범위 | same-store CQRS-lite까지 | 별도 physical read store를 즉시 도입 | 쿼리 최적화와 application read-model 분리를 현재 실습 범위에서 비교한다 | full CQRS의 동기화·운영 문제는 다루지 않는다 | [[raw/official-docs/cqrs-pattern-azure-architecture-center]] |
|
|
|
|
<!-- section-id: project-decisions -->
|
|
## 6.1 안정 결정 레지스트리
|
|
|
|
> 프로젝트가 소유하는 project-wide decision SSOT다. 두 branch packet의 `Project Summary`와 byte-equivalent한 요약을 유지한다.
|
|
|
|
| Decision ID | Revision | Domain | Decision Summary | Status | Owner | Evidence |
|
|
|---|---:|---|---|---|---|---|
|
|
| `DEC-NPLUS1-PRESENTATION-PREP-LEARNING-001` | 1 | `learning` | Measure→Break→Diagnose→Fix→Re-measure→Generalize를 랩 완료 루프로 사용한다. | `active` | [[raw/project-notes/nplus1-presentation-prep]] | [[raw/branch-notes/experiment-nplus1-highlight-feed]] |
|
|
| `DEC-NPLUS1-PRESENTATION-PREP-SUBSTRATE-001` | 1 | `substrate` | ca-tmpl production substrate를 사용하고 학습 API·측정 경로는 profile과 sibling 경로로 격리한다. | `active` | [[raw/project-notes/nplus1-presentation-prep]] | [[raw/branch-notes/experiment-nplus1-feed-api-replay]] |
|
|
| `DEC-NPLUS1-PRESENTATION-PREP-EVIDENCE-001` | 1 | `evidence` | local·Testcontainers 결과는 locally-verified로만 기록하고 prod evidence로 승격하지 않는다. | `active` | [[raw/project-notes/nplus1-presentation-prep]] | [[raw/official-docs/test-taxonomy-testcontainers-official]] |
|
|
| `DEC-NPLUS1-PRESENTATION-PREP-SCOPE-001` | 1 | `scope` | same-store CQRS-lite까지를 현재 범위로 두고 full CQRS는 ca-tmpl contract escalation 이후에만 허용한다. | `active` | [[raw/project-notes/nplus1-presentation-prep]] | [[raw/official-docs/cqrs-pattern-azure-architecture-center]] |
|
|
|
|
<!-- section-id: implementation-boundaries -->
|
|
## 7. 비기능 요구사항
|
|
|
|
- **성능**: production RPS·P99 목표는 설정하지 않는다. checkpoint별 쿼리·entity load 관찰값만 환경과 함께 기록한다.
|
|
- **가용성**: 운영 SLO는 이 프로젝트 범위가 아니다.
|
|
- **확장성**: 로컬 단일 학습 실행만 검증 범위로 둔다.
|
|
- **보안**: 학습 reset/API는 `lab` profile에 한정하고, 정상 profile에서는 route/use case가 등록되지 않아야 한다.
|
|
- **운영 / Observability**: Hibernate Statistics, HTTP response, PostgreSQL row 확인을 같은 checkpoint evidence에 연결한다.
|
|
- **재해 복구 / DR**: 해당 없음. marker-owned local fixture는 reset으로 재생성한다.
|
|
- **컴플라이언스**: 해당 없음. production 데이터는 이 랩의 입력으로 사용하지 않는다.
|
|
|
|
<!-- section-id: project-work-items -->
|
|
## 8.0 실행계획
|
|
|
|
> 두 직접 자식 branch의 stable handoff SSOT다. Applies Decisions는 revision 1 project decisions 네 개를 모두 pin한다.
|
|
|
|
| Work Item ID | branch slug | 완료 조건 (측정가능) | Applies Decisions | Dependencies | Status |
|
|
|---|---|---|---|---|---|
|
|
| `WI-NPLUS1-PRESENTATION-PREP-001` | `experiment-nplus1-highlight-feed` | L2 ToOne EAGER 격리 측정값을 확정하고, L1~L6·L14~L16·Crown·L12의 증거 등급과 사용자 commit-range review를 본문 Closure에 반영한다. | `DEC-NPLUS1-PRESENTATION-PREP-LEARNING-001@1`, `DEC-NPLUS1-PRESENTATION-PREP-SUBSTRATE-001@1`, `DEC-NPLUS1-PRESENTATION-PREP-EVIDENCE-001@1`, `DEC-NPLUS1-PRESENTATION-PREP-SCOPE-001@1` | - | `in-progress` |
|
|
| `WI-NPLUS1-PRESENTATION-PREP-002` | `experiment-nplus1-feed-api-replay` | 11개 replay tag와 guide mapping을 고정하고, clean clone/worktree에서 Compose·HTTP·PostgreSQL smoke 및 full-check 상태를 재검증하며 lab profile의 deployment 비활성 증거를 기록한다. | `DEC-NPLUS1-PRESENTATION-PREP-LEARNING-001@1`, `DEC-NPLUS1-PRESENTATION-PREP-SUBSTRATE-001@1`, `DEC-NPLUS1-PRESENTATION-PREP-EVIDENCE-001@1`, `DEC-NPLUS1-PRESENTATION-PREP-SCOPE-001@1` | `WI-NPLUS1-PRESENTATION-PREP-001` | `in-progress` |
|
|
|
|
## 8. 묶음 (이 프로젝트에 묶이는 모든 raw 자료)
|
|
|
|
<!-- GENERATED: blog-topics:start -->
|
|
- [[raw/blog-topics/nplus1-lab-checkoutable-api-replay-2026-07-15]]
|
|
<!-- GENERATED: blog-topics:end -->
|
|
|
|
### 8.1 브랜치 (project의 직접 자식 branch)
|
|
|
|
<!-- GENERATED: branches:start -->
|
|
- [[raw/branch-notes/experiment-nplus1-feed-api-replay]]
|
|
- [[raw/branch-notes/experiment-nplus1-highlight-feed]]
|
|
<!-- GENERATED: branches:end -->
|
|
|
|
> 아래 표는 사람이 빠르게 식별하기 위한 lookup view다. 완료 조건·decision pin·dependency의 SSOT는 `## 8.0 Work Item Registry / 실행계획`이다.
|
|
|
|
| Branch | Work Item | 현재 단계 |
|
|
|---|---|---|
|
|
| `experiment-nplus1-highlight-feed` | `WI-NPLUS1-PRESENTATION-PREP-001` | `in-progress` |
|
|
| `experiment-nplus1-feed-api-replay` | `WI-NPLUS1-PRESENTATION-PREP-002` | `in-progress` |
|
|
|
|
### 8.2 근거 자료 (프로젝트 전체 차원 foundational 조사)
|
|
|
|
프로젝트에 직접 매달린 source는 없다. 각 source는 자신이 정당화하는 branch의 `## Sources / 근거`에서 추적한다.
|
|
|
|
### 8.3 오류 기록 (branch 외 발생한 환경·운영 이슈)
|
|
|
|
프로젝트에 직접 매달린 error-note는 없다. replay 과정의 오류는 해당 branch cluster가 소유한다.
|
|
|
|
### 8.4 면접 준비
|
|
|
|
프로젝트에 직접 매달린 interview-prep 문서는 없다.
|
|
|
|
### 8.5 블로그·채용공고 연계 글감
|
|
|
|
직접 자식은 없다. checkout replay 글감은 [[raw/branch-notes/experiment-nplus1-feed-api-replay]]의 child로 관리한다.
|
|
|
|
### 8.6 파생 wiki 문서
|
|
|
|
아직 생성하지 않았다. `reviewed` 이상 canonical로 승급되기 전에는 interview·portfolio·blog를 파생하지 않는다.
|
|
|
|
## 9. 검증 등급
|
|
|
|
| 영역 | 등급 | 근거 |
|
|
|---|---|---|
|
|
| 아키텍처 다이어그램 | `documented-only` | [[raw/diagrams/nplus1-presentation-prep/architecture-lab-loop-2026-07-20.drawio]] |
|
|
| 시퀀스 다이어그램 | `documented-only` | §4는 branch의 lab API·DB 관찰 경계를 요약하며 별도 실행 증거를 주장하지 않는다 |
|
|
| 기술 결정 | `documented-only` | §6.1 stable registry와 두 branch packet이 동일한 revision 1 refs를 사용한다 |
|
|
| replay 구현·로컬 측정 | `locally-verified` | [[raw/branch-notes/experiment-nplus1-feed-api-replay]]의 Docker HTTP + PostgreSQL smoke 기록 |
|
|
| 전체 checkpoint closure | `needs-confirmation` | WI-001의 L2 실측과 WI-002의 clean clone/deployment 확인이 남아 있다 |
|
|
|
|
### 9.1 실제 구현 내용 (`actually-implemented`)
|
|
|
|
- 11개 replay commit/tag와 `lab` profile의 reset·feed 관찰 경로는 branch note에 코드 존재 근거와 함께 기록되어 있다.
|
|
|
|
### 9.2 로컬/dev 검증 (`locally-verified`)
|
|
|
|
- final L12와 historical L1 checkpoint의 Docker HTTP·PostgreSQL smoke 결과는 [[raw/branch-notes/experiment-nplus1-feed-api-replay]]에 환경·명령 경계와 함께 기록되어 있다.
|
|
|
|
### 9.3 운영 검증 (`prod-verified`)
|
|
|
|
- 없음. 이 프로젝트는 production 성능·권한·배포를 검증했다고 주장하지 않는다.
|
|
|
|
### 9.4 문서/계획만 존재 (`documented-only`
|
|
|
|
- 다른 clean machine/worktree의 전체 11-stage 재현과 deployment manifest의 `lab` profile 비활성 확인은 `needs-confirmation`이다.
|
|
|
|
## 10. 면접·외부 공개 답변 경계
|
|
|
|
### 10.1 자신 있게 답할 수 있는 범위
|
|
|
|
- 각 checkout 단계에서 무엇을 측정하고 다음 단계가 어떤 문제를 다루는지 branch evidence를 근거로 설명할 수 있다.
|
|
- Crown one-query 경로와 L12 same-store CQRS-lite two-query read-model이 같은 선택이 아님을 설명할 수 있다.
|
|
|
|
### 10.2 적당히 답할 수 있는 범위
|
|
|
|
- 로컬 Docker Compose/Testcontainers에서 관찰한 SQL·HTTP 결과는 환경과 evidence grade를 함께 제시할 때만 답한다.
|
|
|
|
### 10.3 답하면 안 되는 / 공식 자료를 다시 확인해야 하는 범위
|
|
|
|
- production latency·throughput·권한 경계·다중 인스턴스 동작은 검증하지 않았다.
|
|
- 다른 환경에서 11개 tag가 모두 같은 결과를 낸다고 단정하지 않는다.
|
|
|
|
### 10.4 과장 금지 지점
|
|
|
|
- local·Testcontainers 결과를 production evidence로 표현하지 않는다.
|
|
- `addScalar` runtime mapping을 SQL compile-time 검증으로 표현하지 않는다.
|
|
- same-store CQRS-lite를 별도 read store·동기화 파이프라인을 가진 full CQRS로 표현하지 않는다.
|
|
|
|
## 11. 아키텍처 검토 체크리스트
|
|
|
|
- [x] 한 줄 요약·상태·역할을 기록했다.
|
|
- [x] 11 checkpoint와 evidence grade의 측정 가능한 성공 기준을 기록했다.
|
|
- [x] 정적 구조는 draw.io, 시간축은 Mermaid sequence diagram으로 분리했다.
|
|
- [x] Mermaid에 happy path와 profile/input error path를 함께 넣었다.
|
|
- [x] project decision 4개와 Work Item 2개를 stable ID·pinned revision으로 고정했다.
|
|
- [x] 생성 children block이 두 직접 자식 branch와 일치한다.
|
|
- [ ] draw.io에 대한 독립 `wiki-diagram-reviewer` ≥95 판정은 이 문서 작성 범위에서 수행하지 않았다.
|
|
- [ ] WI-001·WI-002의 남은 완료 조건을 충족한 뒤 project status와 evidence grade를 재검토한다.
|
|
|
|
## 12. 다이어그램 파일 관리 가이드
|
|
|
|
- 정적 구조 SSOT: `raw/diagrams/nplus1-presentation-prep/architecture-lab-loop-2026-07-20.drawio`
|
|
- 시간축 SSOT: 이 문서 §4의 Mermaid `sequenceDiagram`
|
|
- 구조 또는 흐름이 바뀌면 새 날짜의 draw.io를 추가하고 `architecture_review`와 `last_reviewed`를 함께 갱신한다.
|
|
- 검증 환경·수치 변경은 다이어그램 안이 아니라 branch evidence와 이 문서 §9에 기록한다.
|
|
|
|
## 13. 관련 개념
|
|
|
|
- [[raw/official-docs/spring-data-jpa-projections-spring-official]] — projection/read shape의 공식 경계.
|
|
- [[raw/official-docs/cqrs-pattern-azure-architecture-center]] — same-store read/write model 분리와 별도 store CQRS의 범위 구분.
|
|
- [[raw/official-docs/test-taxonomy-testcontainers-official]] — 실제 dependency를 사용하는 integration evidence의 근거.
|