Skip to content

[feat] 웨이블존 추천, 검색 응답 필드에 장애 시설 정보 추가#65

Closed
KiSeungMin wants to merge 18 commits into
developfrom
feature/seungmin
Closed

[feat] 웨이블존 추천, 검색 응답 필드에 장애 시설 정보 추가#65
KiSeungMin wants to merge 18 commits into
developfrom
feature/seungmin

Conversation

@KiSeungMin

@KiSeungMin KiSeungMin commented Jul 21, 2025

Copy link
Copy Markdown
Member

✔️ 연관 이슈

📝 작업 내용

  • 웨이블존 추천, 검색 응답 필드에 장애 시설 정보를 추가했습니다.

    • 테스트 코드를 통해 잘 반환하는 것을 확인했습니다.
  • JWT 추가로 테스트 코드 api 요청 과정에서 문제가 발생해, 해당 오류를 해결했습니다

  • 지도 기반 검색 기능의 엔드포인트를 /search/maps로 변경했습니다.

    • 향후 추가될 XX동 주변 TOP3 가게 조회 기능과 엔드포인트를 분리하기 위해 이렇게 변경했습니다.

스크린샷 (선택)

Summary by CodeRabbit

  • 신규 기능

    • 시설 정보(경사로, 문턱 없음, 엘리베이터, 테이블 좌석, 장애인 화장실, 층 정보)가 검색, 추천 및 지역별 인기 순위 결과에 포함되어 노출됩니다.
    • 특정 지역 내 방문자 수 기준 상위 3개 Wayble Zone 정보를 조회하는 기능이 추가되었습니다.
  • 버그 수정

    • 추천 및 검색 API의 엔드포인트가 /maps로 변경되어 접근 경로가 수정되었습니다.
  • 테스트

    • 통합 테스트에 JWT 인증 및 시설 정보 검증이 추가되어, 보다 실제 환경과 유사하게 동작합니다.
  • 기타

    • AWS SDK 관련 의존성이 추가되었습니다.
    • 일부 내부 메서드 접근 제어가 강화되었습니다.
    • 도커 및 CI/CD 환경이 개선되어 Elasticsearch와 연동된 멀티 컨테이너 구성 및 테스트 자동화가 도입되었습니다.

@KiSeungMin KiSeungMin self-assigned this Jul 21, 2025
@KiSeungMin KiSeungMin added the 💡 feature 기능 구현 및 개발 label Jul 21, 2025
@coderabbitai

coderabbitai Bot commented Jul 21, 2025

Copy link
Copy Markdown

