Skip to content

Conversation

@daye200
Copy link
Collaborator

@daye200 daye200 commented Jun 2, 2025

#106

Summary by CodeRabbit

  • 신규 기능
    • 다양한 검색 유형(이름, 소개, 태그, 전체)에 따라 장소를 키워드로 검색할 수 있는 API가 추가되었습니다.
    • 검색 결과는 페이지네이션(페이지, 크기 지정)과 함께 제공됩니다.
    • 각 장소의 상세 정보(이름, 소개, 주소, 이미지, 태그, 카테고리, 좋아요 수, 조회수 등)가 반환됩니다.

@coderabbitai
Copy link

coderabbitai bot commented Jun 2, 2025

Warning

Rate limit exceeded

@daye200 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 16 minutes and 47 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between dda2329 and 8eadf53.

📒 Files selected for processing (2)
  • src/main/java/jombi/freemates/repository/PlaceRepository.java (1 hunks)
  • src/main/java/jombi/freemates/service/SearchService.java (1 hunks)

"""

Walkthrough

검색 기능을 위한 새로운 REST API 및 서비스 계층이 추가되었습니다. 검색 유형, 키워드, 페이지네이션을 지원하며, 장소 정보를 DTO로 반환합니다. 이를 위해 검색 타입 enum, 장소 DTO, 검색 쿼리 메서드, 서비스와 컨트롤러가 각각 신설되었습니다.

Changes

파일/경로 변경 요약
.../controller/SearchController.java /api/search/place GET 엔드포인트 제공, 검색 서비스 호출 및 결과 반환
.../model/constant/SearchType.java 검색 타입(enum) 정의 및 기본값 반환 static 메서드 추가
.../model/dto/PlaceDto.java 장소 정보를 담는 DTO 클래스 신설
.../repository/PlaceRepository.java 장소명, 소개, 태그, 전체 필드별 검색 쿼리 메서드 4종 및 카테고리, 좌표 검색 메서드 추가
.../service/SearchService.java 검색 요청 처리 서비스 클래스 및 DTO 변환 메서드 추가

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant SearchController
    participant SearchService
    participant PlaceRepository

    Client->>SearchController: GET /api/search/place?type&keyword&page&size
    SearchController->>SearchService: searchPlaces(type, keyword, page, size)
    SearchService->>PlaceRepository: searchByName/searchByIntro/searchByTag/searchAllFields
    PlaceRepository-->>SearchService: Page<Place>
    SearchService-->>SearchController: Page<PlaceDto>
    SearchController-->>Client: ResponseEntity<Page<PlaceDto>>
Loading

Poem

🐰
새로운 검색, 토끼도 신나
이름, 소개, 태그 모두 찾아
페이지 나눠 척척 보여주네
DTO 바구니에 담아 hop hop!
이제 친구들 모여라,
검색도 쉽고 빠르다!
🥕
"""

✨ Finishing Touches
  • 📝 Generate Docstrings

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need 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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions
Copy link

github-actions bot commented Jun 2, 2025

PR 빌드 검증 결과: ✅ 빌드 성공

빌드 검증이 완료되었습니다.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (3)
src/main/java/jombi/freemates/controller/SearchController.java (1)

5-5: 사용하지 않는 import를 제거하세요.

PlaceService를 import했지만 실제로 사용하지 않고 있습니다.

-import jombi.freemates.service.PlaceService;
src/main/java/jombi/freemates/service/SearchService.java (1)

54-54: 주석이 실제 클래스명과 일치하지 않습니다.

주석에서 "PlaceResponse"라고 했지만 실제로는 "PlaceDto"를 사용하고 있습니다.

-    // PlaceResponse는 JSON 응답용 DTO
+    // PlaceDto는 JSON 응답용 DTO
src/main/java/jombi/freemates/repository/PlaceRepository.java (1)

34-40: 전체 필드 검색 메서드 성능 최적화를 고려해보세요.

OR 조건을 사용한 복합 검색이 구현되었지만, 큰 데이터셋에서는 성능 이슈가 발생할 수 있습니다.

성능 개선을 위해 다음을 고려해보세요:

  1. 검색 대상 필드에 인덱스 추가
  2. 풀텍스트 검색 엔진(Elasticsearch 등) 도입 검토
  3. 필요시 UNION을 사용한 쿼리 분리

