Conversation
…o feat/#70-get-room-member-list # Conflicts: # src/main/java/konkuk/thip/room/adapter/in/web/RoomQueryController.java
|
""" Walkthrough독서메이트(룸) 멤버 목록을 조회하는 새로운 API가 추가되었습니다. 이를 위해 컨트롤러, 서비스, 포트, 어댑터, JPA 레포지토리, DTO 등이 새로 생성되었고, 관련 통합 및 컨트롤러 테스트가 작성되었습니다. 또한 BOOK_NOT_FOUND 오류 코드의 HTTP 상태가 400에서 404로 변경되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant Controller as RoomQueryController
participant Service as RoomGetMemberListService
participant RoomRepo as RoomJpaRepository
participant UserRoomRepo as UserRoomJpaRepository
participant UserRepo as UserJpaRepository
participant FollowingQuery as FollowingQueryPort
Client->>Controller: GET /rooms/{roomId}/users
Controller->>Service: getRoomMemberList(roomId)
Service->>RoomRepo: findById(roomId)
RoomRepo-->>Service: Room
Service->>UserRoomRepo: findByRoom(room)
UserRoomRepo-->>Service: List<UserRoom>
Service->>UserRepo: findByIds(userIds)
UserRepo-->>Service: Map<userId, User>
Service->>FollowingQuery: countByFollowingUserIds(userIds)
FollowingQuery-->>Service: Map<userId, followerCount>
Service-->>Controller: RoomGetMemberListResponse
Controller-->>Client: BaseResponse<RoomGetMemberListResponse>
Assessment against linked issues
Assessment against linked issues: Out-of-scope changes
Suggested reviewers
Possibly related PRs
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
💤 Files with no reviewable changes (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 7
🧹 Nitpick comments (3)
src/main/java/konkuk/thip/user/adapter/out/persistence/FollowingJpaRepository.java (1)
7-7: 메서드명을 더 간결하게 개선할 수 있습니다.
countByFollowingUserJpaEntity_UserId는 너무 길고 복잡합니다. JPA 네이밍 컨벤션을 유지하면서도 더 간결한 이름을 사용할 수 있습니다.- int countByFollowingUserJpaEntity_UserId(Long userId); + int countByFollowingUserId(Long userId);또는
@Query어노테이션을 사용하여 명시적으로 쿼리를 작성하는 것도 고려해볼 수 있습니다.src/main/java/konkuk/thip/room/adapter/in/web/response/RoomGetMemberListResponse.java (1)
12-19: subscriberCount 필드 타입을 검토해보세요.구독자 수는 항상 0 이상의 값이어야 하므로,
int대신 더 명시적인 타입을 고려해볼 수 있습니다.- int subscriberCount + long subscriberCount또는 validation 어노테이션을 추가하여 음수 값을 방지할 수도 있습니다. 하지만 현재 비즈니스 로직상 음수가 나올 가능성이 없다면, 현재 구현도 충분합니다.
src/test/java/konkuk/thip/room/adapter/in/web/RoomGetMemberListControllerTest.java (1)
23-27: 테스트 어노테이션 구성 검토 필요
@SpringBootTest를 사용하면서[단위]테스트라고 명시되어 있는데, 이는 통합 테스트에 가깝습니다. 진정한 단위 테스트를 원한다면@WebMvcTest(RoomQueryController.class)를 사용하고 의존성들을 모킹하는 것을 고려해보세요.-@SpringBootTest -@ActiveProfiles("test") -@AutoConfigureMockMvc(addFilters = false) +@WebMvcTest(RoomQueryController.class) +@ActiveProfiles("test")
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
src/main/java/konkuk/thip/common/exception/code/ErrorCode.java(1 hunks)src/main/java/konkuk/thip/room/adapter/in/web/RoomQueryController.java(3 hunks)src/main/java/konkuk/thip/room/adapter/in/web/response/RoomGetMemberListResponse.java(1 hunks)src/main/java/konkuk/thip/room/application/port/in/RoomGetMemberListUseCase.java(1 hunks)src/main/java/konkuk/thip/room/application/service/RoomGetMemberListService.java(1 hunks)src/main/java/konkuk/thip/user/adapter/out/persistence/FollowingJpaRepository.java(1 hunks)src/main/java/konkuk/thip/user/adapter/out/persistence/FollowingQueryPersistenceAdapter.java(1 hunks)src/main/java/konkuk/thip/user/application/port/out/FollowingQueryPort.java(1 hunks)src/test/java/konkuk/thip/common/util/TestEntityFactory.java(1 hunks)src/test/java/konkuk/thip/room/adapter/in/web/RoomGetMemberListApiTest.java(1 hunks)src/test/java/konkuk/thip/room/adapter/in/web/RoomGetMemberListControllerTest.java(1 hunks)
🧰 Additional context used
🧠 Learnings (5)
src/main/java/konkuk/thip/user/adapter/out/persistence/FollowingQueryPersistenceAdapter.java (1)
Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#43
File: src/main/java/konkuk/thip/book/application/port/out/BookCommandPort.java:0-0
Timestamp: 2025-07-03T03:05:05.031Z
Learning: THIP 프로젝트에서는 CQRS Port 분리 시 다음 컨벤션을 따름: CommandPort에는 findByXXX를 통해 도메인 엔티티를 찾아오는 메서드를 추가하고, QueryPort에는 조회 API의 response에 해당하는 데이터들을 DB로부터 조회하는 메서드를 추가함.
src/main/java/konkuk/thip/room/adapter/in/web/RoomQueryController.java (1)
Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#43
File: src/main/java/konkuk/thip/book/application/port/out/BookCommandPort.java:0-0
Timestamp: 2025-07-03T03:05:05.031Z
Learning: THIP 프로젝트에서는 CQRS Port 분리 시 다음 컨벤션을 따름: CommandPort에는 findByXXX를 통해 도메인 엔티티를 찾아오는 메서드를 추가하고, QueryPort에는 조회 API의 response에 해당하는 데이터들을 DB로부터 조회하는 메서드를 추가함.
src/main/java/konkuk/thip/user/application/port/out/FollowingQueryPort.java (1)
Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#43
File: src/main/java/konkuk/thip/book/application/port/out/BookCommandPort.java:0-0
Timestamp: 2025-07-03T03:05:05.031Z
Learning: THIP 프로젝트에서는 CQRS Port 분리 시 다음 컨벤션을 따름: CommandPort에는 findByXXX를 통해 도메인 엔티티를 찾아오는 메서드를 추가하고, QueryPort에는 조회 API의 response에 해당하는 데이터들을 DB로부터 조회하는 메서드를 추가함.
src/main/java/konkuk/thip/room/application/service/RoomGetMemberListService.java (1)
Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#43
File: src/main/java/konkuk/thip/book/application/port/out/BookCommandPort.java:0-0
Timestamp: 2025-07-03T03:05:05.031Z
Learning: THIP 프로젝트에서는 CQRS Port 분리 시 다음 컨벤션을 따름: CommandPort에는 findByXXX를 통해 도메인 엔티티를 찾아오는 메서드를 추가하고, QueryPort에는 조회 API의 response에 해당하는 데이터들을 DB로부터 조회하는 메서드를 추가함.
src/test/java/konkuk/thip/room/adapter/in/web/RoomGetMemberListControllerTest.java (1)
Learnt from: hd0rable
PR: THIP-TextHip/THIP-Server#57
File: src/test/java/konkuk/thip/room/domain/RoomTest.java:0-0
Timestamp: 2025-07-08T16:30:33.771Z
Learning: Room 도메인에서 startDate는 현재 날짜 이후여야 하는 도메인 규칙이 있어서, 테스트에서 만료된 상태를 시뮬레이션하려면 reflection을 사용해야 한다.
🧬 Code Graph Analysis (1)
src/test/java/konkuk/thip/room/adapter/in/web/RoomGetMemberListApiTest.java (1)
src/test/java/konkuk/thip/common/util/TestEntityFactory.java (1)
TestEntityFactory(14-143)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
🔇 Additional comments (10)
src/main/java/konkuk/thip/common/exception/code/ErrorCode.java (1)
54-54: HTTP 상태 코드 개선이 적절합니다.BOOK_NOT_FOUND 에러에 대해 BAD_REQUEST(400)에서 NOT_FOUND(404)로 변경한 것이 의미적으로 올바릅니다. "존재하지 않는 BOOK"에 대해서는 404가 더 적절하며, 다른 NOT_FOUND 에러들과의 일관성도 유지됩니다.
src/test/java/konkuk/thip/common/util/TestEntityFactory.java (1)
137-142: 테스트 팩토리 메서드 구현이 좋습니다.새로 추가된
createFollowing메서드가 기존 팩토리 메서드들과 일관된 패턴을 따르고 있으며, 파라미터명이 명확하여 가독성이 좋습니다. 팔로잉 관계 테스트 데이터 생성에 유용할 것 같습니다.src/main/java/konkuk/thip/room/application/port/in/RoomGetMemberListUseCase.java (1)
1-7: 유스케이스 인터페이스 설계가 적절합니다.단일 책임 원칙을 잘 따르고 있으며, 메서드 시그니처가 명확합니다. 기존 프로젝트의 유스케이스 패턴과 일관성을 유지하고 있어 좋습니다.
src/main/java/konkuk/thip/room/adapter/in/web/RoomQueryController.java (2)
6-6: 의존성 추가가 적절합니다.새로운 기능을 위한 유스케이스 의존성이 올바르게 추가되었습니다. import문과 필드 주입이 기존 패턴과 일관성을 유지하고 있습니다.
Also applies to: 9-9, 28-28
58-62: REST API 엔드포인트 구현이 우수합니다.독서메이트 조회를 위한 새로운 엔드포인트가 REST 컨벤션을 잘 따르고 있습니다.
/rooms/{roomId}/users경로가 의미적으로 명확하며, 기존 컨트롤러 메서드들과 일관된 패턴을 유지하고 있습니다.src/main/java/konkuk/thip/user/application/port/out/FollowingQueryPort.java (1)
1-6: 쿼리 포트 인터페이스 설계가 우수합니다.CQRS 패턴에 따른 QueryPort 분리가 적절하며, 팔로워 수 조회라는 단일 책임을 명확히 정의하고 있습니다. 메서드명이 직관적이고 반환 타입도 적절합니다. 프로젝트의 포트 컨벤션을 잘 따르고 있습니다.
src/main/java/konkuk/thip/user/adapter/out/persistence/FollowingQueryPersistenceAdapter.java (1)
7-17: LGTM! CQRS 패턴에 맞게 잘 구현되었습니다.FollowingQueryPort를 구현하는 어댑터가 올바르게 작성되었습니다. 학습된 내용에 따르면 THIP 프로젝트에서는 QueryPort에 조회 API의 response에 해당하는 데이터들을 DB로부터 조회하는 메서드를 추가하는 컨벤션을 따르고 있으며, 이 구현체가 그 컨벤션을 잘 따르고 있습니다.
다만 앞에서 제안한 레포지토리 메서드명 변경을 적용한다면, 15번 라인도 함께 수정이 필요합니다.
src/main/java/konkuk/thip/room/application/service/RoomGetMemberListService.java (1)
22-25: CommandPort 사용에 대한 검토가 필요합니다.학습된 내용에 따르면 THIP 프로젝트에서는 CommandPort에 findByXXX 메서드를 추가하고, QueryPort에는 조회 API의 response 데이터를 조회하는 메서드를 추가하는 컨벤션을 따릅니다.
현재 읽기 전용 서비스에서 여러 CommandPort를 사용하고 있는데, 이것이 컨벤션에 맞는지 확인이 필요합니다. 조회 목적이라면 별도의 QueryPort를 만드는 것을 고려해보세요.
src/test/java/konkuk/thip/room/adapter/in/web/RoomGetMemberListApiTest.java (2)
90-98: 팔로잉 관계 설정이 테스트 시나리오를 잘 설명하고 있습니다.복잡한 팔로잉 관계를 명확한 주석과 함께 설정하여 각 사용자별 예상 팔로워 수를 쉽게 이해할 수 있도록 했습니다. 이는 156-172라인의 팔로워 수 검증 테스트와 완벽하게 연결됩니다.
174-188: 엣지 케이스 테스트가 잘 작성되었습니다.팔로워가 없는 사용자에 대한 테스트 케이스를 추가하여
subscriberCount가 0으로 올바르게 처리되는지 확인하고 있습니다. 이는 실제 운영 환경에서 발생할 수 있는 상황을 잘 다루고 있습니다.
src/main/java/konkuk/thip/room/application/service/RoomGetMemberListService.java
Show resolved
Hide resolved
src/test/java/konkuk/thip/room/adapter/in/web/RoomGetMemberListApiTest.java
Show resolved
Hide resolved
src/test/java/konkuk/thip/room/adapter/in/web/RoomGetMemberListControllerTest.java
Show resolved
Hide resolved
src/test/java/konkuk/thip/room/adapter/in/web/RoomGetMemberListControllerTest.java
Show resolved
Hide resolved
src/test/java/konkuk/thip/room/adapter/in/web/RoomGetMemberListControllerTest.java
Outdated
Show resolved
Hide resolved
src/test/java/konkuk/thip/room/adapter/in/web/RoomGetMemberListControllerTest.java
Show resolved
Hide resolved
src/test/java/konkuk/thip/room/adapter/in/web/RoomGetMemberListControllerTest.java
Show resolved
Hide resolved
buzz0331
left a comment
There was a problem hiding this comment.
수고하셨습니다~ 간단한 리뷰 남겼으니 확인부탁드릴게요
src/main/java/konkuk/thip/room/application/service/RoomGetMemberListService.java
Show resolved
Hide resolved
| @Test | ||
| @DisplayName("팔로워(구독자) 수가 올바르게 집계된다.") | ||
| void getRoomMemberList_subscriberCount() throws Exception { | ||
| //given | ||
| Long roomId = room1.getRoomId(); | ||
|
|
||
| //when | ||
| ResultActions result = mockMvc.perform(get("/rooms/{roomId}/users", roomId)); | ||
|
|
||
| //then | ||
| // user1: user3이 팔로우(1명) | ||
| // user2: user1이 팔로우(1명) | ||
| // user3: user1, user2가 팔로우(2명) | ||
| result.andExpect(status().isOk()) | ||
| .andExpect(jsonPath("$.data.userList[?(@.userId==" + user1.getUserId() + ")].subscriberCount").value(contains(1))) | ||
| .andExpect(jsonPath("$.data.userList[?(@.userId==" + user2.getUserId() + ")].subscriberCount").value(contains(1))) | ||
| .andExpect(jsonPath("$.data.userList[?(@.userId==" + user3.getUserId() + ")].subscriberCount").value(contains(2))); | ||
| } |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
src/main/java/konkuk/thip/user/application/port/out/UserCommandPort.java (1)
12-12: batch 조회 메서드 추가가 프로젝트 컨벤션에 맞습니다.Retrieved learnings에 따르면 THIP 프로젝트에서 CommandPort에 findByXXX 메서드를 추가하는 것이 올바른 접근입니다. 하지만 메서드에 대한 문서화와 예외 상황 명시를 고려해보세요.
다음과 같은 JavaDoc 추가를 고려해보세요:
+ /** + * 주어진 사용자 ID 목록으로 사용자들을 조회합니다. + * @param userIds 조회할 사용자 ID 목록 + * @return 사용자 ID를 키로 하고 User 객체를 값으로 하는 맵 + * @throws IllegalArgumentException userIds가 null인 경우 + */ Map<Long, User> findByIds(List<Long> userIds);src/main/java/konkuk/thip/user/adapter/out/persistence/FollowingQueryPersistenceAdapter.java (1)
15-16: 사용하지 않는 FollowingMapper 의존성을 제거하세요.현재 구현에서
FollowingMapper는 주입되지만 사용되지 않습니다. 리포지토리 메서드가 이미 적절한 타입을 반환하므로 매핑이 필요하지 않다면 해당 의존성을 제거하는 것이 좋습니다.- private final FollowingMapper followingMapper;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
src/main/java/konkuk/thip/room/application/service/RoomGetMemberListService.java(1 hunks)src/main/java/konkuk/thip/user/adapter/out/persistence/FollowingJpaRepository.java(1 hunks)src/main/java/konkuk/thip/user/adapter/out/persistence/FollowingQueryPersistenceAdapter.java(1 hunks)src/main/java/konkuk/thip/user/adapter/out/persistence/FollowingQueryRepository.java(1 hunks)src/main/java/konkuk/thip/user/adapter/out/persistence/FollowingQueryRepositoryImpl.java(1 hunks)src/main/java/konkuk/thip/user/adapter/out/persistence/UserCommandPersistenceAdapter.java(2 hunks)src/main/java/konkuk/thip/user/application/port/out/FollowingQueryPort.java(1 hunks)src/main/java/konkuk/thip/user/application/port/out/UserCommandPort.java(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/main/java/konkuk/thip/room/application/service/RoomGetMemberListService.java
🧰 Additional context used
🧠 Learnings (4)
src/main/java/konkuk/thip/user/application/port/out/UserCommandPort.java (1)
Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#43
File: src/main/java/konkuk/thip/book/application/port/out/BookCommandPort.java:0-0
Timestamp: 2025-07-03T03:05:05.031Z
Learning: THIP 프로젝트에서는 CQRS Port 분리 시 다음 컨벤션을 따름: CommandPort에는 findByXXX를 통해 도메인 엔티티를 찾아오는 메서드를 추가하고, QueryPort에는 조회 API의 response에 해당하는 데이터들을 DB로부터 조회하는 메서드를 추가함.
src/main/java/konkuk/thip/user/application/port/out/FollowingQueryPort.java (1)
Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#43
File: src/main/java/konkuk/thip/book/application/port/out/BookCommandPort.java:0-0
Timestamp: 2025-07-03T03:05:05.031Z
Learning: THIP 프로젝트에서는 CQRS Port 분리 시 다음 컨벤션을 따름: CommandPort에는 findByXXX를 통해 도메인 엔티티를 찾아오는 메서드를 추가하고, QueryPort에는 조회 API의 response에 해당하는 데이터들을 DB로부터 조회하는 메서드를 추가함.
src/main/java/konkuk/thip/user/adapter/out/persistence/UserCommandPersistenceAdapter.java (1)
Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#43
File: src/main/java/konkuk/thip/book/application/port/out/BookCommandPort.java:0-0
Timestamp: 2025-07-03T03:05:05.031Z
Learning: THIP 프로젝트에서는 CQRS Port 분리 시 다음 컨벤션을 따름: CommandPort에는 findByXXX를 통해 도메인 엔티티를 찾아오는 메서드를 추가하고, QueryPort에는 조회 API의 response에 해당하는 데이터들을 DB로부터 조회하는 메서드를 추가함.
src/main/java/konkuk/thip/user/adapter/out/persistence/FollowingQueryPersistenceAdapter.java (1)
Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#43
File: src/main/java/konkuk/thip/book/application/port/out/BookCommandPort.java:0-0
Timestamp: 2025-07-03T03:05:05.031Z
Learning: THIP 프로젝트에서는 CQRS Port 분리 시 다음 컨벤션을 따름: CommandPort에는 findByXXX를 통해 도메인 엔티티를 찾아오는 메서드를 추가하고, QueryPort에는 조회 API의 response에 해당하는 데이터들을 DB로부터 조회하는 메서드를 추가함.
🧬 Code Graph Analysis (1)
src/main/java/konkuk/thip/user/adapter/out/persistence/FollowingQueryPersistenceAdapter.java (1)
src/main/java/konkuk/thip/user/adapter/out/persistence/FollowingQueryRepositoryImpl.java (1)
Repository(13-38)
🔇 Additional comments (7)
src/main/java/konkuk/thip/user/application/port/out/UserCommandPort.java (1)
5-6: 새로운 import 문 추가가 적절합니다.batch 조회 기능을 위한 필요한 타입들을 추가하였으며, 코드가 깔끔하게 정리되어 있습니다.
src/main/java/konkuk/thip/user/adapter/out/persistence/UserCommandPersistenceAdapter.java (1)
12-15: 필요한 import 문들이 적절히 추가되었습니다.batch 조회 기능 구현을 위한 필수 클래스들이 모두 포함되어 있습니다.
src/main/java/konkuk/thip/user/adapter/out/persistence/FollowingJpaRepository.java (1)
1-7: LGTM! 표준 JPA 리포지토리 패턴을 올바르게 따르고 있습니다.Spring Data JPA와 커스텀 쿼리 리포지토리를 적절히 결합한 표준적인 구현입니다.
src/main/java/konkuk/thip/user/application/port/out/FollowingQueryPort.java (1)
6-8: LGTM! CQRS QueryPort 컨벤션을 올바르게 따르고 있습니다.검색된 학습 내용에 따르면, 이 프로젝트에서는 QueryPort에 조회 API response에 해당하는 데이터를 DB로부터 조회하는 메서드를 추가하는 컨벤션을 따르고 있으며, 이 구현이 해당 컨벤션에 부합합니다.
src/main/java/konkuk/thip/user/adapter/out/persistence/FollowingQueryRepository.java (1)
6-8: LGTM! 커스텀 쿼리 메서드 분리가 적절합니다.Spring Data JPA의 커스텀 리포지토리 패턴을 올바르게 따르고 있으며, 메서드 시그니처가 포트 인터페이스와 일치합니다.
src/main/java/konkuk/thip/user/adapter/out/persistence/FollowingQueryPersistenceAdapter.java (1)
18-21: LGTM! 포트 구현이 올바르게 리포지토리에 위임하고 있습니다.어댑터가 포트 인터페이스를 적절히 구현하고 있으며, 리포지토리로의 위임도 올바릅니다.
src/main/java/konkuk/thip/user/adapter/out/persistence/FollowingQueryRepositoryImpl.java (1)
19-37: 팔로워 수 0 처리 및 빈 리스트 엣지 케이스 확인 완료
RoomGetMemberListService에서
- 팔로워가 없는 사용자는
subscriberCountMap.getOrDefault(userId, 0)로 0을 반환- 빈
userIds전달 시 빈 컬렉션 반환두 가지 모두 안전하게 처리되고 있으므로 추가 수정은 필요 없습니다.
| @Override | ||
| public Map<Long, User> findByIds(List<Long> userIds) { | ||
| List<UserJpaEntity> entities = userJpaRepository.findAllById(userIds); | ||
| return entities.stream() | ||
| .map(userMapper::toDomainEntity) | ||
| .collect(Collectors.toMap(User::getId, Function.identity())); | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
구현 로직은 올바르나 예외 처리와 입력 검증을 강화해야 합니다.
현재 구현은 기본적인 기능은 수행하지만 몇 가지 중요한 개선사항이 필요합니다:
- 존재하지 않는 사용자 ID에 대한 처리가 없습니다
- null 입력에 대한 검증이 부족합니다
- 빈 리스트 처리에 대한 고려가 필요합니다
다음과 같은 개선된 구현을 제안합니다:
@Override
public Map<Long, User> findByIds(List<Long> userIds) {
+ if (userIds == null || userIds.isEmpty()) {
+ return Map.of();
+ }
+
List<UserJpaEntity> entities = userJpaRepository.findAllById(userIds);
+
+ // 존재하지 않는 사용자 ID 검증 (선택사항)
+ if (entities.size() != userIds.size()) {
+ Set<Long> foundIds = entities.stream()
+ .map(UserJpaEntity::getUserId)
+ .collect(Collectors.toSet());
+ List<Long> missingIds = userIds.stream()
+ .filter(id -> !foundIds.contains(id))
+ .collect(Collectors.toList());
+ // 로깅 또는 예외 처리 고려
+ }
+
return entities.stream()
.map(userMapper::toDomainEntity)
.collect(Collectors.toMap(User::getId, Function.identity()));
}또는 더 간단한 방식으로 null 체크만 추가할 수도 있습니다:
@Override
public Map<Long, User> findByIds(List<Long> userIds) {
+ if (userIds == null || userIds.isEmpty()) {
+ return Map.of();
+ }
+
List<UserJpaEntity> entities = userJpaRepository.findAllById(userIds);
return entities.stream()
.map(userMapper::toDomainEntity)
.collect(Collectors.toMap(User::getId, Function.identity()));
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @Override | |
| public Map<Long, User> findByIds(List<Long> userIds) { | |
| List<UserJpaEntity> entities = userJpaRepository.findAllById(userIds); | |
| return entities.stream() | |
| .map(userMapper::toDomainEntity) | |
| .collect(Collectors.toMap(User::getId, Function.identity())); | |
| } | |
| @Override | |
| public Map<Long, User> findByIds(List<Long> userIds) { | |
| if (userIds == null || userIds.isEmpty()) { | |
| return Map.of(); | |
| } | |
| List<UserJpaEntity> entities = userJpaRepository.findAllById(userIds); | |
| // 존재하지 않는 사용자 ID 검증 (선택사항) | |
| if (entities.size() != userIds.size()) { | |
| Set<Long> foundIds = entities.stream() | |
| .map(UserJpaEntity::getUserId) | |
| .collect(Collectors.toSet()); | |
| List<Long> missingIds = userIds.stream() | |
| .filter(id -> !foundIds.contains(id)) | |
| .collect(Collectors.toList()); | |
| // TODO: 로깅 또는 예외 처리 고려 | |
| } | |
| return entities.stream() | |
| .map(userMapper::toDomainEntity) | |
| .collect(Collectors.toMap(User::getId, Function.identity())); | |
| } |
🤖 Prompt for AI Agents
In
src/main/java/konkuk/thip/user/adapter/out/persistence/UserCommandPersistenceAdapter.java
around lines 46 to 52, the method findByIds lacks input validation and handling
for missing user IDs. Add a null check for the input list userIds to prevent
NullPointerException. Also, handle the case when the input list is empty by
returning an empty map immediately. Additionally, consider how to handle user
IDs that do not exist in the database, such as by returning only found users
without errors or by logging missing IDs. Implement these checks before
processing the list and ensure the method returns a consistent and safe result.
…member-list # Conflicts: # src/main/java/konkuk/thip/room/adapter/in/web/RoomQueryController.java
|
| User user = userCommandPort.findById(memberUserId); | ||
| Long userId = userRoom.getUserId(); | ||
| User user = userMap.get(userId); | ||
| int subscriberCount = subscriberCountMap.getOrDefault(userId, 0); |



#️⃣ 연관된 이슈
📝 작업 내용
📸 스크린샷
💬 리뷰 요구사항
📌 PR 진행 시 이러한 점들을 참고해 주세요
Summary by CodeRabbit
Summary by CodeRabbit
신규 기능
/rooms/{roomId}/users)가 추가되었습니다. 각 멤버의 사용자 ID, 닉네임, 이미지 URL, 별명, 구독자 수를 확인할 수 있습니다.버그 수정
테스트