| 구분 | 검토 결과 | 설명 |
|---|---|---|
| 인터페이스 기반 프로젝션 = 타입 안정성 O? | 부분적 O | 컴파일 시 getName() 등 메서드 유무는 확인됨. 하지만 매핑 필드명 오류나 as(...) 누락은 런타임 에러 |
Projections.constructor(...)는 리플렉션 사용? | 맞음 | Constructor.newInstance()로 객체 생성 |
Projections.bean(...)은 setter 기반이고 invoke() 호출? | 맞음 | Method.invoke()로 setter 호출 |
Projections.fields(...)은 필드 직접 접근 방식이다? | 맞음 | Field.set() 호출 (리플렉션 기반) |
@QueryProjection은 리플렉션을 안 쓴다? | 맞음 | 직접 new QDto(...) 호출이므로 리플렉션 없음 |
| DTO는 1차 캐시에 등록되지 않는다? | 맞음 | **비엔티티(Non-Entity)**는 영속성 컨텍스트에 포함되지 않음 |
| 리플렉션은 느리고 위험하다? | 일부 맞음 | 느릴 수 있지만, JVM이 내부적으로 캐싱해 성능 이슈는 대부분 미미함. 다만 런타임 오류 가능성은 있음 |
이 표현은 많은 문서(스프링 공식 문서 포함)에서도 쓰지만 정확히 말하면 과장된 표현
정확히는 "구조적 안정성(structural safety)이 있고, 컴파일 시점에 메서드 존재 여부는 확인되지만, 매핑 오류는 런타임에 발생한다"
예를 들어:
public interface ItemView {
String getName(); // O
Integer getPrice(); // O
}
이 인터페이스는 컴파일 시점에 문제가 없지만,
Projections.bean(ItemView.class, item.name.as("username"))
이런 식으로 alias를 잘못 주거나 누락하면 런타임에 해당 필드가 null이 됨.
→ 컴파일러는 ItemView가 어떤 필드를 조회했는지 모름.
그래서 "타입 안정성 O"이라는 말은 절반만 맞는 말.
정확히는:
“컴파일러가 인터페이스의 구조를 확인해주므로 기초적인 타입 안정성은 있으나, 필드 매핑은 런타임까지 알 수 없어 완전한 타입 안전은 아니다.”
| 항목 | 근거 출처 |
|---|---|
Projections.bean → setter 기반 주입 | QueryDSL 공식 Docs (archive) |
@QueryProjection은 직접 생성자 호출 방식 | QueryDSL reference, [김영한 강의 실전 QueryDSL] |
| 인터페이스 기반은 프록시 리플렉션 구현 | [Spring Data JPA 공식 문서 - Projections]https://docs.spring.io/spring-data/jpa/reference/repositories/projections.html#projections.interfaces |
| 원래 문장 | 보완된 표현 |
|---|---|
| "인터페이스 기반도 컴파일 타임에 타입 안정성 보장" | → "인터페이스 구조는 컴파일 시 확인되지만, 필드 매핑은 런타임에만 확인됨 (부분적인 타입 안정성)" |
| "리플렉션은 느림" | → "리플렉션은 런타임 비용이 있으나 JVM 최적화 덕분에 실질적인 성능 문제는 거의 없음. 하지만 타입 안정성은 떨어짐." |