Skip to content

Commit 51d79c6

Browse files
authored
✨ [feat] 유저 닉네임으로 정보 조회 (#101)
* ✨ feat: 특정 닉네임이 포함된 유저 정보 조회 기능 * 🐛 fix: 닉네임 중복 확인 시 대소문자 구분하지 않음 * chore: Java 스타일 수정 --------- Co-authored-by: github-actions <>
1 parent 4c2cd3a commit 51d79c6

File tree

6 files changed

+68
-8
lines changed

6 files changed

+68
-8
lines changed

backend/src/main/java/io/f1/backend/domain/admin/api/AdminController.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66

77
import lombok.RequiredArgsConstructor;
88

9+
import org.apache.commons.lang3.StringUtils;
910
import org.springframework.data.domain.Pageable;
1011
import org.springframework.http.ResponseEntity;
1112
import org.springframework.web.bind.annotation.GetMapping;
1213
import org.springframework.web.bind.annotation.RequestMapping;
14+
import org.springframework.web.bind.annotation.RequestParam;
1315
import org.springframework.web.bind.annotation.RestController;
1416

1517
@RestController
@@ -21,8 +23,15 @@ public class AdminController {
2123

2224
@LimitPageSize
2325
@GetMapping("/users")
24-
public ResponseEntity<UserPageResponse> getUsers(Pageable pageable) {
25-
UserPageResponse response = adminService.getAllUsers(pageable);
26+
public ResponseEntity<UserPageResponse> getUsers(
27+
@RequestParam(required = false) String nickname, Pageable pageable) {
28+
UserPageResponse response;
29+
30+
if (StringUtils.isBlank(nickname)) {
31+
response = adminService.getAllUsers(pageable);
32+
} else {
33+
response = adminService.searchUsersByNickname(nickname, pageable);
34+
}
2635
return ResponseEntity.ok().body(response);
2736
}
2837
}

backend/src/main/java/io/f1/backend/domain/admin/app/AdminService.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,10 @@ public UserPageResponse getAllUsers(Pageable pageable) {
2424
Page<UserResponse> users = userRepository.findAllUsersWithPaging(pageable);
2525
return toUserListPageResponse(users);
2626
}
27+
28+
@Transactional(readOnly = true)
29+
public UserPageResponse searchUsersByNickname(String nickname, Pageable pageable) {
30+
Page<UserResponse> users = userRepository.findUsersByNicknameContaining(nickname, pageable);
31+
return toUserListPageResponse(users);
32+
}
2733
}

backend/src/main/java/io/f1/backend/domain/user/app/UserService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ private void validateNicknameFormat(String nickname) {
6666

6767
@Transactional(readOnly = true)
6868
public void validateNicknameDuplicate(String nickname) {
69-
if (userRepository.existsUserByNickname(nickname)) {
69+
if (userRepository.existsUserByNicknameIgnoreCase(nickname)) {
7070
throw new CustomException(UserErrorCode.NICKNAME_CONFLICT);
7171
}
7272
}

backend/src/main/java/io/f1/backend/domain/user/dao/UserRepository.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,16 @@ public interface UserRepository extends JpaRepository<User, Long> {
1616

1717
Optional<User> findByProviderAndProviderId(String provider, String providerId);
1818

19-
Boolean existsUserByNickname(String nickname);
19+
Boolean existsUserByNicknameIgnoreCase(String nickname);
2020

2121
@Query(
2222
"SELECT new io.f1.backend.domain.admin.dto.UserResponse(u.id, u.nickname, u.lastLogin,"
2323
+ " u.createdAt)FROM User u ORDER BY u.id")
2424
Page<UserResponse> findAllUsersWithPaging(Pageable pageable);
25+
26+
@Query(
27+
"SELECT new io.f1.backend.domain.admin.dto.UserResponse(u.id, u.nickname, u.lastLogin,"
28+
+ " u.createdAt) FROM User u WHERE LOWER(u.nickname) LIKE CONCAT('%',"
29+
+ " LOWER(:nickname), '%')")
30+
Page<UserResponse> findUsersByNicknameContaining(String nickname, Pageable pageable);
2531
}

backend/src/test/java/io/f1/backend/domain/admin/app/AdminServiceTests.java

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.f1.backend.domain.admin.app;
22

3+
import static org.hamcrest.Matchers.hasSize;
34
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
45
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
56
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@@ -35,18 +36,34 @@ void totalUser() throws Exception {
3536
@Test
3637
@DataSet("datasets/admin/sorted-user.yml")
3738
@DisplayName("유저 목록이 id 순으로 정렬되어 반환된다")
38-
void getUsersSortedByLastLogin() throws Exception {
39+
void getUsersSortedByUserId() throws Exception {
3940
// when
4041
ResultActions result = mockMvc.perform(get("/admin/users"));
4142
// then
4243
result.andExpectAll(
4344
status().isOk(),
4445
jsonPath("$.totalElements").value(3),
45-
// 가장 최근 로그인한 USER3이 첫 번째
4646
jsonPath("$.users[0].id").value(1),
47-
// 중간 로그인한 USER2가 두 번째
4847
jsonPath("$.users[1].id").value(2),
49-
// 가장 오래된 로그인한 USER1이 세 번째
48+
jsonPath("$.users[2].id").value(3));
49+
}
50+
51+
@Test
52+
@DataSet("datasets/admin/search-user.yml")
53+
@DisplayName("특정 닉네임이 포함된 유저들의 정보를 조회한다")
54+
void searchUsersByNickname() throws Exception {
55+
// given
56+
String searchNickname = "us";
57+
// when
58+
ResultActions result =
59+
mockMvc.perform(get("/admin/users").param("nickname", searchNickname));
60+
// then
61+
result.andExpectAll(
62+
status().isOk(),
63+
jsonPath("$.totalElements").value(3),
64+
jsonPath("$.users", hasSize(3)),
65+
jsonPath("$.users[0].id").value(1),
66+
jsonPath("$.users[1].id").value(2),
5067
jsonPath("$.users[2].id").value(3));
5168
}
5269
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
user_test:
3+
- id: 1
4+
nickname: "US"
5+
provider: "kakao"
6+
provider_id: "kakao1"
7+
last_login: 2025-07-16 09:00:00
8+
created_at: 2025-07-01 10:00:00
9+
10+
- id: 2
11+
nickname: "USE"
12+
provider: "kakao"
13+
provider_id: "kakao2"
14+
last_login: 2025-07-17 12:00:00
15+
created_at: 2025-07-02 10:00:00
16+
17+
- id: 3
18+
nickname: "USER"
19+
provider: "kakao"
20+
provider_id: "kakao3"
21+
last_login: 2025-07-18 15:00:00
22+
created_at: 2025-07-03 10:00:00

0 commit comments

Comments
 (0)