"""

Walkthrough

웨이블존 추천 및 검색 응답에 장애 시설 정보가 통합되었습니다. 이를 위해 도메인, DTO, Elasticsearch 매핑, 컨트롤러, 서비스, 테스트 코드 등 여러 계층에 시설 관련 필드와 객체가 추가 및 확장되었습니다. 또한, 테스트에서는 JWT 인증과 시설 정보 검증이 강화되었습니다.

Changes

파일/경로 그룹 변경 요약
build.gradle AWS SDK core 및 S3 라이브러리 의존성 추가(중복 추가됨)
.../BaseEntity.java restore() 메서드 추가(soft delete 복원용)
.../WaybleZoneSearchController.java GET 엔드포인트 경로 "" → "/maps"로 변경
.../explore/dto/FacilityResponseDto.java 장애 시설 정보용 DTO 레코드 및 static factory 메서드 신설
.../explore/dto/recommend/WaybleZoneRecommendResponseDto.java
.../explore/dto/search/WaybleZoneSearchResponseDto.java
facility 필드 및 factory 메서드 내 facility 매핑 추가
.../explore/dto/search/WaybleZoneDocumentRegisterDto.java facility 필드 추가 및 import 보강
.../explore/entity/EsWaybleZoneFacility.java 시설 정보용 엔티티 클래스 및 from() factory 메서드 신설
.../explore/entity/WaybleZoneDocument.java facility 필드(EsWaybleZoneFacility) 추가, factory 메서드에서 facility 매핑, thumbnailImageUrl 조건부 변경
.../explore/repository/recommend/WaybleZoneQueryRecommendRepository.java recommend DTO 생성 시 facility 매핑 추가
.../explore/service/WaybleZoneRecommendService.java recommend 관련 메서드 3개 public → private 변경
.../user/repository/UserRepository.java JPA Query, Param import 추가(실질적 로직 변화 없음)
.../wayblezone/controller/WaybleZoneController.java 방문 로그 저장 시 SecurityContext에서 userId 추출 및 전달
.../resources/elasticsearch/settings/wayble_zone_mappings.json facility 오브젝트 필드 및 하위 속성들(불리언, keyword) 매핑 추가
.../test/java/com/wayble/server/explore/WaybleZoneRecommendApiIntegrationTest.java
.../WaybleZoneSearchApiIntegrationTest.java
JWT 인증 적용, 시설 정보 생성 및 응답 검증, 테스트 데이터 세분화/최적화, 콘솔 출력 및 assertion 보강
.github/workflows/cd-develop.yml Elasticsearch 컨테이너 추가 및 네트워크 구성, 상태 체크 로직 추가
.github/workflows/test-elasticsearch.yml 신규 CI/CD 워크플로우 추가: Docker 이미지 빌드, EC2 테스트 환경에서 Elasticsearch 및 앱 컨테이너 실행, 헬스체크, Discord 알림
docker-compose.yml app, elasticsearch 서비스 및 네트워크/볼륨 정의 추가
docker-compose.test.yml 테스트용 app, elasticsearch 서비스 및 네트워크/볼륨 정의 추가
.../explore/dto/search/WaybleZoneDistrictResponseDto.java 신규 레코드 추가: WaybleZoneDistrictResponseDto 및 from() 메서드
.../explore/repository/search/WaybleZoneQuerySearchRepository.java 신규 메서드 추가: 특정 구역 내 방문수 상위 3개 웨이블존 조회 기능 구현

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Controller
    participant Service
    participant Repository
    participant ES as Elasticsearch

    Client->>Controller: GET /explore/maps (with JWT)
    Controller->>Service: findByCondition(...)
    Service->>Repository: search(...)
    Repository->>ES: Query with facility fields
    ES-->>Repository: Documents with facility data
    Repository-->>Service: List<WaybleZoneDocument>
    Service-->>Controller: List<WaybleZoneSearchResponseDto> (facility 포함)
    Controller-->>Client: 응답 (facility 정보 포함)
Loading

Estimated code review effort

4 (~75분)

Possibly related PRs

Suggested labels

🤔 test, 🛠️ fix

Suggested reviewers

  • seung-in-Yoo
  • hyoinYang

Poem

🐇
장애 시설 정보 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.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (6)
src/main/java/com/wayble/server/explore/repository/recommend/WaybleZoneQueryRecommendRepository.java (1)

142-142: 시설 정보 추가가 올바르게 구현되었습니다.

WaybleZoneRecommendResponseDto에 시설 정보를 포함하는 로직이 적절히 구현되었습니다. FacilityResponseDto.from() 메서드를 사용하여 엔티티를 응답 DTO로 변환하는 방식도 일관성 있게 적용되었습니다.

가독성 향상을 위해 전체 패키지명 대신 import 구문 사용을 고려해보세요:

+import com.wayble.server.explore.dto.FacilityResponseDto;

-                            .facility(com.wayble.server.explore.dto.FacilityResponseDto.from(zone.getFacility()))
+                            .facility(FacilityResponseDto.from(zone.getFacility()))
src/main/java/com/wayble/server/explore/entity/EsWaybleZoneFacility.java (1)

20-33: null 처리 방식 개선 고려

현재 facility가 null일 때 null을 반환하고 있는데, 이는 null 값이 전파될 수 있습니다. 기본값을 가진 객체를 반환하는 것을 고려해보세요.

  public static EsWaybleZoneFacility from(WaybleZoneFacility facility) {
      if (facility == null) {
-         return null;
+         return EsWaybleZoneFacility.builder()
+                 .hasSlope(false)
+                 .hasNoDoorStep(false)
+                 .hasElevator(false)
+                 .hasTableSeat(false)
+                 .hasDisabledToilet(false)
+                 .floorInfo("")
+                 .build();
      }
src/main/java/com/wayble/server/explore/dto/FacilityResponseDto.java (1)

15-28: getter 메서드 네이밍 확인 필요

facility.isHasSlope() 같은 getter 호출이 다소 어색합니다. EsWaybleZoneFacility 엔티티의 boolean 필드 getter가 isHasSlope() 형태로 생성되는 것 같은데, 일반적으로 boolean 필드의 getter는 hasSlope() 또는 isSlope() 형태가 더 자연스럽습니다.

엔티티 클래스의 필드명이나 getter 생성 방식을 확인해보시기 바랍니다.

src/main/java/com/wayble/server/explore/entity/WaybleZoneDocument.java (1)

48-48: TODO 주석 처리 필요

이미지 경로 관련 TODO가 남아있습니다. 이미지 URL 처리 로직이 완성되었다면 TODO를 제거하거나, 추가 작업이 필요하다면 구체적인 내용으로 업데이트해주세요.

이미지 경로 처리와 관련된 추가 구현이 필요하신가요? 새로운 이슈를 생성해드릴까요?

src/test/java/com/wayble/server/explore/WaybleZoneSearchApiIntegrationTest.java (2)

410-434: 테스트 간 코드 중복

generateRandomBirthDate()createRandomFacility() 메서드가 WaybleZoneRecommendApiIntegrationTest와 동일합니다.

공통 테스트 유틸리티 클래스로 추출하여 코드 중복을 제거하는 것을 고려해보세요.

+// 새로운 테스트 유틸리티 클래스 생성
+public class WaybleZoneTestUtils {
+    public static LocalDate generateRandomBirthDate() {
+        // 현재 구현 이동
+    }
+    
+    public static WaybleZoneFacility createRandomFacility(int seed) {
+        // 현재 구현 이동
+    }
+}

94-94: 테스트 데이터 샘플 크기 불일치

추천 API 테스트는 100개, 검색 API 테스트는 1000개의 샘플을 사용합니다. 테스트 일관성을 위해 동일한 크기를 사용하거나, 차이가 있는 이유를 문서화하는 것이 좋겠습니다.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dd2c179 and 8b70d24.

📒 Files selected for processing (16)
  • build.gradle (1 hunks)
  • src/main/java/com/wayble/server/common/entity/BaseEntity.java (1 hunks)
  • src/main/java/com/wayble/server/explore/controller/WaybleZoneSearchController.java (1 hunks)
  • src/main/java/com/wayble/server/explore/dto/FacilityResponseDto.java (1 hunks)
  • src/main/java/com/wayble/server/explore/dto/recommend/WaybleZoneRecommendResponseDto.java (3 hunks)
  • src/main/java/com/wayble/server/explore/dto/search/WaybleZoneDocumentRegisterDto.java (2 hunks)
  • src/main/java/com/wayble/server/explore/dto/search/WaybleZoneSearchResponseDto.java (3 hunks)
  • src/main/java/com/wayble/server/explore/entity/EsWaybleZoneFacility.java (1 hunks)
  • src/main/java/com/wayble/server/explore/entity/WaybleZoneDocument.java (3 hunks)
  • src/main/java/com/wayble/server/explore/repository/recommend/WaybleZoneQueryRecommendRepository.java (1 hunks)
  • src/main/java/com/wayble/server/explore/service/WaybleZoneRecommendService.java (3 hunks)
  • src/main/java/com/wayble/server/user/repository/UserRepository.java (1 hunks)
  • src/main/java/com/wayble/server/wayblezone/controller/WaybleZoneController.java (2 hunks)
  • src/main/resources/elasticsearch/settings/wayble_zone_mappings.json (1 hunks)
  • src/test/java/com/wayble/server/explore/WaybleZoneRecommendApiIntegrationTest.java (12 hunks)
  • src/test/java/com/wayble/server/explore/WaybleZoneSearchApiIntegrationTest.java (11 hunks)
🧰 Additional context used
🧠 Learnings (3)
src/main/java/com/wayble/server/user/repository/UserRepository.java (1)

Learnt from: seung-in-Yoo
PR: #37
File: src/main/java/com/wayble/server/user/entity/User.java:61-62
Timestamp: 2025-07-13T15:08:59.318Z
Learning: Java에서 같은 패키지 내의 클래스들은 import 구문 없이 서로를 참조할 수 있다. com.wayble.server.user.entity 패키지 내의 클래스들은 명시적인 import 없이 사용 가능하다.

src/test/java/com/wayble/server/explore/WaybleZoneRecommendApiIntegrationTest.java (1)

Learnt from: seung-in-Yoo
PR: #37
File: src/main/java/com/wayble/server/user/entity/User.java:61-62
Timestamp: 2025-07-13T15:08:59.318Z
Learning: Java에서 같은 패키지 내의 클래스들은 import 구문 없이 서로를 참조할 수 있다. com.wayble.server.user.entity 패키지 내의 클래스들은 명시적인 import 없이 사용 가능하다.

src/test/java/com/wayble/server/explore/WaybleZoneSearchApiIntegrationTest.java (1)

Learnt from: seung-in-Yoo
PR: #37
File: src/main/java/com/wayble/server/user/entity/User.java:61-62
Timestamp: 2025-07-13T15:08:59.318Z
Learning: Java에서 같은 패키지 내의 클래스들은 import 구문 없이 서로를 참조할 수 있다. com.wayble.server.user.entity 패키지 내의 클래스들은 명시적인 import 없이 사용 가능하다.

⏰ 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: run-docker-image-on-ec2
🔇 Additional comments (14)
src/main/java/com/wayble/server/common/entity/BaseEntity.java (1)

27-29: 소프트 삭제 복구 기능이 올바르게 구현되었습니다.

restore() 메서드는 deletedAt 필드를 null로 설정하여 소프트 삭제된 엔터티를 복구하는 기능을 제공합니다. 구현이 간단하고 명확하며, 기존의 소프트 삭제 패턴과 잘 어울립니다.

src/main/java/com/wayble/server/explore/dto/search/WaybleZoneDocumentRegisterDto.java (1)

4-4: 시설 정보 필드 추가가 깔끔하게 구현되었습니다.

WaybleZoneDocumentRegisterDtofacility 필드와 해당 import가 올바르게 추가되었습니다. Record 클래스의 간결한 구조를 유지하면서 새로운 시설 정보를 적절히 통합했습니다.

Also applies to: 15-15

src/main/resources/elasticsearch/settings/wayble_zone_mappings.json (1)

11-33: Elasticsearch 매핑 구조가 적절하게 설계됨

새로 추가된 facility 객체 매핑이 잘 구성되어 있습니다:

  • 장애 시설 관련 boolean 필드들이 적절하게 정의됨
  • floorInfo에 대한 keyword 타입 사용이 정확함
  • 필드명이 일관성 있고 설명적임
  • Java 엔티티 구조와 잘 일치함
src/main/java/com/wayble/server/explore/dto/search/WaybleZoneSearchResponseDto.java (2)

28-31: DTO 구조 확장이 올바르게 구현됨

검색 응답에 시설 정보가 적절하게 통합되었습니다. 필드 추가와 매핑 로직이 일관성 있게 구현되어 있습니다.


43-43: 팩토리 메서드 업데이트가 적절함

FacilityResponseDto.from()을 사용한 시설 정보 변환이 올바르게 구현되었습니다.

src/main/java/com/wayble/server/explore/dto/recommend/WaybleZoneRecommendResponseDto.java (2)

27-27: 추천 응답 DTO에 시설 정보 통합 완료

추천 응답에도 시설 정보가 일관성 있게 추가되어 검색 응답과 동일한 구조를 유지하고 있습니다.


48-48: 팩토리 메서드 업데이트 적절

시설 정보 변환 로직이 올바르게 구현되어 있습니다.

src/main/java/com/wayble/server/explore/entity/EsWaybleZoneFacility.java (1)

6-18: 엔티티 설계가 잘 구현됨

새로운 EsWaybleZoneFacility 엔티티가 적절하게 설계되었습니다:

  • 접근성 관련 boolean 필드들이 명확하게 정의됨
  • Lombok 어노테이션 사용이 적절함
  • 필드명이 일관성 있고 설명적임
  • 접근 제어자가 적절하게 설정됨
src/main/java/com/wayble/server/explore/service/WaybleZoneRecommendService.java (1)

60-60: 접근 제한자 변경이 적절합니다

내부에서만 사용되는 메서드들을 private으로 변경한 것은 캡슐화 원칙에 부합합니다.

Also applies to: 75-75, 91-91

src/test/java/com/wayble/server/explore/WaybleZoneRecommendApiIntegrationTest.java (3)

78-78: 테스트 데이터 샘플 크기 감소

샘플 크기가 1000에서 100으로 줄어들었습니다. 성능 개선을 위한 변경으로 보이지만, 추천 알고리즘의 정확도 테스트에 영향을 줄 수 있습니다. 테스트 커버리지가 충분한지 확인이 필요합니다.


271-277: 시설 정보 검증이 포괄적입니다

모든 시설 관련 필드에 대한 null 체크가 적절히 구현되었습니다.


403-416: 재현 가능한 랜덤 데이터 생성

시드를 사용한 Random 객체로 일관된 테스트 데이터를 생성하는 방식이 좋습니다. 테스트의 재현성을 보장합니다.

src/test/java/com/wayble/server/explore/WaybleZoneSearchApiIntegrationTest.java (2)

147-147: 엔드포인트 경로 변경 확인

/maps 경로로 변경된 것이 PR 목적에 명시된 대로입니다. 향후 특정 지역(XX동) 주변 TOP3 매장 조회 기능과 구분하기 위한 변경으로 이해됩니다.


186-194: 시설 정보 검증 로직이 완벽합니다

검색 결과에 포함된 모든 시설 정보 필드를 빠짐없이 검증하고 있습니다.

Comment thread build.gradle
Comment on lines +38 to +39
implementation 'com.amazonaws:aws-java-sdk-core:1.12.698'
implementation 'com.amazonaws:aws-java-sdk-s3:1.12.698'

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

중복된 AWS SDK 의존성을 제거해주세요.

AWS SDK 의존성이 두 번 선언되어 있습니다:

  • 38-39번째 줄: 첫 번째 선언
  • 48-49번째 줄: 두 번째 선언 (주석과 함께)

이런 중복 선언은 빌드 설정의 혼란을 야기할 수 있습니다.

다음과 같이 중복을 제거해주세요:

 	implementation 'jakarta.servlet:jakarta.servlet-api:6.0.0'
-	implementation 'com.amazonaws:aws-java-sdk-core:1.12.698'
-	implementation 'com.amazonaws:aws-java-sdk-s3:1.12.698'
 	runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
 	runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5'
 
 	runtimeOnly 'com.mysql:mysql-connector-j'
 	compileOnly 'org.projectlombok:lombok'
 	annotationProcessor 'org.projectlombok:lombok'
 
     //AWS S3
 	implementation 'com.amazonaws:aws-java-sdk-core:1.12.698'
 	implementation 'com.amazonaws:aws-java-sdk-s3:1.12.698'

Also applies to: 48-49

🤖 Prompt for AI Agents
In build.gradle around lines 38-39 and 48-49, there are duplicate AWS SDK
dependencies declared for 'aws-java-sdk-core' and 'aws-java-sdk-s3'. Remove the
duplicate declarations on lines 48-49, keeping only one set of these
dependencies to avoid confusion in the build configuration.

private final WaybleZoneSearchService waybleZoneSearchService;

@GetMapping("")
@GetMapping("/maps")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

엔드포인트 경로 변경이 적절하게 구현되었습니다.

검색 API의 경로를 /maps로 변경하여 향후 추가될 TOP3 매장 조회 기능과 분리한 것은 좋은 설계 결정입니다. REST API의 리소스 구조가 더 명확해졌습니다.

기존 클라이언트나 테스트 코드에서 이 엔드포인트를 호출하는 부분이 있는지 확인해주세요:


🏁 Script executed:

#!/bin/bash
# 기존 엔드포인트 경로 사용 확인
echo "=== 테스트 코드에서 기존 경로 사용 확인 ==="
rg -A 3 -B 3 "/api/v1/wayble-zones/search\"" src/test/

echo "=== 전체 프로젝트에서 웨이블존 검색 API 호출 확인 ==="
rg -A 3 -B 3 "wayble-zones/search" --type java

echo "=== 새로운 /maps 경로 사용 확인 ==="
rg -A 3 -B 3 "search/maps" --type java

Length of output: 2563


REST 엔드포인트 경로 변경으로 인한 테스트 수정 필요

컨트롤러에서 엔드포인트를
GET /api/v1/wayble-zones/searchGET /api/v1/wayble-zones/search/maps
로 변경했으므로, 테스트 코드가 여전히 옛 경로를 참조해 실패합니다. 아래 파일을 수정해주세요:

  • src/test/java/com/wayble/server/explore/WaybleZoneSearchApiIntegrationTest.java
    - private static final String baseUrl = "/api/v1/wayble-zones/search";
    + private static final String baseUrl = "/api/v1/wayble-zones/search/maps";

위 수정 외에도 실제 클라이언트 호출이나 다른 테스트에서 구 경로를 참조하는 부분이 없는지 한번 더 검토 부탁드립니다.

🤖 Prompt for AI Agents
In
src/main/java/com/wayble/server/explore/controller/WaybleZoneSearchController.java
at line 24, the REST endpoint path was changed from GET
/api/v1/wayble-zones/search to GET /api/v1/wayble-zones/search/maps. Update all
test cases in
src/test/java/com/wayble/server/explore/WaybleZoneSearchApiIntegrationTest.java
to use the new endpoint path /api/v1/wayble-zones/search/maps. Additionally,
review other client calls and tests to ensure no references remain to the old
endpoint path and update them accordingly.

Comment on lines +6 to +7
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

사용되지 않는 import 구문을 확인해주세요.

현재 코드에서 @Query@Param 어노테이션을 사용하는 메서드가 없습니다. 이 import 구문들이 향후 구현 예정인 기능을 위한 것인지, 아니면 실수로 추가된 것인지 확인이 필요합니다.

다음 스크립트로 이 import들의 실제 사용 여부를 확인해보겠습니다:


🏁 Script executed:

#!/bin/bash
# UserRepository에서 @Query와 @Param 사용 확인
echo "=== UserRepository 파일에서 @Query 사용 확인 ==="
rg "@Query" src/main/java/com/wayble/server/user/repository/UserRepository.java || echo "사용되지 않음"

echo "=== UserRepository 파일에서 @Param 사용 확인 ==="
rg "@Param" src/main/java/com/wayble/server/user/repository/UserRepository.java || echo "사용되지 않음"

echo "=== user 패키지 전체에서 UserRepository의 @Query/@Param 사용 확인 ==="
rg -A 5 -B 2 "(@Query|@Param)" src/main/java/com/wayble/server/user/

Length of output: 2332


불필요한 import 제거 필요
src/main/java/com/wayble/server/user/repository/UserRepository.java 6–7행의
org.springframework.data.jpa.repository.Query
org.springframework.data.repository.query.Param 임포트는 현재 코드 내에서 사용되지 않습니다.

  • 사용되지 않는 import는 코드 가독성을 저해하고 혼동을 줄 수 있으므로 제거를 권장합니다.
  • 만약 향후 쿼리 메서드 구현을 위한 준비라면, TODO 주석 등으로 목적을 명시하거나 실제 구현 시에 import를 추가해주세요.

예시 diff:

- import org.springframework.data.jpa.repository.Query;
- import org.springframework.data.repository.query.Param;
📝 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
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
🤖 Prompt for AI Agents
In src/main/java/com/wayble/server/user/repository/UserRepository.java at lines
6 to 7, remove the unused imports org.springframework.data.jpa.repository.Query
and org.springframework.data.repository.query.Param to improve code clarity. If
these imports are intended for future use, add a TODO comment explaining their
purpose; otherwise, delete them to avoid confusion.

Comment on lines 60 to +62
// TODO: JWT에서 userId 추출해서 상세 조회 기록 남기기
// waybleZoneVisitLogService.saveVisitLog(null, waybleZoneId);
Long userId = (Long) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
waybleZoneVisitLogService.saveVisitLog(userId, waybleZoneId);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

인증 추출에서 안전성 검사 추가 필요

현재 구현에서 SecurityContextHolder.getContext().getAuthentication().getPrincipal()을 직접 Long으로 캐스팅하고 있어 잠재적인 ClassCastException 위험이 있습니다. 또한 인증 객체의 null 체크도 누락되어 있습니다.

다음과 같이 안전한 방식으로 개선하는 것을 권장합니다:

- // TODO: JWT에서 userId 추출해서 상세 조회 기록 남기기
- Long userId = (Long) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
- waybleZoneVisitLogService.saveVisitLog(userId, waybleZoneId);
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+ if (authentication != null && authentication.getPrincipal() instanceof Long userId) {
+     waybleZoneVisitLogService.saveVisitLog(userId, waybleZoneId);
+ }
🤖 Prompt for AI Agents
In
src/main/java/com/wayble/server/wayblezone/controller/WaybleZoneController.java
around lines 60 to 62, the code directly casts the principal from
SecurityContextHolder to Long without null checks or type verification, risking
ClassCastException. To fix this, first check if the Authentication object and
its principal are not null, then verify the principal's type before casting.
Extract the userId safely by handling cases where the principal is not a Long,
and only then call waybleZoneVisitLogService.saveVisitLog with the valid userId.

@KiSeungMin KiSeungMin closed this Jul 21, 2025

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (12)
src/main/java/com/wayble/server/explore/repository/search/WaybleZoneQuerySearchRepository.java (3)

132-152: 메서드명과 실제 구현이 일치하도록 수정하세요.

findTop3WaybleZonesByDistrict라는 메서드명은 특정 district의 상위 3개 zone을 찾는다는 의미를 전달하지만, 실제로는 방문 수 기준 상위 3개를 반환합니다. 메서드명을 더 명확하게 변경하는 것을 제안합니다.

-public List<WaybleZoneDistrictResponseDto> findTop3WaybleZonesByDistrict(String district) {
+public List<WaybleZoneDistrictResponseDto> findTop3WaybleZonesByDistrictOrderByVisitCount(String district) {

237-237: 정렬 로직을 null-safe하게 개선하세요.

visitCount()가 null을 반환할 가능성이 있다면 NullPointerException이 발생할 수 있습니다.

-.sorted((a, b) -> Long.compare(b.visitCount(), a.visitCount())) // 방문 수 내림차순 정렬
+.sorted((a, b) -> {
+    long aCount = a.visitCount() != null ? a.visitCount() : 0L;
+    long bCount = b.visitCount() != null ? b.visitCount() : 0L;
+    return Long.compare(bCount, aCount);
+}) // 방문 수 내림차순 정렬

188-206: 사용하지 않는 메서드를 제거하거나 aggregation 구현으로 대체하세요.

getVisitCountsByZoneIds 메서드를 aggregation으로 개선한다면, 이 메서드는 더 이상 필요하지 않을 수 있습니다.

이 메서드를 제거하고 aggregation 기반 구현으로 대체하는 것을 고려해 주세요.

.github/workflows/cd-develop.yml (2)

94-102: Spring 프로필 환경변수 누락 → 설정값 불일치 가능성
CI 환경에서 develop 프로필을 의도하셨다면 동일 값을 컨테이너에도 주입해 주세요.

 -p 8080:8080 \
+-e "SPRING_PROFILES_ACTIVE=develop" \

59-59: 불필요한 행 끝 공백
YAML lint 경고가 발생합니다. 작은 부분이지만 차후 머지 충돌을 줄이기 위해 정리해 주세요.

docker-compose.yml (2)

30-34: Elasticsearch 실행 시 vm.max_map_count sysctl 미설정
호스트 기본값이 65 535인 경우 ES 부팅 도중 bootstrap checks failed 로 종료됩니다. Compose 레벨에서 설정해 두면 CI, 로컬 모두 안전합니다.

     environment:
       - discovery.type=single-node
       - xpack.security.enabled=false
       - ES_JAVA_OPTS=-Xms512m -Xmx512m
+    sysctls:
+      - vm.max_map_count=262144

46-48: 마지막 줄 개행(Newline at EOF) 누락
일부 도구에서 패치 계산 시 불필요한 노이즈가 생깁니다. 개행을 추가해 주세요.

docker-compose.test.yml (2)

28-31: 테스트용 ES도 동일한 vm.max_map_count 설정 필요
운영‧개발 환경과 동일하게 sysctl 추가를 권장합니다.

       - xpack.security.enabled=false
       - ES_JAVA_OPTS=-Xms512m -Xmx512m
+    sysctls:
+      - vm.max_map_count=262144

42-45: EOF 개행 누락
위 파일과 동일한 사유로 개행을 추가해 주세요.

.github/workflows/test-elasticsearch.yml (3)

17-20: GitHub Actions 버전 업데이트 권장
actions/checkout@v4, actions/setup-java@v4, docker/login-action@v3 가 릴리스돼 있습니다. self-hosted 러너에서도 최신 기능과 버그 픽스를 활용하기 위해 버전을 올려 주세요.

-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4

(다른 액션도 동일)


105-116: 애플리케이션 헬스 체크를 루프 형태로 변경 권장
고정 sleep 30 은 서비스 부팅 시간 변동에 취약합니다. ES 대기 루프와 동일한 패턴을 사용하면 실패율을 낮출 수 있습니다.

-          echo "Waiting for application to start..."
-          sleep 30
+          echo "Waiting for application to start..."
+          for i in {1..30}; do
+            if curl -f http://localhost:8081/actuator/health > /dev/null 2>&1; then
+              echo "Application is healthy!"
+              break
+            fi
+            echo "Waiting... ($i/30)"
+            sleep 10
+          done

59-59: 행 끝 공백 제거
YAML lint 경고가 있으므로 정리하면 좋습니다.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8b70d24 and f40f4fb.

📒 Files selected for processing (6)
  • .github/workflows/cd-develop.yml (1 hunks)
  • .github/workflows/test-elasticsearch.yml (1 hunks)
  • docker-compose.test.yml (1 hunks)
  • docker-compose.yml (1 hunks)
  • src/main/java/com/wayble/server/explore/dto/search/WaybleZoneDistrictResponseDto.java (1 hunks)
  • src/main/java/com/wayble/server/explore/repository/search/WaybleZoneQuerySearchRepository.java (3 hunks)
🧰 Additional context used
🪛 YAMLlint (1.37.1)
.github/workflows/cd-develop.yml

[error] 59-59: trailing spaces

(trailing-spaces)

.github/workflows/test-elasticsearch.yml

[error] 59-59: trailing spaces

(trailing-spaces)


[error] 109-109: trailing spaces

(trailing-spaces)


[error] 117-117: trailing spaces

(trailing-spaces)


[error] 153-153: no new line character at the end of file

(new-line-at-end-of-file)

docker-compose.test.yml

[error] 45-45: no new line character at the end of file

(new-line-at-end-of-file)

docker-compose.yml

[error] 48-48: no new line character at the end of file

(new-line-at-end-of-file)

🪛 actionlint (1.7.7)
.github/workflows/test-elasticsearch.yml

17-17: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


20-20: the runner of "actions/setup-java@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


34-34: the runner of "docker/login-action@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

⏰ 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: test-elasticsearch-on-ec2
🔇 Additional comments (1)
src/main/java/com/wayble/server/explore/repository/search/WaybleZoneQuerySearchRepository.java (1)

162-162: 하드코딩된 제한값 제거 및 설정 가능하도록 개선

district별 zone 개수가 1000개를 초과할 수 있는지 확인 후, 상수나 설정값으로 분리하세요.

확인해야 할 사항:

  • 운영 DB나 샘플 데이터를 조회해 district별 zone 개수가 1000개를 넘는지 검증
  • 실제 최대 값을 기준으로 적절한 디폴트 한도 설정

예시 수정안:

--- a/src/main/java/com/wayble/server/explore/repository/search/WaybleZoneQuerySearchRepository.java
+++ b/src/main/java/com/wayble/server/explore/repository/search/WaybleZoneQuerySearchRepository.java
@@ -1,6 +1,7 @@
 public class WaybleZoneQuerySearchRepository {
+
+    // district당 조회 가능한 최대 zone 수 (설정 파일 또는 환경 변수로 관리 권장)
+    private static final int MAX_ZONES_PER_DISTRICT = 10000;
 
     public List<Zone> findZonesByDistrict(String districtId) {
         NativeQuery searchQuery = NativeQuery.builder()
-            .withQuery(termQuery)
-            .withMaxResults(1000) // district 내 모든 zone 조회
+            .withQuery(termQuery)
+            .withMaxResults(MAX_ZONES_PER_DISTRICT) // district 내 모든 zone 조회
             .build();
         …
     }

Comment on lines +52 to +65
- name: Stop existing containers if any
run: |
CONTAINER_ID=$(sudo docker ps -q --filter "name=github-actions-demo")
if [ ! -z "$CONTAINER_ID" ]; then
sudo docker stop $CONTAINER_ID
# Stop Spring Boot app container
APP_CONTAINER_ID=$(sudo docker ps -q --filter "name=github-actions-demo")
if [ ! -z "$APP_CONTAINER_ID" ]; then
sudo docker stop $APP_CONTAINER_ID
fi

# Stop Elasticsearch container
ES_CONTAINER_ID=$(sudo docker ps -q --filter "name=elasticsearch")
if [ ! -z "$ES_CONTAINER_ID" ]; then
sudo docker stop $ES_CONTAINER_ID
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

컨테이너 stoprm 누락 – 동일한 이름으로 새 컨테이너 실행 시 충돌
docker stop만 호출하면 컨테이너 이름이 여전히 예약돼 있어 이후 docker run --name … 단계에서 Conflict. The container name … is already in use 오류가 발생합니다. docker rm까지 수행해 이름을 해제해 주세요.

-          if [ ! -z "$APP_CONTAINER_ID" ]; then
-            sudo docker stop $APP_CONTAINER_ID
+          if [ ! -z "$APP_CONTAINER_ID" ]; then
+            sudo docker stop $APP_CONTAINER_ID
+            sudo docker rm  $APP_CONTAINER_ID
           fi
…
-          if [ ! -z "$ES_CONTAINER_ID" ]; then
-            sudo docker stop $ES_CONTAINER_ID
+          if [ ! -z "$ES_CONTAINER_ID" ]; then
+            sudo docker stop $ES_CONTAINER_ID
+            sudo docker rm  $ES_CONTAINER_ID
           fi
📝 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
- name: Stop existing containers if any
run: |
CONTAINER_ID=$(sudo docker ps -q --filter "name=github-actions-demo")
if [ ! -z "$CONTAINER_ID" ]; then
sudo docker stop $CONTAINER_ID
# Stop Spring Boot app container
APP_CONTAINER_ID=$(sudo docker ps -q --filter "name=github-actions-demo")
if [ ! -z "$APP_CONTAINER_ID" ]; then
sudo docker stop $APP_CONTAINER_ID
fi
# Stop Elasticsearch container
ES_CONTAINER_ID=$(sudo docker ps -q --filter "name=elasticsearch")
if [ ! -z "$ES_CONTAINER_ID" ]; then
sudo docker stop $ES_CONTAINER_ID
fi
- name: Stop existing containers if any
run: |
# Stop Spring Boot app container
APP_CONTAINER_ID=$(sudo docker ps -q --filter "name=github-actions-demo")
if [ ! -z "$APP_CONTAINER_ID" ]; then
sudo docker stop $APP_CONTAINER_ID
sudo docker rm $APP_CONTAINER_ID
fi
# Stop Elasticsearch container
ES_CONTAINER_ID=$(sudo docker ps -q --filter "name=elasticsearch")
if [ ! -z "$ES_CONTAINER_ID" ]; then
sudo docker stop $ES_CONTAINER_ID
sudo docker rm $ES_CONTAINER_ID
fi
🧰 Tools
🪛 YAMLlint (1.37.1)

[error] 59-59: trailing spaces

(trailing-spaces)

🤖 Prompt for AI Agents
In .github/workflows/cd-develop.yml around lines 52 to 65, after stopping the
containers with `docker stop`, the containers are not removed, causing name
conflicts when creating new containers with the same name. To fix this, add
`docker rm` commands after each `docker stop` to remove the stopped containers
and free up their names for reuse.

Comment on lines +85 to +88
for i in {1..30}; do
if curl -s http://localhost:9200/_health > /dev/null 2>&1; then
echo "Elasticsearch is ready!"
break

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Elasticsearch 헬스 체크 엔드포인트 오류
/_health 엔드포인트는 존재하지 않습니다. 일반적으로 /_cluster/health 또는 _cluster/health?wait_for_status=yellow&timeout=... 를 사용합니다. 현 상태로는 5 분 타임아웃 후 앱 컨테이너가 실행돼도 ES 미기동 상태일 가능성이 큽니다.

-            if curl -s http://localhost:9200/_health > /dev/null 2>&1; then
+            if curl -s http://localhost:9200/_cluster/health > /dev/null 2>&1; then
📝 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
for i in {1..30}; do
if curl -s http://localhost:9200/_health > /dev/null 2>&1; then
echo "Elasticsearch is ready!"
break
for i in {1..30}; do
if curl -s http://localhost:9200/_cluster/health > /dev/null 2>&1; then
echo "Elasticsearch is ready!"
break
🤖 Prompt for AI Agents
In .github/workflows/cd-develop.yml around lines 85 to 88, the curl command
checks Elasticsearch health using a non-existent endpoint /_health. Replace this
with the correct endpoint /_cluster/health or use
/_cluster/health?wait_for_status=yellow&timeout=... to properly verify
Elasticsearch readiness before proceeding.

Comment on lines +21 to +34
public static WaybleZoneDistrictResponseDto from(WaybleZoneDocument document, Long visitCount) {
return WaybleZoneDistrictResponseDto.builder()
.zoneId(document.getZoneId())
.zoneName(document.getZoneName())
.zoneType(document.getZoneType())
.thumbnailImageUrl(document.getThumbnailImageUrl())
.latitude(document.getAddress().getLocation().getLat())
.longitude(document.getAddress().getLocation().getLon())
.averageRating(document.getAverageRating())
.reviewCount(document.getReviewCount())
.facility(FacilityResponseDto.from(document.getFacility()))
.visitCount(visitCount != null ? visitCount : 0L)
.build();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

null 체크를 추가하여 안정성을 향상시키세요.

from 메서드에서 잠재적인 NullPointerException이 발생할 수 있습니다. 다음 상황을 고려해 주세요:

  • document 파라미터가 null인 경우
  • document.getAddress() 또는 document.getAddress().getLocation()이 null인 경우
  • document.getFacility()가 null인 경우

다음과 같이 null 체크를 추가하는 것을 제안합니다:

 public static WaybleZoneDistrictResponseDto from(WaybleZoneDocument document, Long visitCount) {
+    if (document == null) {
+        throw new IllegalArgumentException("WaybleZoneDocument cannot be null");
+    }
+    
+    Double latitude = null;
+    Double longitude = null;
+    if (document.getAddress() != null && document.getAddress().getLocation() != null) {
+        latitude = document.getAddress().getLocation().getLat();
+        longitude = document.getAddress().getLocation().getLon();
+    }
+    
     return WaybleZoneDistrictResponseDto.builder()
             .zoneId(document.getZoneId())
             .zoneName(document.getZoneName())
             .zoneType(document.getZoneType())
             .thumbnailImageUrl(document.getThumbnailImageUrl())
-            .latitude(document.getAddress().getLocation().getLat())
-            .longitude(document.getAddress().getLocation().getLon())
+            .latitude(latitude)
+            .longitude(longitude)
             .averageRating(document.getAverageRating())
             .reviewCount(document.getReviewCount())
-            .facility(FacilityResponseDto.from(document.getFacility()))
+            .facility(document.getFacility() != null ? FacilityResponseDto.from(document.getFacility()) : null)
             .visitCount(visitCount != null ? visitCount : 0L)
             .build();
 }
📝 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 static WaybleZoneDistrictResponseDto from(WaybleZoneDocument document, Long visitCount) {
return WaybleZoneDistrictResponseDto.builder()
.zoneId(document.getZoneId())
.zoneName(document.getZoneName())
.zoneType(document.getZoneType())
.thumbnailImageUrl(document.getThumbnailImageUrl())
.latitude(document.getAddress().getLocation().getLat())
.longitude(document.getAddress().getLocation().getLon())
.averageRating(document.getAverageRating())
.reviewCount(document.getReviewCount())
.facility(FacilityResponseDto.from(document.getFacility()))
.visitCount(visitCount != null ? visitCount : 0L)
.build();
}
public static WaybleZoneDistrictResponseDto from(WaybleZoneDocument document, Long visitCount) {
if (document == null) {
throw new IllegalArgumentException("WaybleZoneDocument cannot be null");
}
Double latitude = null;
Double longitude = null;
if (document.getAddress() != null && document.getAddress().getLocation() != null) {
latitude = document.getAddress().getLocation().getLat();
longitude = document.getAddress().getLocation().getLon();
}
return WaybleZoneDistrictResponseDto.builder()
.zoneId(document.getZoneId())
.zoneName(document.getZoneName())
.zoneType(document.getZoneType())
.thumbnailImageUrl(document.getThumbnailImageUrl())
.latitude(latitude)
.longitude(longitude)
.averageRating(document.getAverageRating())
.reviewCount(document.getReviewCount())
.facility(document.getFacility() != null
? FacilityResponseDto.from(document.getFacility())
: null)
.visitCount(visitCount != null ? visitCount : 0L)
.build();
}
🤖 Prompt for AI Agents
In
src/main/java/com/wayble/server/explore/dto/search/WaybleZoneDistrictResponseDto.java
around lines 21 to 34, the from method lacks null checks for the document
parameter and its nested fields, which can cause NullPointerExceptions. Add null
checks to verify if document is null, if document.getAddress() or
document.getAddress().getLocation() are null, and if document.getFacility() is
null before accessing their properties. Provide default values or handle these
null cases gracefully to improve method stability.

Comment on lines +176 to +186
private Map<Long, Long> getVisitCountsByZoneIds(List<Long> zoneIds) {
Map<Long, Long> visitCountMap = new HashMap<>();

// 각 zoneId별로 방문 로그 수를 직접 카운트
for (Long zoneId : zoneIds) {
long count = countVisitLogsByZoneId(zoneId);
visitCountMap.put(zoneId, count);
}

return visitCountMap;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

N+1 쿼리 문제를 해결하여 성능을 개선하세요.

각 zoneId에 대해 개별적으로 쿼리를 실행하는 것은 성능 문제를 야기할 수 있습니다. Elasticsearch의 aggregation 기능을 사용하여 한 번의 쿼리로 모든 zone의 방문 수를 집계하는 것이 더 효율적입니다.

다음과 같이 aggregation을 사용하여 개선할 수 있습니다:

 private Map<Long, Long> getVisitCountsByZoneIds(List<Long> zoneIds) {
-    Map<Long, Long> visitCountMap = new HashMap<>();
-    
-    // 각 zoneId별로 방문 로그 수를 직접 카운트
-    for (Long zoneId : zoneIds) {
-        long count = countVisitLogsByZoneId(zoneId);
-        visitCountMap.put(zoneId, count);
-    }
-
-    return visitCountMap;
+    // Terms aggregation을 사용하여 한 번의 쿼리로 모든 zone의 방문 수 집계
+    Query termsQuery = Query.of(q -> q
+        .terms(t -> t
+            .field("zoneId")
+            .terms(v -> v.value(zoneIds.stream().map(id -> id.toString()).collect(Collectors.toList())))
+        )
+    );
+    
+    // Aggregation 쿼리 구성
+    // 실제 구현은 Elasticsearch aggregation API 사용
+    // 여기서는 의사코드로 표현
+    return executeAggregationQuery(termsQuery);
 }

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In
src/main/java/com/wayble/server/explore/repository/search/WaybleZoneQuerySearchRepository.java
around lines 176 to 186, the current method executes a separate query for each
zoneId causing an N+1 query problem. Refactor this method to use Elasticsearch
aggregation to fetch visit counts for all zoneIds in a single query. Implement a
terms aggregation on zoneId and a count aggregation to retrieve the visit counts
efficiently, then map the results to the visitCountMap to eliminate multiple
queries and improve performance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💡 feature 기능 구현 및 개발

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant