🦵🏼발단
우테코에 오기 전, 팀 프로젝트를 하면서 JPQL의 new 키워드를 통해 생성한 DTO를 받은 적이 있었다.
그러고 난후 코드리뷰에서 다른 팀원이 비용이 비싸기 때문에 DB단에서 연산을 지양하는 것이 좋을 것 같다는 식의 피드백을 주었는데, 당시에 new 키워드의 실행 시점이 어느 시점인지 파악해보거나 깊게 생각해보지 않고 코드를 변경했었다.
우테코에 오고 난후, 미션을 진행하면서 JPQL로 new 키워드를 사용한 예제 코드가 있었는데 당시의 경험이 기억나면서 정말 지양해야 할지 장단점이 무엇일지 파악하고자 글을 작성하게 되었다.
🤔 의문
- new 키워드가 정말 DB단에서 연산이 맞을까?
- new 키워드, 더 나아가 JPQL은 어떻게 동작할까?
- 아니라면, 지양해야 하는 다른 이유가 있을까?
- 최종적으로 new 키워드를 어떻게 받아들이는 것이 좋을까?
1. new 키워드가 정말 DB단에서 연산이 맞을까?
먼저, new 키워드 DB 단의 연산이 맞는지 확인하기 위해서 JPQL과 해당 연산의 실행 시점을 파악해보자.
JPQL의 동작과정
JPQL을 어떻게 동작시키는지 봐보도록 하자. Hibernate의 구현방법으로 살펴보겠다.
- JPQL 파싱
- Hibernate는 JPQL 쿼리를 받으면 먼저 파싱을 진행한다.
- 파싱 과정에서 JPQL 쿼리의 구문을 분석하고, 엔티티 클래스와 속성, 연산자, 함수 등의 요소를 식별한다.
- AST(Abstract Syntax Tree) 생성
- 파싱 결과를 바탕으로 JPA 프로바이더가 추상 구문 트리(AST)를 생성한다.
- 이때 AST는 JPQL 쿼리의 구조와 의미를 트리 형태로 표현한 것이다.
- SQL 생성
- 그 후 생성된 AST를 분석하여 데이터베이스 종류에 맞는 SQL 쿼리로 변환
- 이때 엔티티 클래스와 데이터베이스 테이블 간의 매핑 정보를 사용한다.
- SQL 실행
- 생성된 SQL 쿼리를 데이터베이스에 전송하고 실행시킨다.
- 실행이 완료된 후, 데이터베이스에서 반환된 결과 집합을 받는다.
- 결과 매핑:
- Hibernate는 데이터베이스에서 반환된 결과 집합을 분석하여 JPQL 쿼리의 반환 타입에 맞게 처리한다.
- 엔티티 객체를 반환하는 JPQL 쿼리의 경우 데이터베이스 결과를 엔티티 객체로 변환하게 된다.
위 과정에서 알 수 있는 사실은 쿼리가 실행되고 DB에서 결과 집합을 받은 후 Hibernate가 자바 객체로 매핑해준다.
즉, new 키워드를 통한 객체 매핑 역시 애플리케이션 단에서 동작한다는 것을 알 수 있다.
2. 아니라면, 지양해야 하는 다른 이유가 있을까?
1번 의문의 해소를 통해 기존에 지양해야 한다고 제시되었던 이유가 사라졌다.
그렇다면 new 키워드를 막 사용해도 될까?
내가 생각해본 new 키워드의 문제점은 아래와 같다.
new 키워드의 문제점
- JPA 기능 사용 제한
- new 키워드를 통해 대상 엔티티가 아닌 DTO등 다른 자바 객체를 생성하기 때문에 JPA의 지연 로딩, 캐싱 등의 최적화 기능을 활용하기 어려워진다.
- 따라서 영속성 컨텍스트의 이점을 충분히 활용할 수 없다는 단점이 있다.
- 유지보수 관점
- 쿼리 결과의 구조가 변경되거나 DTO가 변경될 경우, DTO 클래스와 쿼리를 함께 수정해야 하므로 유연성이 떨어질 수 있다.
- 요구사항에 대응하기 위해 여러 버전의 DTO와 쿼리가 만들어진다면 각 DTO의 역할을 파악하는데에 힘들어질 수 있다.
- 또한, jpa 메서드만 보았을 때, 실행 시 개발자가 기대하는 반환타입과 실제 반환타입이 다를 수 있다.
🔥 최종적으로 new 키워드를 어떻게 받아들이는 것이 좋을까?
new 키워드에 알아보면서 든 생각을 정리해면, "굳이 사용하지 않아야 하나?"라는 의문을 지울 수 없었다.
new를 사용하는 예상 상황은 아마도,
- DB 단의 연산을 통해 엔티티 값이 아닌 새로운 값을 받거나
- 연산이 없지만 다른 여러 테이블의 값들이 필요한 경우
이지 않을까 싶다. 그런데 1번은 엔티티의 데이터가 아닌 새로운 데이터를 필요로 하기 때문에 영속성 컨텍스트의 이점을 사용하지 않으려는 경우라고 생각한다.
너무 많은 상황에서 사용하려고 하면 안되겠지만은, 위에서 말한 문제점들을 크게 고려해도 되지 않는 상황이라면 new를 사용해도 괜찮을 것 같다.
참고 자료
'우아한테크코스 6기 > 2단계' 카테고리의 다른 글
난 레벨 2 동안 어떤 경험들을 했을까? (0) | 2024.07.08 |
---|---|
gradle 살펴보기 (0) | 2024.06.23 |
[방탈출 사용자 예약] @Bean, @Component, 그리고 POJO (0) | 2024.05.14 |
영속성 entity 와 domain entity 분리해보기 (0) | 2024.05.12 |
[방탈출 예약 관리] 템플릿 엔진과 @RestController (0) | 2024.05.12 |