현재 구현도 기능적으로는 올바르게 동작할 것입니다.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dc125ec and 345e9e8.

📒 Files selected for processing (5)
  • src/main/java/jombi/freemates/controller/SearchController.java (1 hunks)
  • src/main/java/jombi/freemates/model/constant/SearchType.java (1 hunks)
  • src/main/java/jombi/freemates/model/dto/PlaceDto.java (1 hunks)
  • src/main/java/jombi/freemates/repository/PlaceRepository.java (1 hunks)
  • src/main/java/jombi/freemates/service/SearchService.java (1 hunks)
🔇 Additional comments (7)
src/main/java/jombi/freemates/model/constant/SearchType.java (1)

3-12: 검색 타입 enum이 잘 구현되었습니다.

enum 구조가 명확하고 defaultType() 메서드를 통해 기본값을 제공하는 것이 좋은 설계입니다. 각 검색 타입별 주석도 명확합니다.

src/main/java/jombi/freemates/model/dto/PlaceDto.java (1)

13-30: DTO 클래스가 잘 구현되었습니다.

Lombok 어노테이션을 적절히 사용하여 boilerplate 코드를 줄였고, 필드 타입도 적절합니다. 장소 정보를 담기에 충분한 필드들이 포함되어 있습니다.

src/main/java/jombi/freemates/repository/PlaceRepository.java (5)

7-10: Spring Data 임포트가 올바르게 추가되었습니다.

페이지네이션과 쿼리 기능을 위한 필요한 임포트들이 적절히 추가되었습니다.


18-21: 장소명 검색 메서드가 잘 구현되었습니다.

대소문자를 구분하지 않는 부분 문자열 검색이 올바르게 구현되었습니다. JPQL 구문과 파라미터 바인딩이 적절합니다.


23-26: 소개 텍스트 검색 메서드가 적절히 구현되었습니다.

placeName 검색과 동일한 패턴으로 일관성 있게 구현되었습니다.


28-32: 태그 검색 메서드가 올바르게 구현되었습니다.

ElementCollection인 tags를 JOIN하여 검색하고 DISTINCT를 사용해 중복을 제거하는 것이 적절합니다.


18-41: 쿼리 메서드들의 일관성과 구조가 우수합니다.

4개의 검색 메서드가 모두 일관된 패턴으로 구현되어 있고, 각각의 용도가 명확합니다. 페이지네이션 지원도 적절히 포함되었습니다.

