-
자바 코드로 정렬 vs db에서 특정 값을 정렬해서 select프로젝트/Trend-Pick 2023. 7. 28. 22:30
사진 랭킹을 보여주는 페이지를 만들 때 dto로 사진 과 사진의 좋아요 개수를 넘겨줘야한다.
처음에는 사진만 select 한 다음 service 계층에서 자바 코드로 로직을 구현했었다.
하지만 좋아요 개수가 아니라 시간에 따른 좋아요 개수로 정렬해야하기 때문에 정렬을 할 때 db와의 소통이 무조건 필요했다. 많은 시간을 들인 끝에야 쿼리로 데이터를 받아오는 것이 맞다고 판단해서 repository 계층에서 select를 할 때 사진과 함께 사진의 좋아요 수를 쿼리로 받아왔다.
주간 랭킹의 예시
public List<Object[]> weeklyLike() { LocalDateTime now = LocalDateTime.now(); LocalDateTime startOfWeek = now.with(DayOfWeek.MONDAY); LocalDateTime endOfWeek = startOfWeek.plusDays(7); List<Object[]> resultList = em.createQuery( "SELECT l.picture, " + "SUM(CASE WHEN l.status = :likeStatus THEN 1 " + " WHEN l.status = :dislikeStatus THEN -1 " + " ELSE 0 END) as likeDislikeDifference " + "FROM Like l " + "WHERE l.likeTime >= :startOfWeek " + "AND l.likeTime < :endOfWeek " + "GROUP BY l.picture.id " + "ORDER BY likeDislikeDifference DESC", Object[].class) .setParameter("startOfWeek", startOfWeek) .setParameter("endOfWeek", endOfWeek) .setParameter("likeStatus", LikeStatus.LIKE) .setParameter("dislikeStatus", LikeStatus.DISLIKE) .setMaxResults(3) .getResultList(); return resultList; }
이렇게 받아오고 return 값을 Object[] 배열로 반환했다.
public List<Object[]> RankingOfWeek() { List<Object[]> weeklyLike = likeRepository.weeklyLike(); return weeklyLike; }
Service 계층에서는 조회를 한 다음 컨트롤러로 넘겨주었다.
@GetMapping("weekly_ranking") public List<WeeklyRankingDto> weeklyRanking() { List<Object[]> pictures = likeService.RankingOfWeek(); List<WeeklyRankingDto> weeklyList = new ArrayList<>(); for (Object[] result : pictures) { Picture picture = (Picture) result[0]; Long likeDislikeDifference = (Long) result[1]; Long pictureId = picture.getId(); WeeklyRankingDto weeklyRankingDto = new WeeklyRankingDto(pictureId, likeDislikeDifference); weeklyList.add(weeklyRankingDto); } return weeklyList; }
컨트롤러 계층에서 Service 계층의 RankingOfWeek를 불러와서 picutres라는 Object[] 타입의 리스트로 받아왔다.
그리고 for문을 통해 result의 첫번째 값 (result[0])은 picutre로, reuslt의 두번째 값 (result[1])은 좋아요의 수로 형변환을 시켜준 뒤 dto의 리스트에 하나씩 넣어주고, 그 리스트를 반환했다.
값을 가져오거나 정렬할 때에 자바 코드로 하는 것이 더 나은 선택인지, 쿼리를 통해 특정 값을 가져오는 것이 효율적인지 정하는 것이 중요하다.
이번에는 좋아요를 누른 시간에 따라서 달라졌다.
만약에 A라는 사진의 누적 좋아요 수가 100개인데, 그 중에서 이번 주에 받은 좋아요 수인 50개만 가져와야 하니까 db에서 특정 값을 가져오는 것이 훨씬 효율적이라는 것을 알게 되었다.
'프로젝트 > Trend-Pick' 카테고리의 다른 글
fetch join으로 성능 최적화 (0) 2023.08.16 AWS S3를 이용한 사진 저장 (0) 2023.07.31 비어있을 수도 있는 객체의 조회 -> Optional 사용 (0) 2023.07.27 @RequestParam과 @RequestBody의 차이점 (0) 2023.07.22 로그인 세션으로 자동 CRUD (0) 2023.07.12