백엔드 면접 용어 사전
Spring·JPAQMember

Q 클래스

QueryDSL 이 빌드 시점에 엔티티로부터 생성하는 메타모델 클래스. 쿼리 조건을 타입 있는 필드로 쓰게 해준다.

무엇이 생성되는가 @Entity class Member { String email; int age; } 를 컴파일하면 QueryDSL 의 애너테이션 프로세서가 QMember 를 만든다. 안에는 StringPath email, NumberPath<Integer> age 처럼 필드마다 타입이 붙은 경로 객체가 들어 있다. Path 는 "이 쿼리에서 어떤 칼럼을 가리키는지" 를 나타내는 표현식이고, 타입이 있으니 그 타입에 맞는 연산만 호출할 수 있다.

왜 타입이 중요한가 문자열 쿼리에서 age = 'abc' 는 컴파일러가 막지 못한다. NumberPath<Integer> 에는 문자열을 넘기는 메서드가 아예 없으므로 같은 실수가 컴파일 단계에서 불가능해진다. 즉 검증 시점을 런타임에서 컴파일 타임으로 끌어당기는 것이 Q 클래스의 존재 이유다.

대가 소스가 생성물이라는 점에서 두 가지 비용이 온다.

  • 빌드 설정이 필요하다. annotationProcessor 의존성을 걸어야 하고, 생성된 소스는 보통 build/generated 아래에 놓여 저장소에 커밋하지 않는다.
  • 엔티티를 바꾸면 재생성해야 한다. 필드 이름을 바꿨는데 Q 클래스가 옛것이면 컴파일이 깨진다. 클린 빌드가 필요한 순간이 이때다. IDE 가 생성 디렉터리를 소스 경로로 인식하지 못해 "QMember 를 찾을 수 없다" 로 보이는 문제도 대부분 이 경로 설정 문제다.

면접에서 이어지는 지점 Spring Boot 3 이후 Q 클래스 생성이 실패하는 사례는 대개 QueryDSL 항목에 적은 Jakarta 이행 때문이다. 프로세서가 javax.persistence.Entity 를 찾는데 엔티티에는 jakarta.persistence.Entity 가 붙어 있어, 프로세서가 엔티티를 하나도 인식하지 못하고 생성물이 비는 형태로 드러난다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — Spring·JPA — IoC/DI·AOP·영속성 컨텍스트·N+1