Comment on lines +21 to +30
@GetMapping("/place")
public ResponseEntity<Page<PlaceDto>> search(
@RequestParam(value = "type", required = false) SearchType type,
@RequestParam("keyword") String keyword,
@RequestParam(value = "page", defaultValue = "0") int page,
@RequestParam(value = "size", defaultValue = "10") int size
) {
Page<PlaceDto> result = searchService.searchPlaces(type, keyword, page, size);
return ResponseEntity.ok(result);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

매개변수 유효성 검증을 추가하세요.

페이지네이션 매개변수와 키워드에 대한 유효성 검증이 필요합니다. page, size가 음수이거나 keyword가 비어있을 수 있습니다.

  @GetMapping("/place")
  public ResponseEntity<Page<PlaceDto>> search(
      @RequestParam(value = "type", required = false) SearchType type,
-     @RequestParam("keyword") String keyword,
-     @RequestParam(value = "page", defaultValue = "0") int page,
-     @RequestParam(value = "size", defaultValue = "10") int size
+     @RequestParam("keyword") @NotBlank String keyword,
+     @RequestParam(value = "page", defaultValue = "0") @Min(0) int page,
+     @RequestParam(value = "size", defaultValue = "10") @Min(1) @Max(100) int size
  ) {

추가로 import에 validation 어노테이션들을 포함해야 합니다:

+import javax.validation.constraints.Min;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.NotBlank;
📝 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.

Suggested change
@GetMapping("/place")
public ResponseEntity<Page<PlaceDto>> search(
@RequestParam(value = "type", required = false) SearchType type,
@RequestParam("keyword") String keyword,
@RequestParam(value = "page", defaultValue = "0") int page,
@RequestParam(value = "size", defaultValue = "10") int size
) {
Page<PlaceDto> result = searchService.searchPlaces(type, keyword, page, size);
return ResponseEntity.ok(result);
}
// add these imports
import javax.validation.constraints.Min;
import javax.validation.constraints.Max;
import javax.validation.constraints.NotBlank;
@GetMapping("/place")
public ResponseEntity<Page<PlaceDto>> search(
@RequestParam(value = "type", required = false) SearchType type,
@RequestParam("keyword") @NotBlank String keyword,
@RequestParam(value = "page", defaultValue = "0") @Min(0) int page,
@RequestParam(value = "size", defaultValue = "10") @Min(1) @Max(100) int size
) {
Page<PlaceDto> result = searchService.searchPlaces(type, keyword, page, size);
return ResponseEntity.ok(result);
}
🤖 Prompt for AI Agents
In src/main/java/jombi/freemates/controller/SearchController.java around lines
21 to 30, add validation for the request parameters to ensure 'page' and 'size'
are non-negative and 'keyword' is not empty. Use validation annotations like
@Min(0) for 'page' and 'size', and @NotBlank for 'keyword'. Also, import the
necessary validation annotations from javax.validation.constraints. This will
prevent invalid input and improve robustness.

Comment on lines +33 to +51
Page<Place> placePage;
switch (searchType) {
case NAME:
placePage = placeRepository.searchByName(keyword, pageable);
break;
case INTRO:
placePage = placeRepository.searchByIntro(keyword, pageable);
break;
case TAG:
placePage = placeRepository.searchByTag(keyword, pageable);
break;
case ALL:
default:
placePage = placeRepository.searchAllFields(keyword, pageable);
break;
}

return placePage.map(this::toDto);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Repository 메서드 존재 여부를 확인하세요.

서비스에서 호출하는 repository 메서드들(searchByName, searchByIntro, searchByTag, searchAllFields)이 실제로 PlaceRepository에 구현되어 있는지 확인이 필요합니다.


🏁 Script executed:

#!/bin/bash
# Repository 메서드들이 구현되어 있는지 확인
ast-grep --pattern $'interface PlaceRepository {
  $$$
  searchByName($_, $_) {
    $$$
  }
  $$$
}'

ast-grep --pattern $'searchByIntro'
ast-grep --pattern $'searchByTag' 
ast-grep --pattern $'searchAllFields'

Length of output: 1037


PlaceRepository에 searchByName 메서드 누락

서비스에서 호출하는 searchByName 메서드가 아래 리포지토리 인터페이스에 정의되어 있지 않습니다. 구현을 추가해주세요:

• 파일: src/main/java/jombi/freemates/repository/PlaceRepository.java

// 예시: 이름 검색 메서드 추가
Page<Place> searchByName(@Param("keyword") String keyword, Pageable pageable);
🤖 Prompt for AI Agents
In src/main/java/jombi/freemates/repository/PlaceRepository.java, add the
missing method declarations for searchByName, searchByIntro, searchByTag, and
searchAllFields to match those called in SearchService.java lines 33 to 51.
Define each method to accept a String keyword and Pageable pageable as
parameters and return a Page<Place>. Annotate parameters with @Param("keyword")
as needed. This will ensure the repository interface supports all search methods
used by the service.

Comment on lines 22 to 31
public Page<PlaceDto> searchPlaces(
SearchType searchType,
String keyword,
int page,
int size
) {
if (searchType == null) {
searchType = SearchType.defaultType();
}
Pageable pageable = PageRequest.of(page, size, Sort.by("placeName").ascending());
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

키워드 매개변수에 대한 유효성 검증을 추가하세요.

키워드가 null이거나 빈 문자열일 경우에 대한 처리가 필요합니다. 또한 page, size 매개변수도 음수값일 수 있습니다.

  public Page<PlaceDto> searchPlaces(
      SearchType searchType,
      String keyword,
      int page,
      int size
  ) {
+   if (keyword == null || keyword.trim().isEmpty()) {
+     throw new IllegalArgumentException("검색 키워드는 필수입니다.");
+   }
+   if (page < 0 || size <= 0) {
+     throw new IllegalArgumentException("잘못된 페이지네이션 매개변수입니다.");
+   }
+   
    if (searchType == null) {
      searchType = SearchType.defaultType();
    }
📝 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.

Suggested change
public Page<PlaceDto> searchPlaces(
SearchType searchType,
String keyword,
int page,
int size
) {
if (searchType == null) {
searchType = SearchType.defaultType();
}
Pageable pageable = PageRequest.of(page, size, Sort.by("placeName").ascending());
public Page<PlaceDto> searchPlaces(
SearchType searchType,
String keyword,
int page,
int size
) {
// Validate keyword
if (keyword == null || keyword.trim().isEmpty()) {
throw new IllegalArgumentException("검색 키워드는 필수입니다.");
}
// Validate pagination parameters
if (page < 0 || size <= 0) {
throw new IllegalArgumentException("잘못된 페이지네이션 매개변수입니다.");
}
if (searchType == null) {
searchType = SearchType.defaultType();
}
Pageable pageable = PageRequest.of(page, size, Sort.by("placeName").ascending());
// ...
🤖 Prompt for AI Agents
In src/main/java/jombi/freemates/service/SearchService.java around lines 22 to
31, add validation for the keyword parameter to check if it is null or an empty
string and handle those cases appropriately. Also validate that the page and
size parameters are not negative, and handle invalid values by either setting
defaults or throwing an exception. This ensures the method behaves correctly
with invalid input.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
src/main/java/jombi/freemates/repository/PlaceRepository.java (2)

21-42: 검색 성능 최적화를 위한 데이터베이스 인덱스 고려가 필요합니다.

검색 쿼리들이 placeName, introText, tags 필드에서 LIKE 연산을 수행하므로, 성능 향상을 위해 해당 필드들에 인덱스 생성을 고려해보세요. 특히 전체 검색(searchAllFields)의 경우 복합 쿼리이므로 성능 테스트를 권장합니다.


47-47: 좌표 검색 메서드의 데이터 타입 개선을 고려해보세요.

x, y 좌표를 String으로 받고 있는데, 좌표 데이터의 특성상 Double이나 BigDecimal 타입이 더 적절할 수 있습니다. 또한 좌표 범위 검색이나 거리 기반 검색도 향후 필요할 수 있습니다.

좌표 타입을 개선하려면 다음과 같이 변경할 수 있습니다:

-Optional<Place> findByXAndY(String x, String y);
+Optional<Place> findByXAndY(Double x, Double y);
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 345e9e8 and dda2329.

📒 Files selected for processing (2)
  • src/main/java/jombi/freemates/repository/PlaceRepository.java (1 hunks)
  • src/main/java/jombi/freemates/service/SearchService.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/jombi/freemates/service/SearchService.java
🔇 Additional comments (6)
src/main/java/jombi/freemates/repository/PlaceRepository.java (6)

12-12: 올바른 @param 임포트가 적용되었습니다.

이전 리뷰에서 지적된 잘못된 lettuce core @param 임포트 문제가 올바르게 수정되어 Spring Data의 @param 어노테이션을 사용하고 있습니다.


21-23: 장소명 검색 메서드가 잘 구현되었습니다.

JPQL 쿼리가 올바르게 작성되었으며, 대소문자 구분 없는 검색과 매개변수 바인딩이 적절히 적용되었습니다.


26-28: 소개글 검색 메서드가 잘 구현되었습니다.

searchByName과 일관된 패턴으로 구현되어 있어 코드의 일관성이 좋습니다.


31-34: 태그 검색 메서드에서 DISTINCT 사용이 적절합니다.

ElementCollection인 tags를 검색할 때 DISTINCT를 사용하여 중복 결과를 방지한 것이 올바른 접근입니다.


37-42: 전체 필드 검색에서 LEFT JOIN 사용이 적절합니다.

태그가 없는 장소도 검색 결과에 포함시키기 위해 LEFT JOIN을 사용한 것이 올바른 설계입니다. OR 조건과 DISTINCT 사용도 적절합니다.


45-45: 카테고리별 검색 메서드가 간결하게 잘 구현되었습니다.

Spring Data JPA의 메서드 명명 규칙을 올바르게 사용하여 간단하고 명확한 구현입니다.

@github-actions
Copy link

github-actions bot commented Jun 4, 2025

PR 빌드 검증 결과: ✅ 빌드 성공

빌드 검증이 완료되었습니다.

@daye200 daye200 merged commit 87d8233 into main Jun 4, 2025
2 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Jun 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants