JPA 구현체인 Hibernate 의 문제점

Java 의 ORM 인 JPA(Java Persistence API)와 그 구현체 중 하나인 Hibrernate 를 사용하다보면 몇 가지 불편사항이 생긴다.

  • Native Query 를 사용하지 않으면 (JPA) 쿼리 실행 계획이 어떻게 되는지 알 수 없다
  • Hibernate debug log 를 이용하면 Bulk insert 여부를 알 수 없다
  • Hibernate debug log 를 이용하면 Binding variable 파악을 위한 불편이 생긴다
  • Query 의 execute 결과를 계획하기 어렵다

 

사실 어떻게 보면 단편적 혹은 극단적으로 작성한 사항일 수 있다.

하지만 비즈니스 로직을 작성하다보면 위 같은 사항들이 얼마나 불편한지 알게된다.

 

어떻게든 해결하는 방법은 있다.

예를들면 Binding variable 같은 문제는

로 해결한다던지….

 

properties 나 log4j configuration class 를 바꾸는 등

어차피 소스코드를 변경해야한다면 한 번에 해결하는편이 좋지 않을까?

위에 나열한 대부분의 단점을 해결할 수 있는 방법이 있다.

 

Datasource Proxy 란

 

Java 에서 ‘우아하게’ (혹은 그럴듯하게) DB에 접근하는 과정은 다음과 같다.

Application -> DataSource -> JDBC Driver -> Physical DB

풀이하자면,
Application 에서는
DataSource 로부터 Connection 정보를 설정하고
DB Connectivity Driver 를 이용해
Physical DB 에 연결한다.

이 DataSource 와 Application 사이에 Proxy 를 두는것이다

연결을 가로채어 Persistence 와 Gathering 등 Database 와의 일련의 모든 로직들을 까볼 수 있다.

다음과 같이 말이다.

Application -> DataSourceProxy -> DataSource -> JDBC Driver -> Physical DB

 

DataSourceProxy 설정방법

먼저 DataSourceProxy 는 Spring 내에 기본적으로 탑재돼있지 않기 때문에 별도의 의존성이 필요하다.

본 글에서는 ttddyy 님의 datasource-proxy (https://github.com/ttddyy/datasource-proxy) 를 이용하도록 한다. Github의 README.md 를 참고하여 dependency 설정을 해주도록 한다. (maven, gradle 등 빌드툴에 맞게)

 

이후 DataSource 를 Bean 을 설정하는 부분을 DataSourceProxy 객체를 반환하도록 작성해야 한다.

예를들어 Spring 에서는 기본 DataSource 를 Bean 을 등록할 때,

위 처럼 Configuration class 에 method 를 작성한다.

 

이 DataSource 를 반환하는 method 에서 DataSourceProxy 객체를 반환하도록, 아주 약간만 수정해주면 된다.

정말 간단하게, DataSourceProxyBuilder 에 이전에 생성한 dataSource 객체를 담고 qualifier (bean name) 을 지정해준다.

이후 필요한 설정들을 빌더에 추가로 덧붙여준다. 아래는 내가 사용하는 설정이다.

  • logQueryToSysOut() : System.out 으로 수행된 query 를 출력한다.
    e.g.)

    {“name”:”dataSource”, “connection”:5, “time”:85, “success”:true, “type”:”Prepared”, “batch”:true, “querySize”:1, “batchSize”:100, “query”: ~~~~

  • asJson() : 위 출력될 query 데이터의 형식을 json 형식으로 지정한다.
  • countQuery() : 실행된 query 의 count 를 보여준다.
  • afterQuery() : query 가 실행된 이후의 동작을 지정한다. Java8 의 Consumer 를 받는다.
    Consume 을 위해 제공되는 객체는 ExecInfo 와 QueryInfoList 2개이다. (위 코드 참고)
    보통 query elasped time 을 찍는다.

위 설정을 마치고 query 가 수행되면 아래와 같이 로그가 남을것이다.

 

말 그대로 로그이니, 디버깅에 사용하고 싶다면 JSON Beautifier 등을 이용해 이쁘게 보도록 하자

 

 

주의사항

이 DataSourceProxy 을 이용한 콘셉트는 DataSource 위에 추상계층이 있는 것이다.

따라서 ORM(여기서는 JPA) 를 구현한 라이브러리를 이용할때는 해당 로그를 꺼야, 이중으로 로그가 나오는 것을 막는다

 

예를 들어 hibernate 라면 application properties 에서

다음 3줄을 코멘트 처리하거나 지워주도록 하자.

 

 

참고문헌


댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다

This site uses Akismet to reduce spam. Learn how your comment data is processed.