[픽플] JPA Repository 접근 실험

이지우·2021년 5월 9일
1
post-thumbnail

픽플에서 JPA를 채택하여 도입하고 있는데, ORM(Object Relational Mapping)시 Hibernate프레임워크를 사용하고 있다.

MySQL만 주구장창 쓰다가 많이 익숙해져서 거의 자유자재로 쓸때쯤 JPA를 접하게 되었는데, 'sql을 짜는 것이 더 쉬울 것 같은데 왜 이걸 쓰는걸까' 생각했다.

막연하게 생산성이 증대된다, 개발자로 하여금 많은 시간을 낭비하지 않게 하고, 단순한 create같은 반복작업들을 할 때 느낄 수 있는 지루함(현타)를 느끼지 않게 해준다.. 라고 배웠을때는 몰랐는데

쓰다 보니 너무 편해서(...!) 느낀점이나 조사한것, 사용법을 작성해보고자 한다.
역시 백번 듣는 것보다 한번 해보는게 확실한 것 같다.

JpaRepository

픽플에는 회원이 모집글을 북마킹할 수 있는 기능이 존재한다.

이 때 사용되는 엔티티는 회원, 모집글, 북마크.

따라서 Repository도
Account JpaRepository,
RecruitmentBoard(RecBoard) JpaRepository,
Bookmark JpaRepository 가 각각 존재한다.

Controller에서 호출되는 Service단계에서, 생성 시 같은 모집글에 같은 회원이 여러번 북마크를 하면 안되니까 미리 체크하기 위해 북마크를 불러올 때 회원은 Account 객체로, 모집글은 (account는 context에서 불러져있어서 그대로 사용하고자 했었다)
그러다 문득 hibernate가 남겨주는 로그를 보니 '어라, 왠지 궁금한데' 하면서 뭔가 시험해보고싶어졌다.

코드와 Hibernate가 생성하는 쿼리 비교

확실히 어디서 쿼리가 나가는지 알기 위해 번호를 찍게 했다.

  • 오, 1이 찍히기 이전에 쿼리가 한 개 발생했다. 당연히 create가 시작하는 AccountContextService에서 시작되니까 처음 Account에 접근하겠지! 라고 생각했는데 의외로 아니었다..
    아마 이 부분은 request가 filter를 거치는 과정에서 권한을 검사하는데, 이 때 Account테이블에 속성으로 들어가있는 권한을 찾는 과정인 것 같다.

  • 1 찍힌 아래부분
    여기가 코드 상으로 AccountContextService.getContextService() 부분에서 나가는 쿼리인데, AccountJpaRepository를 접근하기때문에 한 번 select된다.

  • 2 아래 부분,
    RecruitmentBoardJpaRepository에 한 번 접근한다.

  • 3 아래 부분,
    bookmarkId는 주어졌고, account는 객체로 가지고 있다.

  • 4 아래는 Bookmark를 생성하는 부분이다. 물론 쿼리가 나가지는 않는다. 구분을 위해 찍어두었을 뿐이므로 생략.

  • 5 아래 부분,
    save시에 insert된다.

다른 것은 예상한 대로지만, 3번을 보았을 때 bookmark는 id로 조회하기 때문에 left outer join이 필요한 것 같은데, account는 객체를 가지고 있기때문에 join이 필요하지 않은 것일까?

확인을 위해 jpa repository의 파라미터를 (Account account, Long
boardId)에서 (Long accountId,Long boardId)로 넣어보기로 했다.

적용 후

(Long accountId, Long boardId)


left outer join이 두 번 일어난 것을 확인할 수 있었다.
그럼 이를 반대로 이용하면 join이 여러번 일어나지 않도록 할 수 있지 않을까?
Board도 객체로 적용해보자.

(Account account, RecBoard recBoard)


예상대로 join없이 단순한 쿼리로 원하는 값을 가져왔다.
조건에 맞는 객체를 이미 가지고 있기 때문에 해당 table과의 join이 필요없는 것 같다.

후자가 join을 거치지 않으니 더 효율적인 방식일까?
확실하게는 모르겠으나 직관적으로 봤을 때 그런 것 같다. 객체로 적용이 가능하다면 id를 굳이 뽑아낼 필요도 없고, DB에서 join작업도 거치지 않으니 훨씬 효율적이지 않을까?

지금까지는 전통적인 데이터베이스를 기준으로 '무조건 join해서 id를 통해 받아내야지!' 라고 생각했는데 이런 사소한 궁금증을 통해 내 시야가 조금 넓어진 것 같다.

profile
개발 관찰일지

0개의 댓글