--- title: official-doc / Spring Data JPA — Projections (Spring Official Reference) source_type: official-doc url: https://docs.spring.io/spring-data/jpa/reference/repositories/projections.html archive_url: status: raw confidence: high tags: [spring-data, jpa, projection, read-model, cqrs, query, ca-skeleton] related_branches: [feature-application-query-bypass-contract] related_projects: [ca-skeleton] created: 2026-06-04 last_reviewed: 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 ` Collection findByLastname(String lastname, Class 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 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 선행 계약