From c060f314a3d7ea36bca9e491485edc36c468d1bc Mon Sep 17 00:00:00 2001 From: projectmiluju Date: Tue, 16 Sep 2025 04:32:31 +0900 Subject: [PATCH] =?UTF-8?q?refactor(ProfileSearchService):=20=ED=94=84?= =?UTF-8?q?=EB=A1=9C=ED=95=84=20=EA=B2=80=EC=83=89=20=EB=8B=89=EB=84=A4?= =?UTF-8?q?=EC=9E=84=20=EC=98=A4=EB=A6=84=EC=B0=A8=EC=88=9C=20=EC=A0=95?= =?UTF-8?q?=EB=A0=AC=20DP-430?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/repository/UserRepository.java | 29 +++++++++++++++ .../player/service/ProfileSearchService.java | 36 ++++++++++++------- 2 files changed, 53 insertions(+), 12 deletions(-) diff --git a/src/main/java/goorm/ddok/member/repository/UserRepository.java b/src/main/java/goorm/ddok/member/repository/UserRepository.java index 9ef2a7a9..1d3a846b 100644 --- a/src/main/java/goorm/ddok/member/repository/UserRepository.java +++ b/src/main/java/goorm/ddok/member/repository/UserRepository.java @@ -226,4 +226,33 @@ interface UserOverlayRow { ORDER BY LOWER(u.nickname) ASC, u.id ASC """) Page searchPlayersWithKeyword(@Param("keyword") String keyword, Pageable pageable); + + @Query(""" + SELECT DISTINCT u.id, LOWER(u.nickname) as nickname_lower FROM User u + LEFT JOIN u.location loc + LEFT JOIN u.positions pos + WHERE (:keyword IS NULL OR :keyword = '' OR + LOWER(u.nickname) LIKE LOWER(CONCAT('%', :keyword, '%')) OR + LOWER(pos.positionName) LIKE LOWER(CONCAT('%', :keyword, '%')) OR + LOWER(COALESCE(loc.region1DepthName, '')) LIKE LOWER(CONCAT('%', :keyword, '%')) OR + LOWER(COALESCE(loc.region2DepthName, '')) LIKE LOWER(CONCAT('%', :keyword, '%')) OR + LOWER(COALESCE(loc.region3DepthName, '')) LIKE LOWER(CONCAT('%', :keyword, '%')) OR + LOWER(COALESCE(loc.roadName, '')) LIKE LOWER(CONCAT('%', :keyword, '%')) OR + LOWER(COALESCE(loc.mainBuildingNo, '')) LIKE LOWER(CONCAT('%', :keyword, '%')) OR + LOWER(COALESCE(loc.subBuildingNo, '')) LIKE LOWER(CONCAT('%', :keyword, '%')) OR + LOWER(CONCAT(COALESCE(loc.region1DepthName, ''), ' ', COALESCE(loc.region2DepthName, ''))) LIKE LOWER(CONCAT('%', :keyword, '%')) + ) + ORDER BY LOWER(u.nickname) ASC, u.id ASC + """) + Page searchPlayerIdsWithKeywordAndNickname(@Param("keyword") String keyword, Pageable pageable); + + // 2단계: ID 리스트로 User 엔티티 조회 (정렬 유지) + @Query(""" + SELECT u FROM User u + LEFT JOIN FETCH u.location + LEFT JOIN FETCH u.positions + WHERE u.id IN :userIds + ORDER BY LOWER(u.nickname) ASC, u.id ASC + """) + List findUsersByIdsWithDetails(@Param("userIds") List userIds); } diff --git a/src/main/java/goorm/ddok/player/service/ProfileSearchService.java b/src/main/java/goorm/ddok/player/service/ProfileSearchService.java index e59ac086..f0811513 100644 --- a/src/main/java/goorm/ddok/player/service/ProfileSearchService.java +++ b/src/main/java/goorm/ddok/player/service/ProfileSearchService.java @@ -44,28 +44,40 @@ public Page searchPlayers(String keyword, int page, int s size = (size <= 0) ? 10 : size; Pageable pageable = PageRequest.of(page, size); - String searchKeyword = hasText(keyword) ? keyword.trim() : null; - Page rows = userRepository.searchPlayersWithKeyword(searchKeyword, pageable); + // 1단계: ID와 정렬용 nickname 조회 + Page userIdPage = userRepository.searchPlayerIdsWithKeywordAndNickname(searchKeyword, pageable); + + if (userIdPage.getContent().isEmpty()) { + return new PageImpl<>(Collections.emptyList(), pageable, 0); + } + + // ID만 추출 (이미 정렬된 순서) + List userIds = userIdPage.getContent().stream() + .map(row -> (Long) row[0]) + .toList(); + + // 2단계: User 엔티티 조회 (정렬 순서 유지) + List users = userRepository.findUsersByIdsWithDetails(userIds); - List distinctUsers = rows.getContent().stream() - .collect(Collectors.toMap(User::getId, user -> user, (existing, replacement) -> existing)) - .values() - .stream() - .sorted((u1, u2) -> { - int nicknameCompare = u1.getNickname().compareToIgnoreCase(u2.getNickname()); - return nicknameCompare != 0 ? nicknameCompare : u1.getId().compareTo(u2.getId()); - }) + // ID 순서대로 정렬 (첫 번째 쿼리의 정렬 순서 유지) + Map userMap = users.stream() + .collect(Collectors.toMap(User::getId, user -> user)); + + List sortedUsers = userIds.stream() + .map(userMap::get) + .filter(Objects::nonNull) .toList(); - List responses = distinctUsers.stream() + List responses = sortedUsers.stream() .map(u -> toResponse(u, currentUserId)) .toList(); - return new PageImpl<>(responses, pageable, rows.getTotalElements()); + return new PageImpl<>(responses, pageable, userIdPage.getTotalElements()); } + // 나머지 메서드들은 그대로 유지 private ProfileSearchResponse toResponse(User u, Long currentUserId) { // 기존 코드 그대로