문제에 대한 한줄 요약

Problem - 현재 어떤 문제, 혹은 질문이 있는지

queryqsl을 사용하면서 테이블에 있는 컬럼들중에 제외하거나 추가해서 데이터를 받아와야 해서 프로젝션(Projection)을 사용하여 어떤 컬럼들을 조회할지 대상을 지정해서 사용 하였고Projection.constructor 방식을 사용하면서 한가지 문제가 발생했습니다.

Projection.constructor 방식을 사용하면 Projection.constructor에 주입하는 클래스의 변수의 작성 순서와 컬럼의 순서를 일치시켜줘야 하는 문제가 발생했습니다.

Reason - 해당 Problem의 이유, 문제가 되는 사유가 무엇인지

Projection.constructor에 주입하는 클래스의 변수 작성 순서와 컬럼 순서를 일치시켜줘야 하는 이유는 Projection.constructor 방식은 생성자 기반으로 바인딩 하기 때문입니다.

즉 값이 넘어갈 때 생성자와 순서를 일치시켜줘야 합니다!

해당 문제점의 가장 큰 문제는 에러가 초기에 발견되지 않고 사용자가 해당 기능을 사용하면 에러가 발생하여 데이터가 보내지지 않는 점이라는 것입니다.

위에서 constructor를 사용하는 경우에 실질적으로 동작을 해야지만 에러가 발생하는 이유는 생성자를 객체 생성자에 직접 바인딩 하는 것이 아닌 Expression<?> 값을 넘기는 방식? 이기 때문입니다.

결국 값을 넘길 때에 생성자와 순서를 일치해야하기때문에 직접 동작해야지만 에러가 발생하는 것으로 판단됩니다.

Try to solve - 문제를 해결하기 위해 어떤 시도를 했고, 조사한 사항은 어디까지인지 ( 중요 )

Projection에는 여러가지 방식이 있습니다.

  1. Projections.bean, Projections.fields
    1. setter 기반으로 동작하게 된다.
    2. 사용자가 기능을 사용해야 에러가 발견된다.
  2. Projections.constructor
    1. 생성자 기반으로 동작합니다.
    2. 타입만 일치하면 된다.
    3. 실질적으로 값이 들어올때 생성자에 바인딩 하는 문제가 있다.
    4. 사용자가 기능을 사용해야 에러가 발견된다.
  3. @QueryProjection
    1. 가장 중요한건 @QueryProjection은 Projections.constructor, bean, fields와는 다르게 생성자(Q클래스) 그대로 사용할 수 있기 때문에 데이터 타입이 일치 하지 않으면 그 빌드 단계에서 에러를 발생시켜준다.
    2. IDE 에서도 자체 에러를 뱉어준다.
    3. Projections.constructor와는 다르게 생성자에 파라미터를 빼고 추가하여 원하는 컬럼만을 사용할 수 있다는 편리함도 있다.
      • 예제(확실한 차이를 위해 파라미터를 수정하였기 때문에 차이만 보면 좋을것 같습니다.)
    4. 가장 안전하고 편리하다고 판단.

여러가지 방식중에 빌드 단계에서 에러를 뱉어주어 가장 안전한 방식이라고 생각한 @QueryProjection을 선택하여 문제를 해결했습니다.

하지만 한가지 단점이 있다면 해당 클래스 전체 생성자에 @QueryProjection을 직접 매칭 시켜줘야 해서 @AllArgsConstructor 어노테이션을 사용할 수 없는 불편함이 있었습니다.

( Option ) Alternative - 문제를 해결하지 못할 경우의 대안