본문 바로가기

Backend/Spring

[JPA] JPA를 통한 데이터 조회 (Entity, DTO)

 

 

JPA를 통한 데이터 조회

JPA(Jakarta Persistence Api)*로 조회한 DB의 데이터를 매핑할 때 Entity(엔티티)나 DTO를 이용한다. 웹 어플리케이션을 만들 때 두 매핑방식에는 서로 다른 장단점이 존재하며 상황에 따라 적합한 방식을 사용한다.

 

*2019년 이후로 JPA의 이름은 Java Persistence Api에서 Jakarta Persistence Api로 바뀌었다.

https://en.wikipedia.org/wiki/Jakarta_Persistence

 

 

 

 

 

Entity / DTO 매핑 방식의 차이점

큰 맥락에서 둘 사이의 가장 큰 차이점은 '코드의 가독성'과 '조회되는 데이터의 양'이다.

 

- 엔티티 조회 방식

가독성이 좋고 유지보수를 하는데 편리하다. 하지만 엔티티에 매핑할 경우 엔티티의 모든 정보를 DB에서 가져오기 때문에 비즈니스 로직에 불필요한 정보까지 가져올 수 있다는 단점이 존재한다.

 

- DTO 조회 방식

비즈니스 로직에 맞추어 필요한 데이터만 가져올 수 있다. 하지만 dto에 맞추어 jpql을 작성해야하기 때문에 특정 요청에 종속되기 때문에 재사용성이 떨어진다. (presentation layor의 request에 적합하게 커스텀된다.) 이는 성능 최적화 등을 위한 유지보수시 코드의 많은 수정을 필요로한다.

 

 

 

 

 

데이터 전달시 유의사항

JPA에서 클라이언트의 요청에 대응하여 데이터를 조회하고 응답할 때, 다음과 같은 사항을 주의해야한다.

 

 

- 엔티티

1. 조회한 엔티티를 그대로 전달

   API 스팩이 한번 정해지면 변경하기 어렵다. 엔티티는 비즈니스 모델의 확장에 따라 변동가능성이 존재한다. 때문에 가변적인 엔티티를 API 스팩에 연결하면 유지보수에 어려움이 발생한다.

> API 스팩에 맞는 DTO 객체를 사용하여 클라이언트의 요청에 응답한다.

 

 

2. 엔티티 조회에 따른 다수의 쿼리 발생

  엔티티 조회 시 지연로딩이 설정된 엔티티들에 의하여 DB에 연쇄적으로 SQL문이 실행되며 이는 심각한 성능저하문제로 연결될 수 있다.

> fetch join을 사용하여 지연 로딩 속성을 무시하고 연관관계를 갖는 엔티티를 동시에 조회한다.

 

 

3. 컬렉션 조회 및 페이징 적용

  컬렉션 조회 시 페치조인을 사용하면 페이징 처리가 불가능하다. 1:N 관계일 때 조회되는 테이블 뷰의 row는 'N'에 맞추어 형성된다. distinct 키워드를 통해 조회 결과의 중복을 제거할 순 있지만 페이징 처리는 불가능하다. (전체 조회 결과를 가져와 인메모리에서 하이버네이트가 페이징 처리를 한다는 경고문을 볼수 있다. - 시스템에 굉장히 위험)

> i. 일대일 or 다대일 관계는 페치조인을 사용하여 쿼리수를 최적화

   ii. 컬렉션은 페치조인 대신 지연로딩을 유지하고 hibernate.default_batch_fetch_size 혹은, @BatchSize 로 최적화한다.

 

 

 

- DTO

1. 컬렉션 조회

  루트 쿼리(커스텀된 DTO 조회 쿼리)를 실행하고 컬렉션을 초기화 하기 위한 조회 쿼리를 실행하면 총 실행 쿼리 수는 '1+N'개로 시스템에 부하를 가져올 수 있다. 

> 'in' 연산자를 사용하여 컬렉션을 단일쿼리로 조회한다. 1(루트) + 1(컬렉션) 번의 쿼리를 실행한다.

 

 

2. 플랫 데이터

>  필요한 모든 데이터를 단일쿼리로 조회하여 DTO로 가져온다. API 스팩에 맞는 형태로 바꾸어야하는 번거로움이 존재하고 루트 쿼리 대상에 맞추어 페이징처리작업을 하기 어렵다.

 

 

 

 

 

권장 순서

1. 엔티티 조회 방식

    i. 페치조인으로 쿼리 수 최적화

    ii. 컬렉션 최적화

        a. 페이징 필요: hibernate.default_batch_fetch_size , @BatchSize 사용

        b. 페이징 필요 X: 페치조인 사용

2. 위 방식으로 원하는 성능이 안나올 시 DTO 조회 방식 사용

3. 2번 방식으로 어려울 경우 NativeSQL or 스프링 JdbcTemplate 사용

 

 

 

 

 

 

 

 

 

[참고]

(inflearn) 실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화 (김영한)  - https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-JPA-API%EA%B0%9C%EB%B0%9C-%EC%84%B1%EB%8A%A5%EC%B5%9C%EC%A0%81%ED%99%94/dashboard