8.9 KiB
title, source_type, url, archive_url, status, confidence, tags, related_branches, related_projects, created, last_reviewed
| title | source_type | url | archive_url | status | confidence | tags | related_branches | related_projects | created | last_reviewed | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| official-doc / Spring Data JPA — Projections (Spring Official Reference) | official-doc | https://docs.spring.io/spring-data/jpa/reference/repositories/projections.html | raw | high |
|
|
|
2026-06-04 | 2026-06-04 |
Spring Data JPA — Projections (Spring Official Reference)
Layer:
raw/official-docs/— Spring Data JPA 공식 레퍼런스의 Projections 섹션 원문 발췌. interface-based projection, class-based projection (DTO), dynamic projection 의 공식 명세. ca-tmpl CQRS-lite read path 결정의 official-vendor-doc 근거.
Parent / 활용 branch (필수)
| Branch | 이 자료가 정당화하는 결정 |
|---|---|
| raw/branch-notes/feature-application-query-bypass-contract | D1 (aggregate 우회 + dedicated read port 에서 projection DTO 반환) 의 Spring 공식 mechanism 근거 — closed projection 이 query column subset 을 최적화함 |
출처 / Source
- 원본 URL: https://docs.spring.io/spring-data/jpa/reference/repositories/projections.html
- 아카이브 URL:
- 저자 / 조직: Spring Team (VMware/Broadcom) — 공식 reference documentation
- 발행일: ongoing (Spring Data JPA 4.x, 2026-06-04 기준 최신)
- 마지막 확인일: 2026-06-04
왜 저장했는지 / Why archived
ca-tmpl read path bypass 의 기술적 mechanism (projection interface, DTO constructor, query rewriting) 에 대한 공식 벤더 명세. alternative 2 (CQRS-lite with same store) 가 Spring Data JPA 위에서 구체적으로 어떻게 작동하는지의 1차 근거.
핵심 인용 / Key quotes (verbatim)
[§Interface-based projections — mechanism] "The query execution engine creates proxy instances of that interface at runtime for each element returned and forwards calls to the exposed methods to the target object."
[§Closed projections — definition] "A projection interface whose accessor methods all match properties of the target aggregate is considered to be a closed projection."
[§Closed projections — optimization] "If you use a closed projection, Spring Data can optimize the query execution, because we know about all the attributes that are needed to back the projection proxy."
[§Open projections — limitation] "Spring Data cannot apply query execution optimizations in this case, because the SpEL expression could use any attribute of the aggregate root."
[§Class-based projections — DTO] "If the store optimizes the query execution by limiting the fields to be loaded, the fields to be loaded are determined from the parameter names of the constructor that is exposed."
[§JPQL query rewriting] "If an @Query-annotated query already uses constructor expressions, then Spring Data backs off and doesn't apply DTO constructor expression rewriting."
[§Dynamic projections] "Type selection occurs at invocation time" — via
<T> Collection<T> findByLastname(String lastname, Class<T> type)
[§Projection limitations — joins] "Projections limit the selection to top-level properties of the target entity. Any nested properties resolving to joins select the entire nested property causing the full join to materialize."
Claims Extracted / 추출된 주장
| Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove |
|---|---|---|---|---|---|
| SPRING-PROJ-C1 | interface-based projection 은 runtime proxy 로 구현되어 declared accessor method 에 해당하는 target object property 만 노출 | [§Interface-based] "The query execution engine creates proxy instances of that interface at runtime for each element returned and forwards calls to the exposed methods to the target object." | official-vendor-doc |
Spring Data JPA repository method 반환 타입이 interface projection 인 경우 | proxy 생성 overhead 자체는 본 문서에서 정량화 안 됨 |
| SPRING-PROJ-C2 | closed projection (모든 accessor 가 aggregate property 와 매칭) 에 대해 Spring Data 는 query execution 최적화 가능 | [§Closed projections] "If you use a closed projection, Spring Data can optimize the query execution, because we know about all the attributes that are needed to back the projection proxy." | official-vendor-doc |
모든 accessor 가 entity top-level property 와 1:1 매칭되는 interface projection | "최적화" 의 구체 방식 (column subset SELECT vs full entity load) 은 본 인용에서 명시 안 됨 |
| SPRING-PROJ-C3 | open projection (@Value SpEL expression 포함) 은 Spring Data 가 query 최적화 불가 | [§Open projections] "Spring Data cannot apply query execution optimizations in this case, because the SpEL expression could use any attribute of the aggregate root." | official-vendor-doc |
@Value 기반 computed field 가 하나라도 있는 projection interface | SpEL expression 이 없는 default method 는 closed projection 으로 취급 가능 |
| SPRING-PROJ-C4 | class-based projection (DTO) 은 constructor parameter 이름으로 SELECT 할 column 을 결정 | [§Class-based] "If the store optimizes the query execution by limiting the fields to be loaded, the fields to be loaded are determined from the parameter names of the constructor that is exposed." | official-vendor-doc |
JPA constructor expression (SELECT new com.example.Dto(...) FROM ...) 을 사용하는 경우 | 모든 JPA provider 에서 동일하게 적용된다는 보장 — Hibernate vs EclipseLink 차이 가능 |
| SPRING-PROJ-C5 | @Query 에 constructor expression 이 이미 있으면 Spring Data 는 DTO rewriting 을 skip (back off) | [§JPQL rewriting] "If an @Query-annotated query already uses constructor expressions, then Spring Data backs off and doesn't apply DTO constructor expression rewriting." | official-vendor-doc |
명시적 @Query + constructor expression 조합 사용 시 | Spring Data 가 rewriting 을 back off 할 때 어떤 동작을 하는지 (전체 entity load 하는지) 는 본 인용에서 불명확 |
| SPRING-PROJ-C6 | nested property 로의 projection 은 join 전체를 materialize 하므로 column subset 최적화 불가 | [§Limitations] "Projections limit the selection to top-level properties of the target entity. Any nested properties resolving to joins select the entire nested property causing the full join to materialize." | official-vendor-doc |
entity 간 join 이 필요한 nested property 를 projection 에 포함할 때 | top-level property 만 있는 flat projection 에는 이 제한 해당 안 됨 |
| SPRING-PROJ-C7 | dynamic projection 은 Class<T> type 파라미터로 호출 시점에 projection 타입을 선택 가능 |
[§Dynamic] "Type selection occurs at invocation time" (via generic Class parameter) | official-vendor-doc |
동일 repository method 가 domain entity 도, DTO projection 도 반환해야 할 때 | dynamic projection 이 ArchUnit rule 로 강제 가능한지는 본 문서 범위 밖 |
Usage Boundaries / 적용 경계
- 이 자료가 직접 증명하는 것:
SPRING-PROJ-C1~C7: Spring Data JPA projection 의 공식 mechanism (proxy, closed/open distinction, class-based DTO, JPQL rewriting, nested join limitation, dynamic projection)
- 이 자료가 증명하지 않는 것:
- projection 을 hexagonal architecture 의 어느 layer 에 둬야 한다는 guidance — 아키텍처 배치는 본 문서 범위 밖
- closed projection 이 full entity load 대비 얼마나 빠른지의 구체 benchmark — 별도 성능 테스트 필요
- Spring Data JPA 없이 JdbcTemplate / native query 로 projection DTO 반환 시의 동작 — 별도 참조 필요
- ArchUnit 으로 projection 사용 패턴을 어떻게 강제하는지
- 내 프로젝트에 적용하려면 추가 확인이 필요한 것:
- ca-tmpl 의 hexagonal module 구조에서 projection interface 를 application layer 에 두는지 adapter layer 에 두는지 결정 (D1 결정 후)
- Hibernate 6 기준 closed projection 이 실제로 column subset SELECT 를 생성하는지 통합 테스트 검증
메모 / Notes
- Spring Data JPA 4.x 기준 (Spring Boot 3.4+ 에서 기본 버전)
- interface-based projection 은 JPA entity 와 adapter layer 사이의 "clean boundary" 를 application port 에 둘 수 있게 하는 mechanism — hexagonal 에서 web DTO 와 JPA entity 가 application layer 에 leak 하지 않으면서 필요 데이터만 반환 가능
- class-based DTO (record) 는 hexagonal application port 의 반환 타입으로 직접 사용 가능 — JPA entity (infrastructure) 가 application layer 에 노출되지 않음
Related / 관련
- raw/official-docs/cqrs-fowler-bliki — CQRS 개념 상위 문서
- raw/official-docs/at-transactional-spring-official — read-only transaction 과 projection 의 결합 근거
- raw/branch-notes/feature-application-port-usecase-contract — QueryUseCase + READ_REPOSITORY capability 선행 계약