[feat] 방 검색 api 개발#59
Conversation
|
""" Walkthrough방 검색 API가 새롭게 도입되었습니다. 이를 위해 컨트롤러, 서비스, 포트, 어댑터, 레포지토리, 도메인 객체, 예외 코드, 테스트 등 전 계층에 걸쳐 방 검색 기능을 위한 코드가 추가 및 수정되었습니다. 통합 테스트도 함께 작성되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant Controller as RoomQueryController
participant Service as RoomSearchService
participant Port as RoomQueryPort
participant Adapter as RoomQueryPersistenceAdapter
participant Repo as RoomQueryRepositoryImpl
Client->>Controller: GET /rooms/search?keyword&category&sort&page
Controller->>Service: searchRoom(keyword, category, sort, page)
Service->>Port: searchRoom(keyword, category, pageable)
Port->>Adapter: searchRoom(keyword, category, pageable)
Adapter->>Repo: searchRoom(keyword, category, pageable)
Repo-->>Adapter: Page<RoomSearchResult>
Adapter-->>Port: Page<RoomSearchResult>
Port-->>Service: Page<RoomSearchResult>
Service-->>Controller: RoomSearchResponse
Controller-->>Client: BaseResponse<RoomSearchResponse>
Assessment against linked issues
Suggested labels
Suggested reviewers
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous 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 (8)
src/main/java/konkuk/thip/room/adapter/in/web/RoomQueryController.java (1)
19-19: 필드 순서를 일관되게 유지하세요.새로운 의존성 필드가 기존 필드보다 먼저 선언되었습니다. 코드의 일관성을 위해 필드 순서를 정리해주세요.
+ private final RoomVerifyPasswordUseCase roomVerifyPasswordUseCase; private final RoomSearchUseCase roomSearchUseCase; - private final RoomVerifyPasswordUseCase roomVerifyPasswordUseCase;src/main/java/konkuk/thip/common/util/DateUtilsss.java (1)
9-30: 로직은 올바르지만 매직 스트링을 개선해보세요.날짜 계산 로직은 올바르게 구현되어 있습니다. 하지만
"??"와 같은 매직 스트링 대신 의미있는 상수를 사용하는 것을 고려해보세요.+ private static final String EXPIRED_TIME_DISPLAY = "마감"; + public static String formatAfterTime(LocalDate date) { LocalDateTime now = LocalDateTime.now(); LocalDateTime dateTime = date.atStartOfDay(); Duration d = Duration.between(now, dateTime); if (d.isNegative() || d.isZero()) { - return "??"; + return EXPIRED_TIME_DISPLAY; }src/main/java/konkuk/thip/room/adapter/out/persistence/CategoryName.java (1)
24-31: 예외 메시지를 더 명확하게 개선하세요.
from메서드의 로직은 올바르지만 예외 메시지가 불명확합니다..orElseThrow( - () -> new IllegalArgumentException("현재 카테고리 이름 : " + value) + () -> new IllegalArgumentException("유효하지 않은 카테고리 이름입니다: " + value) );src/main/java/konkuk/thip/room/adapter/out/persistence/RoomSearchSortParam.java (1)
18-26: 예외 메시지를 더 명확하게 개선하세요.
from메서드의 로직은 올바르지만 예외 메시지가 불명확합니다..orElseThrow( - () -> new IllegalArgumentException("현재 정렬 조건 param : " + value) + () -> new IllegalArgumentException("유효하지 않은 정렬 조건입니다: " + value) );src/main/java/konkuk/thip/room/application/service/RoomSearchService.java (1)
77-80: 추천 로직 구현 추적이 필요합니다.TODO 주석으로 추후 구현이 필요함을 명시했습니다. 현재는
Sort.unsorted()로 안전하게 처리되고 있습니다.추천 로직 구현을 위한 이슈를 생성하시겠습니까?
src/test/java/konkuk/thip/room/adapter/in/web/RoomSearchApiTest.java (1)
71-137: 테스트 헬퍼 메서드에 중복 코드가 있습니다.
saveRoom과saveUsersToRoom메서드 모두에서 동일한AliasJpaEntity를 생성하고 있습니다. 별도의 헬퍼 메서드로 추출하면 중복을 제거할 수 있습니다.Alias 생성을 별도 메서드로 추출:
+ private AliasJpaEntity createTestAlias() { + return aliasJpaRepository.save(AliasJpaEntity.builder() + .value("소설-칭호") + .color("blue") + .imageUrl("http://image.url") + .build()); + } private RoomJpaEntity saveRoom(String categoryValue, String bookTitle, String isbn, String roomName, LocalDate startDate, int recruitCount) { - AliasJpaEntity alias = aliasJpaRepository.save(AliasJpaEntity.builder() - .value("소설-칭호") - .color("blue") - .imageUrl("http://image.url") - .build()); + AliasJpaEntity alias = createTestAlias();src/main/java/konkuk/thip/room/adapter/out/persistence/RoomQueryRepositoryImpl.java (2)
36-36: 주석의 오타를 수정해주세요."첵제목" → "책제목"
- // 1. 검색 조건(where) 조립 : 방이름 or 첵제목에 keyword 포함, category 필터 적용, 멤버 모집중인(= 활동 시작전인) 방만 검색 + // 1. 검색 조건(where) 조립 : 방이름 or 책제목에 keyword 포함, category 필터 적용, 멤버 모집중인(= 활동 시작전인) 방만 검색
87-87: 키셋 페이징 도입 검토가 좋은 접근입니다.대량의 데이터에서 오프셋 페이징은 성능 문제를 일으킬 수 있으므로, 키셋 페이징 도입은 좋은 개선 방향입니다.
키셋 페이징 구현을 위한 이슈를 생성하시겠습니까?
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (14)
src/main/java/konkuk/thip/common/exception/code/ErrorCode.java(1 hunks)src/main/java/konkuk/thip/common/util/DateUtilsss.java(1 hunks)src/main/java/konkuk/thip/room/adapter/in/web/RoomQueryController.java(1 hunks)src/main/java/konkuk/thip/room/adapter/in/web/response/RoomSearchResponse.java(1 hunks)src/main/java/konkuk/thip/room/adapter/out/persistence/CategoryName.java(1 hunks)src/main/java/konkuk/thip/room/adapter/out/persistence/RoomJpaRepository.java(1 hunks)src/main/java/konkuk/thip/room/adapter/out/persistence/RoomQueryPersistenceAdapter.java(2 hunks)src/main/java/konkuk/thip/room/adapter/out/persistence/RoomQueryRepository.java(1 hunks)src/main/java/konkuk/thip/room/adapter/out/persistence/RoomQueryRepositoryImpl.java(1 hunks)src/main/java/konkuk/thip/room/adapter/out/persistence/RoomSearchSortParam.java(1 hunks)src/main/java/konkuk/thip/room/application/port/in/RoomSearchUseCase.java(1 hunks)src/main/java/konkuk/thip/room/application/port/out/RoomQueryPort.java(1 hunks)src/main/java/konkuk/thip/room/application/service/RoomSearchService.java(1 hunks)src/test/java/konkuk/thip/room/adapter/in/web/RoomSearchApiTest.java(1 hunks)
🧰 Additional context used
🧠 Learnings (9)
📓 Common learnings
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/out/persistence/RoomQueryRepository.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/out/persistence/RoomQueryPersistenceAdapter.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/test/java/konkuk/thip/room/adapter/in/web/RoomSearchApiTest.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.756Z
Learning: Room 도메인에서 startDate는 현재 날짜 이후여야 하는 도메인 규칙이 있어서, 테스트에서 만료된 상태를 시뮬레이션하려면 reflection을 사용해야 한다.
src/main/java/konkuk/thip/room/application/port/out/RoomQueryPort.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/port/in/RoomSearchUseCase.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/RoomSearchService.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/out/persistence/RoomQueryRepositoryImpl.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/room/adapter/out/persistence/RoomQueryRepositoryImpl.java (2)
src/main/java/konkuk/thip/common/util/DateUtilsss.java (1)
DateUtilsss(7-31)src/main/java/konkuk/thip/room/adapter/out/persistence/RoomQueryPersistenceAdapter.java (1)
Repository(13-29)
⏰ 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 (16)
src/main/java/konkuk/thip/common/exception/code/ErrorCode.java (1)
74-75: 에러 코드 추가가 적절합니다.기존 패턴을 잘 따르고 있으며, 방 검색 정렬 조건 검증을 위한 에러 코드가 적절하게 추가되었습니다. 코드 번호와 메시지도 일관성이 있습니다.
src/main/java/konkuk/thip/room/adapter/out/persistence/RoomJpaRepository.java (1)
8-8: 인터페이스 확장이 적절합니다.JPA 리포지토리에 커스텀 쿼리 기능을 추가하는 표준적인 방법입니다. 기존 메서드는 유지하면서 새로운 검색 기능을 깔끔하게 추가했습니다.
src/main/java/konkuk/thip/room/application/port/out/RoomQueryPort.java (1)
12-12: 메서드 시그니처는 적절합니다.페이지네이션을 지원하는 검색 메서드 시그니처가 적절하게 정의되었습니다. 검색 키워드, 카테고리, 페이지 정보를 받아서 페이지네이션된 결과를 반환하는 구조가 명확합니다.
src/main/java/konkuk/thip/room/adapter/out/persistence/RoomQueryRepository.java (1)
9-9: 인터페이스 선언이 명확합니다.검색 메서드의 시그니처가 명확하고 간결하게 정의되었습니다. QueryDSL 구현체에서 이를 구현할 수 있도록 적절한 인터페이스를 제공하고 있습니다.
src/main/java/konkuk/thip/room/application/port/in/RoomSearchUseCase.java (1)
7-7: UseCase 메서드 시그니처가 적절합니다.검색 파라미터들을 명확하게 정의했으며, 기본 타입을 사용하여 application layer에 적합한 인터페이스를 제공하고 있습니다.
src/main/java/konkuk/thip/room/adapter/out/persistence/RoomQueryPersistenceAdapter.java (2)
3-3: 새로운 임포트 추가가 적절합니다.방 검색 기능을 위한 필요한 의존성들이 올바르게 추가되었습니다.
Also applies to: 7-8
25-28: 메서드 구현이 깔끔합니다.Adapter 패턴에 맞게 repository로 단순 위임하는 구조가 적절합니다.
src/main/java/konkuk/thip/room/adapter/in/web/RoomQueryController.java (2)
4-5: 필요한 임포트가 적절히 추가되었습니다.방 검색 API를 위한 의존성들이 올바르게 임포트되었습니다.
Also applies to: 10-12
21-29: 엔드포인트 구현이 적절하지만 파라미터 검증을 확인하세요.REST API 엔드포인트가 올바르게 구현되었습니다. 하지만
page파라미터에 대한 음수 값이나 잘못된 값에 대한 검증이 Service 계층에서 수행되는지 확인해주세요.src/main/java/konkuk/thip/room/adapter/out/persistence/RoomSearchSortParam.java (1)
14-14: 미완성 기능에 대한 처리를 확인하세요.
RECOMMEND상수가 "개발 미정"으로 표시되어 있는데, 현재 사용되지 않는 상수라면 제거하거나 사용 시 적절한 예외 처리가 필요합니다.src/main/java/konkuk/thip/room/application/service/RoomSearchService.java (3)
28-47: 메서드 구현이 적절합니다!searchRoom 메서드가 명확한 단계별 로직으로 잘 구성되어 있습니다. 페이지 인덱스 변환과 기본값 처리가 안전하게 구현되었습니다.
49-55: 정렬 파라미터 검증 로직이 적절합니다.enum을 활용한 검증과 비즈니스 예외로의 적절한 변환이 구현되었습니다.
57-67: 카테고리 검증 로직이 잘 구현되었습니다.null과 빈 문자열 처리가 적절하며, 일관된 예외 처리 패턴을 사용하고 있습니다.
src/main/java/konkuk/thip/room/adapter/in/web/response/RoomSearchResponse.java (1)
5-22: 응답 DTO 구조가 명확합니다!record를 사용한 불변 DTO 구현이 적절하며, 페이지네이션 정보와 검색 결과가 잘 구성되어 있습니다.
src/test/java/konkuk/thip/room/adapter/in/web/RoomSearchApiTest.java (2)
158-159: 도메인 규칙 위반 가능성을 확인해주세요.
LocalDate.now().minusDays(1)로 과거 날짜를 설정하고 있는데, Room 도메인에 startDate는 현재 날짜 이후여야 한다는 규칙이 있을 수 있습니다. 이 경우 도메인 규칙 위반으로 테스트가 실패할 수 있습니다.만약 도메인 규칙이 있다면, reflection을 사용하여 만료된 상태를 시뮬레이션하는 것을 고려해보세요.
139-366: 테스트 케이스가 포괄적으로 잘 작성되었습니다!키워드, 카테고리, 정렬, 페이지네이션 등 다양한 시나리오를 검증하고 있으며, 특히 방 이름과 책 제목 매칭의 우선순위까지 검증하는 점이 좋습니다.
| @@ -1,7 +1,13 @@ | |||
| package konkuk.thip.room.application.port.out; | |||
|
|
|||
| import konkuk.thip.room.adapter.in.web.response.RoomSearchResponse; | |||
There was a problem hiding this comment.
🛠️ Refactor suggestion
아키텍처 레이어 의존성 검토가 필요합니다.
Port 인터페이스(application layer)에서 web layer의 response DTO를 직접 의존하고 있습니다. Clean Architecture 원칙에 따르면 application layer는 adapter layer에 의존하지 않아야 합니다.
도메인/application layer에서 사용할 별도의 DTO나 도메인 객체를 정의하는 것을 고려해보세요.
🤖 Prompt for AI Agents
In src/main/java/konkuk/thip/room/application/port/out/RoomQueryPort.java at
line 3, the import statement brings in a web layer response DTO into the
application layer port interface, violating Clean Architecture principles. To
fix this, remove the dependency on the web layer DTO by defining a separate DTO
or domain object within the domain or application layer that represents the data
needed. Then update the port interface to use this new internal DTO instead of
the web response class.
| @@ -0,0 +1,10 @@ | |||
| package konkuk.thip.room.adapter.out.persistence; | |||
|
|
|||
| import konkuk.thip.room.adapter.in.web.response.RoomSearchResponse; | |||
There was a problem hiding this comment.
🛠️ Refactor suggestion
레이어 의존성 검토가 필요합니다.
Persistence layer의 인터페이스에서 web layer의 response DTO를 직접 의존하고 있습니다. 이는 레이어 간 의존성을 증가시킬 수 있습니다.
가능하다면 persistence layer에서 사용할 별도의 DTO나 도메인 객체를 정의하는 것을 고려해보세요.
🤖 Prompt for AI Agents
In
src/main/java/konkuk/thip/room/adapter/out/persistence/RoomQueryRepository.java
at line 3, the persistence layer is directly importing a web layer response DTO,
which increases layer dependency. To fix this, remove the import of the web
layer DTO and instead define and use a separate DTO or domain object within the
persistence layer that represents the data needed. This will decouple the
persistence layer from the web layer and maintain proper layer separation.
| @@ -0,0 +1,8 @@ | |||
| package konkuk.thip.room.application.port.in; | |||
|
|
|||
| import konkuk.thip.room.adapter.in.web.response.RoomSearchResponse; | |||
There was a problem hiding this comment.
🛠️ Refactor suggestion
UseCase에서 web layer 의존성 검토가 필요합니다.
Application layer의 UseCase에서 web layer의 response DTO를 직접 의존하고 있습니다. 이는 Clean Architecture의 의존성 규칙을 위반할 수 있습니다.
Application layer에서 사용할 독립적인 DTO나 도메인 객체를 정의하는 것을 고려해보세요.
🤖 Prompt for AI Agents
In src/main/java/konkuk/thip/room/application/port/in/RoomSearchUseCase.java at
line 3, the import of RoomSearchResponse from the web layer creates an unwanted
dependency from the application layer to the web layer, violating Clean
Architecture principles. To fix this, remove the import of the web layer DTO and
define a new independent DTO or domain object within the application layer that
represents the response data. Refactor the UseCase interface and its
implementations to use this new application-layer DTO instead of the web layer
response class.
| import java.time.LocalDate; | ||
| import java.time.LocalDateTime; | ||
|
|
||
| public class DateUtilsss { |
There was a problem hiding this comment.
클래스 이름의 오타를 수정하세요.
클래스 이름에 DateUtilsss라고 되어 있는데, DateUtils로 수정해야 합니다.
-public class DateUtilsss {
+public class DateUtils {📝 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.
| public class DateUtilsss { | |
| -public class DateUtilsss { | |
| +public class DateUtils { |
🤖 Prompt for AI Agents
In src/main/java/konkuk/thip/common/util/DateUtilsss.java at line 7, the class
name is misspelled as DateUtilsss. Rename the class to DateUtils to correct the
typo and ensure consistency with naming conventions.
| SCIENCE_IT("과학/IT"), | ||
| Literature("문학"), | ||
| ART("예술"), | ||
| SOCIAL_SCIENCE("사회과확"), |
There was a problem hiding this comment.
카테고리 이름의 오타를 수정하세요.
"사회과확"이 "사회과학"으로 수정되어야 합니다.
- SOCIAL_SCIENCE("사회과확"),
+ SOCIAL_SCIENCE("사회과학"),🤖 Prompt for AI Agents
In src/main/java/konkuk/thip/room/adapter/out/persistence/CategoryName.java at
line 19, correct the typo in the category name from "사회과확" to "사회과학" by updating
the string literal accordingly.
| private OrderSpecifier<?> toOrderSpecifier(Sort sort, QRoomJpaEntity room, NumberExpression<Long> memberCountExpr) { | ||
| // sort 파라미터가 없으면 기본 마감 임박순 | ||
| if (sort.isUnsorted()) { | ||
| return room.startDate.asc(); | ||
| } | ||
|
|
||
| // 클라이언트가 보낸 첫 번째 sort 키를 꺼냅니다. | ||
| String key = sort.stream().findFirst().get().getProperty(); | ||
|
|
||
| switch (key) { | ||
| case "memberCount": | ||
| // user_rooms 테이블에서 현재 참여자 수 집계 → 내림차순 | ||
| return new OrderSpecifier<>(Order.DESC, memberCountExpr); | ||
| case "deadLine": | ||
| default: | ||
| // deadLine: 마감 임박순 = startDate 빠른 순서대로(오름차순) | ||
| return room.startDate.asc(); | ||
| } | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
정렬 키 추출 시 안전성을 개선해주세요.
findFirst().get() 사용은 NoSuchElementException을 발생시킬 수 있습니다.
private OrderSpecifier<?> toOrderSpecifier(Sort sort, QRoomJpaEntity room, NumberExpression<Long> memberCountExpr) {
// sort 파라미터가 없으면 기본 마감 임박순
if (sort.isUnsorted()) {
return room.startDate.asc();
}
// 클라이언트가 보낸 첫 번째 sort 키를 꺼냅니다.
- String key = sort.stream().findFirst().get().getProperty();
+ String key = sort.stream()
+ .findFirst()
+ .map(Sort.Order::getProperty)
+ .orElse("deadLine");
switch (key) {📝 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.
| private OrderSpecifier<?> toOrderSpecifier(Sort sort, QRoomJpaEntity room, NumberExpression<Long> memberCountExpr) { | |
| // sort 파라미터가 없으면 기본 마감 임박순 | |
| if (sort.isUnsorted()) { | |
| return room.startDate.asc(); | |
| } | |
| // 클라이언트가 보낸 첫 번째 sort 키를 꺼냅니다. | |
| String key = sort.stream().findFirst().get().getProperty(); | |
| switch (key) { | |
| case "memberCount": | |
| // user_rooms 테이블에서 현재 참여자 수 집계 → 내림차순 | |
| return new OrderSpecifier<>(Order.DESC, memberCountExpr); | |
| case "deadLine": | |
| default: | |
| // deadLine: 마감 임박순 = startDate 빠른 순서대로(오름차순) | |
| return room.startDate.asc(); | |
| } | |
| } | |
| private OrderSpecifier<?> toOrderSpecifier(Sort sort, QRoomJpaEntity room, NumberExpression<Long> memberCountExpr) { | |
| // sort 파라미터가 없으면 기본 마감 임박순 | |
| if (sort.isUnsorted()) { | |
| return room.startDate.asc(); | |
| } | |
| // 클라이언트가 보낸 첫 번째 sort 키를 꺼냅니다. | |
| String key = sort.stream() | |
| .findFirst() | |
| .map(Sort.Order::getProperty) | |
| .orElse("deadLine"); | |
| switch (key) { | |
| case "memberCount": | |
| // user_rooms 테이블에서 현재 참여자 수 집계 → 내림차순 | |
| return new OrderSpecifier<>(Order.DESC, memberCountExpr); | |
| case "deadLine": | |
| default: | |
| // deadLine: 마감 임박순 = startDate 빠른 순서대로(오름차순) | |
| return room.startDate.asc(); | |
| } | |
| } |
🤖 Prompt for AI Agents
In
src/main/java/konkuk/thip/room/adapter/out/persistence/RoomQueryRepositoryImpl.java
around lines 121 to 139, the code uses findFirst().get() on the sort stream
which can throw NoSuchElementException if no elements exist. To fix this, safely
check if the first sort key is present using isPresent() or use orElse to
provide a default value before accessing it. This will prevent exceptions when
the sort parameter is empty.
|
hd0rable
left a comment
There was a problem hiding this comment.
수고하셨습니다!! 중요 로직이 누락된것 같아 확인부탁드립니다!
| // 1. validation | ||
| String sortVal = validateSort(sort); | ||
| String categoryVal = validateCategory(category); | ||
|
|
| public Page<RoomSearchResponse.RoomSearchResult> searchRoom(String keyword, String category, Pageable pageable) { | ||
| // 1. 검색 조건(where) 조립 : 방이름 or 첵제목에 keyword 포함, category 필터 적용, 멤버 모집중인(= 활동 시작전인) 방만 검색 | ||
| BooleanBuilder where = new BooleanBuilder(); | ||
| // keyword 필터 (빈 문자열이면 생략) |
There was a problem hiding this comment.
p2: 저희 서비스에서 모임방 검색후 검색어와 일치하는 모임방을 카테고리/정렬 필터에 따른 값으로 보여주는 것으로 알고있는데 이렇게 되면 keyword 필터가 필수이지않을까요..? 현재 구현하신것으로는 키워드가 없으면 키워드 없이 필터나/정렬으로만 결과가 반환되서 전체 책의 정렬 결과가 반환 될 것같은데 키워드포함 정렬결과가 반환되어야할것같습니다..!
|
|
||
| // 3. 방 검색 | ||
| Page<RoomSearchResponse.RoomSearchResult> result = roomQueryPort.searchRoom(keyword, categoryVal, pageable); | ||
|
|
There was a problem hiding this comment.
p2: 유저의 최근 검색어 추가 로직이 누락된것같습니다!



#️⃣ 연관된 이슈
📝 작업 내용
방 검색 api를 개발하였습니다
<방 검색 api 플로우>
📸 스크린샷
💬 리뷰 요구사항
다양한 테스트 케이스를 고려해 '방 검색 api' 통합 테스트 코드를 작성해보았습니다. 테스트 코드를 참고해주시면 QueryDSL 로직이 더 잘 이해되실 것 같습니다!
📌 PR 진행 시 이러한 점들을 참고해 주세요
Summary by CodeRabbit
신규 기능
버그 수정
테스트