본문 바로가기
웹 개발/블로그 만들기 프로젝트

스프링 데이터 JPA - @EntityGraph 사용 및 Page로 받아오기

by L3m0n S0ju 2023. 11. 19.

 

 

 

@Query("SELECT p FROM Post p JOIN FETCH p.writer WHERE (:search IS NULL OR p.title LIKE %:search%) AND (:writer IS NULL OR p.writer.uid = :writer)")
List<Post> findAllWithFetchJoin(String search, String writer, Pageable pageable);

long count();

@Query("SELECT COUNT(p) FROM Post p WHERE :search IS NULL OR p.title LIKE %:search%")
long countBySearch(String search);

 

조금씩 레포지토리에 조건이 추가되다 보니깐 점점 복잡해지는 느낌이 든다. 위 레포지토리는 조건이 2개 추가되었는데 복잡하다. 슬슬 QueryDSL을 적용할 때가 된 것 같다.

 

반환 타입도 Page로 가져와서 count 값도 사용하고 싶지만 그렇게 하면 페치조인을 사용할 수 없다고 생각했어서 위 코드처럼 count 값을 따로 가져왔었다. 지금 왜 그렇게 생각하고 있었는지 기억이 잘 나지는 않지만 결과적으로 아래 코드처럼 함수를 하나로 줄이고 오히려 코드 양도 줄었다. 페치조인 역할을 대신하는 @EntityGraph를 사용하고 Page로 반환을 하기 때문에 count를 따로 쿼리로 실행할 필요 없이 한번에 정보를 얻어올 수 있다.

@EntityGraph(attributePaths = {"writer"})
@Query("SELECT p FROM Post p WHERE (:search IS NULL OR p.title LIKE %:search%) AND (:writer IS NULL OR p.writer.uid = :writer)")
Page<Post> findAllWithFetchJoin(String search, String writer, Pageable pageable);

 

 

 

 

 

 

 

 


 

List<Post> findPosts;
findPosts = postDataRepository.findAllWithFetchJoin(search, findMember.getUid(), pageable);
List<PostInfoResponseDto> postList = matchLike(findMember, findPosts);
long totalItemsCount = search == null ? postDataRepository.count() : postDataRepository.countBySearch(search);

AllPostsResponseDto allPostsResponseDto = AllPostsResponseDto.builder()
        .posts(postList)
        .totalItemsCount(totalItemsCount)
        .build();
return allPostsResponseDto;

 

예를 들어서 위에서 totalItemsCount을 가져오기 위해 long totalItemsCount = search == null ? postDataRepository.count() : postDataRepository.countBySearch(search);

를 실행했지만 아래처럼 page로 가져오면 코드 가독성이 높아진 것을 확인할 수 있다.

 

Page<Post> findPostsPage;
findPostsPage = postDataRepository.findAllWithFetchJoin(search, findMember.getUid(), pageable);
List<PostInfoResponseDto> postList = matchLike(findMember, findPostsPage.getContent());

AllPostsResponseDto allPostsResponseDto = AllPostsResponseDto.builder()
        .posts(postList)
        .totalItemsCount(findPostsPage.getTotalElements())
        .build();
return allPostsResponseDto;

 

 

 

 

 

 


처음에는 프론트에서 모든 데이터를 받아서 페이징 함수를 구현했었는데 데이터가 많아지니깐 점점 느려졌고 데이터를 가져오는데 6초 정도 걸려서 조금씩 구닥다리 느낌이 났다. 지금은 캐싱 기능을 통해서 거의 1초안에 데이터를 가져오지만 처음에는 성능 개선을 위해서 페치 조인을 사용하였다. 페이징 기능을 프론트엔드가 아니라 백엔드에서 다시 구현하면서 시간적으로도 단축이 많이 되었지만 조금씩 코드 가독성이 떨어지는 느낌을 받았다. 개인적으로 함수가 10줄 이상 넘어가는 것을 싫어해서 계속해서 분리하고 또 분리하다 보니깐 이제는 어느 정도 한눈에 알아볼 수 있는 코드가 된 것 같다. 앞으로 할 일은 QueryDSL만 추가하면 딱히 추가할 기능은 없어 보인다.

댓글