Skip to content

Conversation

@hyoinYang
Copy link
Contributor

@hyoinYang hyoinYang commented Aug 14, 2025

✔️ 연관 이슈

📝 작업 내용

현재까지의 진행상황을 main으로 머지

스크린샷 (선택)

Summary by CodeRabbit

  • New Features
    • 경로 검색이 다중 경로를 지원하며, 각 옵션에 경로 인덱스가 포함됩니다.
    • Wayble 존 유효성 검사 엔드포인트 추가: GET /validate
  • Refactor
    • 교통 경로 응답 구조가 단일 단계 목록에서 다중 Route 목록으로 변경되었습니다(각 Route는 Step 목록 포함). Step 정보에 경로명 등 추가 필드가 포함됩니다.
  • Chores
    • Wayble 존 검색에서 반경 최소값 제한이 제거되어 더 작은 반경으로도 조회 가능합니다.
    • 유사 존 매칭 정확도가 향상되었습니다(근접·이름 유사도 기반).

@coderabbitai
Copy link

coderabbitai bot commented Aug 14, 2025

Walkthrough

대중교통 경로 API가 단일 경로에서 다중 경로 반환으로 변경되었고, DTO 구조가 Route 단위로 확장되었습니다. 탐색 도메인에는 유효성 검증용 /validate 엔드포인트와 유사 존 검색(30m 이내) 로직이 추가되었으며, 관련 DTO 유효성 제약이 완화되고 통합 테스트가 추가되었습니다.

Changes

Cohort / File(s) Summary
Transportation DTO & Service (multi-route)
src/main/java/com/wayble/server/direction/dto/response/TransportationResponseDto.java, src/main/java/com/wayble/server/direction/service/TransportationService.java
DTO: routes 타입 List→List, Route 레코드 추가, Step 필드(routeName, moveNumber, busInfo, subwayInfo, from, to) 확장. Service: 다중 경로 생성/정렬/필터링, 엣지 패널티 기반 대안 경로 탐색, 페이징 시 Route 생성.
Explore search validation flow
src/main/java/com/wayble/server/explore/controller/WaybleZoneSearchController.java, src/main/java/com/wayble/server/explore/service/WaybleZoneSearchService.java, src/main/java/com/wayble/server/explore/repository/search/WaybleZoneQuerySearchRepository.java, src/main/java/com/wayble/server/explore/dto/search/request/WaybleZoneSearchConditionDto.java
/validate 엔드포인트 추가. Service에 isValidWaybleZone 위임 메서드 추가. Repository에 이름 유사도+30m 지오필터로 단건 조회 메서드 추가. radiusKm의 @DecimalMin 제거.
Tests
src/test/java/com/wayble/server/explore/WaybleZoneSearchApiIntegrationTest.java
/validate 엔드포인트 통합 테스트 추가(거리/이름 유사도/허버사인 검증 포함).

Sequence Diagram(s)

sequenceDiagram
  actor Client
  participant Controller as Transportation API
  participant Service as TransportationService
  participant Graph as RoutingEngine

  Client->>Controller: GET /transportation/routes
  Controller->>Service: findRoutes(...)
  Service->>Graph: runDijkstra(start, end)
  Graph-->>Service: firstRoute
  Service->>Graph: penalizeUsedEdges(firstRoute)
  Service->>Graph: findAlternativeRoutes(MAX_ROUTES-1)
  Graph-->>Service: alternativeRoutes[]
  Service->>Service: filterAndSortRoutes(routes)
  Service-->>Controller: List<Route> (paged)
  Controller-->>Client: 200 OK (routes)
Loading
sequenceDiagram
  actor Client
  participant C as WaybleZoneSearchController
  participant S as WaybleZoneSearchService
  participant R as WaybleZoneQuerySearchRepository
  participant ES as Elasticsearch

  Client->>C: GET /api/v1/wayble-zones/search/validate?...
  C->>S: isValidWaybleZone(cond)
  S->>R: findSimilarWaybleZone(cond)
  R->>ES: query(name similarity + geo_distance≤30m)
  ES-->>R: top hit or none
  R-->>S: WaybleZoneSearchResponseDto or null
  S-->>C: dto
  C-->>Client: 200 OK (CommonResponse)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Assessment against linked issues

Objective Addressed Explanation
DTO 수정 (#142)
엣지 패널티 적용을 통한 다중 경로 추천 (#142)

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
/validate 엔드포인트 추가 (src/main/java/com/wayble/server/explore/controller/WaybleZoneSearchController.java:L30-L80) 링크된 이슈 #142의 범위(대중교통 다중 경로)와 무관한 탐색 도메인 신규 API입니다.
Service 위임 메서드 isValidWaybleZone 추가 (src/main/java/com/wayble/server/explore/service/WaybleZoneSearchService.java:L25-L40) 이슈 #142와 직접 관련 없는 탐색 서비스 기능 추가입니다.
Repository 메서드 findSimilarWaybleZone 추가 (src/main/java/com/wayble/server/explore/repository/search/WaybleZoneQuerySearchRepository.java:L60-L150) 대중교통 경로와 관련 없는 엘라스틱서치 기반 유사 존 검색 로직입니다.
radiusKm 최소값 검증 제거 (src/main/java/com/wayble/server/explore/dto/search/request/WaybleZoneSearchConditionDto.java:L40) 이슈 #142 요구사항과 무관한 DTO 검증 정책 변경입니다.
/validate 통합 테스트 추가 (src/test/java/com/wayble/server/explore/WaybleZoneSearchApiIntegrationTest.java:L90-L170) 링크된 이슈 범위를 벗어난 탐색 API 테스트입니다.

Possibly related PRs

Suggested labels

💡 feature, 🤔 test

Suggested reviewers

  • zyovn
  • seung-in-Yoo

Poem

당근 들고 춤추는 토끼 한 마리 🥕
한 길만 가던 버스, 이제는 셋, 넷, 다섯 길!
엣지에 살짝 페널티, 새로운 길이 필!
30미터 속삭임, 존의 이름을 맞추고,
길 위에 풍덩 뛰어, 오늘 배포는 스틸!

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch develop

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.
    • 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.
  • 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 the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

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

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • 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.

@hyoinYang hyoinYang self-assigned this Aug 14, 2025
@hyoinYang hyoinYang added the release 프로덕션 서버에 배포 label Aug 14, 2025
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: 10

🔭 Outside diff range comments (1)
src/main/java/com/wayble/server/direction/dto/response/TransportationResponseDto.java (1)

19-28: 조치 필요: Step 레코드의 nullable 필드(null) 생성 및 검증 부족

검색 결과, 서버 코드에서 Step 생성 시 moveInfo/routeName/busInfo/subwayInfo가 null로 전달되는 호출을 확인했으며, busInfo()/subwayInfo()에 대한 명시적 null 검사 패턴은 코드베이스에서 발견되지 않았습니다.

문제가 있을 가능성이 있는 위치:

  • src/main/java/com/wayble/server/direction/service/TransportationService.java
    • mergedSteps.add(new TransportationResponseDto.Step(DirectionType.WALK, null, null, 0, null, null, fromName, toName))
    • mergedSteps.add(new TransportationResponseDto.Step(currentType, moveInfoList, routeName, moveNumber, busInfo, ...))

권장 조치:

  • 서버에서 nullable 컬렉션/문자열은 null 대신 빈 컬렉션/빈 문자열으로 전달하거나 DTO 직렬화 설정(@JsonInclude 등)으로 null을 생략하도록 통일하세요.
  • busInfo/subwayInfo를 사용하는 모든 경로에 대해 null 체크를 추가하거나, 클라이언트에서 null을 안전하게 처리하도록 API 계약과 문서를 명확히 하세요.
  • 클라이언트(UI)가 null 값 표시/대체 로직을 가지고 있는지 검증(또는 단위/통합 테스트 추가)하세요.
🧹 Nitpick comments (7)
src/main/java/com/wayble/server/explore/controller/WaybleZoneSearchController.java (1)

70-76: 핸들러 메서드 명명 개선 제안.

findIsValidWaybleZone는 이중 동사 + boolean 뉘앙스로 가독성이 떨어집니다. validateWaybleZone 또는 findSimilarWaybleZone처럼 역할 중심으로 단순화하는 것을 권장합니다.

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

580-588: 부분 문자열 추출의 안전성 보완.

zoneName 길이가 2 미만인 경우 substring(0, 2)에서 예외가 발생합니다. 현재 데이터셋에서는 대부분 2글자 이상이지만, 회귀 방지를 위해 안전 처리하는 것이 좋습니다.

-        String requestedName = zoneName.substring(0, 2);
+        String requestedName = zoneName.length() >= 2 ? zoneName.substring(0, 2) : zoneName;

553-555: 테스트 로그 과다 출력 줄이기.

테스트에서 매번 pretty print를 출력하면 파이프라인 로그가 과도하게 길어질 수 있습니다. 실패 시에만 진단 정보가 출력되도록 조건부 로깅 또는 assertJ의 withFailMessage 활용으로 노이즈를 줄이는 것을 권장합니다.

src/main/java/com/wayble/server/explore/repository/search/WaybleZoneQuerySearchRepository.java (2)

141-155: 이름 유사도 쿼리 구성 보완 제안.

현재 match + fuzzy + wildcard 조합은 간단하지만, 불필요한 리소스 사용 또는 과/소매칭이 발생할 수 있습니다. 다음을 고려해보세요.

  • dis_max 쿼리로 should 절 묶기(가장 잘 맞는 쿼리의 스코어를 채택하며 tie-breaker로 다른 쿼리 기여 조정).
  • prefix 검색은 match_phrase_prefix가 더 효율적/정확합니다(특히 zoneName 앞부분 검색 시).
  • 30m 필터가 있으므로 점수 정렬 대신 거리 우선 정렬만으로도 충분할 가능성이 큽니다. 점수는 track_scores(true)로만 조회하고 정렬은 거리만 사용하는 방식을 고려.

구현은 선택 사항이지만, 정확도/성능 균형을 위해 재검토를 권장합니다.


132-136: 입력 검증 책임의 일관성.

zoneName이 null/blank일 때 null을 반환하는 대신, 레이어 경계를 명확히 하기 위해 컨트롤러/서비스에서 400/404로 처리하거나 예외를 던지도록 일관화하는 것이 좋습니다(현재 컨트롤러는 @Valid로 DTO 필드 유효성 검증을 수행). 레포지토리 레이어는 검색 책임에 집중하도록 위로 끌어올리는 것을 권장합니다.

src/main/java/com/wayble/server/direction/dto/response/TransportationResponseDto.java (1)

14-17: Route 레코드의 필드명을 더 명확하게 변경하는 것을 고려해보세요

routeIndex라는 필드명이 다소 모호합니다. 이것이 페이징된 결과에서의 순서를 나타내는 것인지, 아니면 전체 경로 목록에서의 인덱스인지 명확하지 않습니다. routeNumber 또는 routeOrder와 같은 더 명확한 이름을 사용하는 것이 좋겠습니다.

 public record Route(
-        Integer routeIndex, // 경로 인덱스
+        Integer routeNumber, // 경로 번호 (1부터 시작)
         List<Step> steps // 해당 경로의 단계들
 ) {}
src/main/java/com/wayble/server/direction/service/TransportationService.java (1)

86-88: createRoute 메서드가 단순한 래퍼 역할만 수행

이 메서드는 단순히 TransportationResponseDto.Route 생성자를 호출하는 것 외에 다른 로직이 없습니다. 이런 단순한 래퍼 메서드는 불필요한 추상화일 수 있습니다.

메서드를 제거하고 직접 생성자를 호출하는 것을 고려해보세요:

-            TransportationResponseDto.Route routeObj = createRoute(route, startIndex + i + 1);
+            TransportationResponseDto.Route routeObj = new TransportationResponseDto.Route(startIndex + i + 1, route);
             routeList.add(routeObj);

-private TransportationResponseDto.Route createRoute(List<TransportationResponseDto.Step> steps, int routeIndex) {
-    return new TransportationResponseDto.Route(routeIndex, steps);
-}
📜 Review details

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

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 54c4e8f and 59c9ff5.

📒 Files selected for processing (7)
  • src/main/java/com/wayble/server/direction/dto/response/TransportationResponseDto.java (1 hunks)
  • src/main/java/com/wayble/server/direction/service/TransportationService.java (5 hunks)
  • src/main/java/com/wayble/server/explore/controller/WaybleZoneSearchController.java (1 hunks)
  • src/main/java/com/wayble/server/explore/dto/search/request/WaybleZoneSearchConditionDto.java (0 hunks)
  • src/main/java/com/wayble/server/explore/repository/search/WaybleZoneQuerySearchRepository.java (1 hunks)
  • src/main/java/com/wayble/server/explore/service/WaybleZoneSearchService.java (1 hunks)
  • src/test/java/com/wayble/server/explore/WaybleZoneSearchApiIntegrationTest.java (1 hunks)
💤 Files with no reviewable changes (1)
  • src/main/java/com/wayble/server/explore/dto/search/request/WaybleZoneSearchConditionDto.java
🧰 Additional context used
🧬 Code Graph Analysis (6)
src/main/java/com/wayble/server/explore/service/WaybleZoneSearchService.java (2)
src/main/java/com/wayble/server/explore/dto/search/request/WaybleZoneSearchConditionDto.java (1)
  • Builder (10-30)
src/main/java/com/wayble/server/wayblezone/service/WaybleZoneService.java (2)
  • zone (33-59)
  • Service (20-126)
src/main/java/com/wayble/server/direction/dto/response/TransportationResponseDto.java (1)
src/main/java/com/wayble/server/direction/entity/transportation/Route.java (1)
  • Entity (9-36)
src/main/java/com/wayble/server/explore/controller/WaybleZoneSearchController.java (2)
src/main/java/com/wayble/server/explore/controller/WaybleFacilitySearchController.java (2)
  • RestController (17-30)
  • GetMapping (24-29)
src/main/java/com/wayble/server/explore/controller/WaybleZoneRecommendController.java (1)
  • RestController (15-37)
src/main/java/com/wayble/server/explore/repository/search/WaybleZoneQuerySearchRepository.java (2)
src/main/java/com/wayble/server/explore/repository/recommend/WaybleZoneQueryRecommendRepository.java (2)
  • Repository (30-163)
  • searchPersonalWaybleZones (48-162)
src/main/java/com/wayble/server/explore/repository/facility/WaybleFacilityQuerySearchRepository.java (1)
  • Repository (20-101)
src/main/java/com/wayble/server/direction/service/TransportationService.java (1)
src/main/java/com/wayble/server/direction/controller/TransportationController.java (2)
  • Operation (25-60)
  • RestController (18-62)
src/test/java/com/wayble/server/explore/WaybleZoneSearchApiIntegrationTest.java (1)
src/test/java/com/wayble/server/explore/WaybleFacilityApiIntegrationTest.java (1)
  • Test (179-235)
🔇 Additional comments (2)
src/main/java/com/wayble/server/direction/service/TransportationService.java (2)

41-41: MAX_ROUTES 상수와 페이지 크기 설정의 일관성 확인 필요

MAX_ROUTES가 5로 설정되어 있는데, Line 63에서 페이지 크기 기본값도 5입니다. 이 두 값이 동일한 것이 의도된 것인지, 아니면 서로 다른 용도인지 명확히 할 필요가 있습니다.


625-627: catch 블록의 잘못된 중괄호 위치

try-catch 블록의 중괄호 구조가 잘못되어 있습니다. Line 625에 불필요한 닫는 중괄호가 있고, catch 블록이 제대로 닫히지 않았습니다.

                     }
-                        } catch (Exception e) {
+                } catch (Exception e) {
                     log.info("버스 정보 조회 실패: {}", e.getMessage());
-        }
+                }

Likely an incorrect or invalid review comment.

Set<Pair<Long, Long>> usedEdges = extractActualEdgesFromRoute(firstRoute, graph);

// 최대 4개의 추가 경로 찾기
for (int i = 0; i < 4 && alternativeRoutes.size() < MAX_ROUTES - 1; i++) {
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

대체 경로 생성 루프의 종료 조건 개선 필요

현재 루프가 4회 고정 반복인데, MAX_ROUTES - 1개의 대체 경로를 찾으면 조기 종료하도록 되어 있습니다. 이는 불필요한 반복을 유발할 수 있습니다.

-        for (int i = 0; i < 4 && alternativeRoutes.size() < MAX_ROUTES - 1; i++) {
+        for (int i = 0; alternativeRoutes.size() < MAX_ROUTES - 1 && i < MAX_ROUTES - 1; i++) {
📝 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 (int i = 0; i < 4 && alternativeRoutes.size() < MAX_ROUTES - 1; i++) {
for (int i = 0; alternativeRoutes.size() < MAX_ROUTES - 1 && i < MAX_ROUTES - 1; i++) {
🤖 Prompt for AI Agents
In src/main/java/com/wayble/server/direction/service/TransportationService.java
around line 183, replace the fixed-count for-loop with a loop that stops
immediately when the desired number of alternative routes is reached: introduce
an attempts counter (e.g., attempts = 0) and use while (alternativeRoutes.size()
< MAX_ROUTES - 1 && attempts < 4) { ...; attempts++; } so the loop checks the
current alternativeRoutes.size() each iteration and exits as soon as MAX_ROUTES
- 1 is met, avoiding unnecessary extra iterations.

Comment on lines +213 to +238
private Set<Pair<Long, Long>> extractActualEdgesFromRoute(List<TransportationResponseDto.Step> route, Map<Long, List<Edge>> graph) {
Set<Pair<Long, Long>> usedEdges = new HashSet<>();

for (TransportationResponseDto.Step step : route) {
String fromName = step.from();
String toName = step.to();

for (Map.Entry<Long, List<Edge>> entry : graph.entrySet()) {
Long nodeId = entry.getKey();
List<Edge> edges = entry.getValue();

for (Edge edge : edges) {
Node fromNode = edge.getStartNode();
Node toNode = edge.getEndNode();

if ((fromNode.getStationName().equals(fromName) && toNode.getStationName().equals(toName)) ||
(fromNode.getStationName().equals(toName) && toNode.getStationName().equals(fromName))) {
usedEdges.add(Pair.of(fromNode.getId(), toNode.getId()));
usedEdges.add(Pair.of(toNode.getId(), fromNode.getId()));
}
}
}
}

return usedEdges;
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

extractActualEdgesFromRoute 메서드의 성능 최적화 필요

이 메서드는 O(n * m * k) 복잡도를 가지고 있습니다 (n: route 크기, m: graph 엔트리 수, k: 각 노드의 엣지 수). 대규모 그래프에서는 성능 문제가 발생할 수 있습니다.

노드 이름을 키로 하는 맵을 미리 구성하여 검색 성능을 개선할 수 있습니다:

 private Set<Pair<Long, Long>> extractActualEdgesFromRoute(List<TransportationResponseDto.Step> route, Map<Long, List<Edge>> graph) {
     Set<Pair<Long, Long>> usedEdges = new HashSet<>();
+    
+    // 노드 이름으로 엣지를 빠르게 찾기 위한 맵 구성
+    Map<String, List<Edge>> edgesByNodeName = new HashMap<>();
+    for (List<Edge> edges : graph.values()) {
+        for (Edge edge : edges) {
+            if (edge.getStartNode() != null) {
+                edgesByNodeName.computeIfAbsent(edge.getStartNode().getStationName(), k -> new ArrayList<>()).add(edge);
+            }
+        }
+    }
     
     for (TransportationResponseDto.Step step : route) {
         String fromName = step.from();
         String toName = step.to();
         
-        for (Map.Entry<Long, List<Edge>> entry : graph.entrySet()) {
-            Long nodeId = entry.getKey();
-            List<Edge> edges = entry.getValue();
-            
-            for (Edge edge : edges) {
-                Node fromNode = edge.getStartNode();
-                Node toNode = edge.getEndNode();
-                
-                if ((fromNode.getStationName().equals(fromName) && toNode.getStationName().equals(toName)) ||
-                    (fromNode.getStationName().equals(toName) && toNode.getStationName().equals(fromName))) {
-                    usedEdges.add(Pair.of(fromNode.getId(), toNode.getId()));
-                    usedEdges.add(Pair.of(toNode.getId(), fromNode.getId()));
-                }
+        List<Edge> candidateEdges = edgesByNodeName.getOrDefault(fromName, new ArrayList<>());
+        for (Edge edge : candidateEdges) {
+            Node toNode = edge.getEndNode();
+            if (toNode != null && toNode.getStationName().equals(toName)) {
+                usedEdges.add(Pair.of(edge.getStartNode().getId(), toNode.getId()));
+                usedEdges.add(Pair.of(toNode.getId(), edge.getStartNode().getId()));
             }
         }
     }
📝 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
private Set<Pair<Long, Long>> extractActualEdgesFromRoute(List<TransportationResponseDto.Step> route, Map<Long, List<Edge>> graph) {
Set<Pair<Long, Long>> usedEdges = new HashSet<>();
for (TransportationResponseDto.Step step : route) {
String fromName = step.from();
String toName = step.to();
for (Map.Entry<Long, List<Edge>> entry : graph.entrySet()) {
Long nodeId = entry.getKey();
List<Edge> edges = entry.getValue();
for (Edge edge : edges) {
Node fromNode = edge.getStartNode();
Node toNode = edge.getEndNode();
if ((fromNode.getStationName().equals(fromName) && toNode.getStationName().equals(toName)) ||
(fromNode.getStationName().equals(toName) && toNode.getStationName().equals(fromName))) {
usedEdges.add(Pair.of(fromNode.getId(), toNode.getId()));
usedEdges.add(Pair.of(toNode.getId(), fromNode.getId()));
}
}
}
}
return usedEdges;
}
private Set<Pair<Long, Long>> extractActualEdgesFromRoute(List<TransportationResponseDto.Step> route, Map<Long, List<Edge>> graph) {
Set<Pair<Long, Long>> usedEdges = new HashSet<>();
// 노드 이름으로 엣지를 빠르게 찾기 위한 맵 구성
Map<String, List<Edge>> edgesByNodeName = new HashMap<>();
for (List<Edge> edges : graph.values()) {
for (Edge edge : edges) {
if (edge.getStartNode() != null) {
edgesByNodeName.computeIfAbsent(edge.getStartNode().getStationName(), k -> new ArrayList<>()).add(edge);
}
}
}
for (TransportationResponseDto.Step step : route) {
String fromName = step.from();
String toName = step.to();
List<Edge> candidateEdges = edgesByNodeName.getOrDefault(fromName, new ArrayList<>());
for (Edge edge : candidateEdges) {
Node toNode = edge.getEndNode();
if (toNode != null && toNode.getStationName().equals(toName)) {
usedEdges.add(Pair.of(edge.getStartNode().getId(), toNode.getId()));
usedEdges.add(Pair.of(toNode.getId(), edge.getStartNode().getId()));
}
}
}
return usedEdges;
}

int weight = entry.getValue();

if (usedEdges.contains(edge)) {
int penalty = routeIndex * 100000;
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

패널티 계산에 매직 넘버 사용

routeIndex * 100000에서 100000이라는 매직 넘버가 사용되고 있습니다. 이 값을 상수로 정의하여 코드의 가독성과 유지보수성을 향상시키는 것이 좋습니다.

+ private static final int ROUTE_PENALTY_MULTIPLIER = 100000; // 경로별 패널티 가중치

 private Map<Pair<Long, Long>, Integer> createActualEdgePenalizedWeightMap(Map<Pair<Long, Long>, Integer> originalWeightMap, Set<Pair<Long, Long>> usedEdges, int routeIndex) {
     Map<Pair<Long, Long>, Integer> penalizedWeightMap = new HashMap<>();
     
     for (Map.Entry<Pair<Long, Long>, Integer> entry : originalWeightMap.entrySet()) {
         Pair<Long, Long> edge = entry.getKey();
         int weight = entry.getValue();
         
         if (usedEdges.contains(edge)) {
-            int penalty = routeIndex * 100000;
+            int penalty = routeIndex * ROUTE_PENALTY_MULTIPLIER;
             penalizedWeightMap.put(edge, weight + penalty);
         } else {
             penalizedWeightMap.put(edge, weight);
         }
     }
📝 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
int penalty = routeIndex * 100000;
private static final int ROUTE_PENALTY_MULTIPLIER = 100000; // 경로별 패널티 가중치
private Map<Pair<Long, Long>, Integer> createActualEdgePenalizedWeightMap(Map<Pair<Long, Long>, Integer> originalWeightMap, Set<Pair<Long, Long>> usedEdges, int routeIndex) {
Map<Pair<Long, Long>, Integer> penalizedWeightMap = new HashMap<>();
for (Map.Entry<Pair<Long, Long>, Integer> entry : originalWeightMap.entrySet()) {
Pair<Long, Long> edge = entry.getKey();
int weight = entry.getValue();
if (usedEdges.contains(edge)) {
int penalty = routeIndex * ROUTE_PENALTY_MULTIPLIER;
penalizedWeightMap.put(edge, weight + penalty);
} else {
penalizedWeightMap.put(edge, weight);
}
}
🤖 Prompt for AI Agents
In src/main/java/com/wayble/server/direction/service/TransportationService.java
around line 248, the penalty calculation uses a magic number ("routeIndex *
100000"); replace the literal with a clearly named constant (e.g.,
PENALTY_PER_ROUTE or ROUTE_PENALTY_MULTIPLIER) declared at the top of the class
(private static final int) and use that constant in the multiplication to
improve readability and maintainability.

Comment on lines +290 to +292
// 환승 횟수 검증 (4회 이상 제외)
int transferCount = calculateTransferCount(route);
return transferCount < 4;
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

환승 횟수 제한이 하드코딩됨

환승 횟수 제한이 4회로 하드코딩되어 있습니다. 이를 상수로 정의하여 설정 가능하도록 하는 것이 좋습니다.

+ private static final int MAX_TRANSFER_COUNT = 4; // 최대 환승 횟수

 // 환승 횟수 검증 (4회 이상 제외)
 int transferCount = calculateTransferCount(route);
- return transferCount < 4;
+ return transferCount < MAX_TRANSFER_COUNT;

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

🤖 Prompt for AI Agents
In src/main/java/com/wayble/server/direction/service/TransportationService.java
around lines 290 to 292 the transfer limit is hardcoded as 4; replace the magic
number with a named constant (e.g., MAX_TRANSFER_COUNT) declared at the top of
the class (or as a configurable property if preferred) and use that constant in
the comparison; ensure the constant is documented and, if made configurable,
loaded from application properties with a sensible default and validated before
use.

Comment on lines +301 to 309
private int calculateWalkDistance(List<TransportationResponseDto.Step> route) {
return route.stream()
.filter(step -> step.mode() == DirectionType.WALK)
.mapToInt(step -> {
// 간단한 도보 거리 추정 (실제로는 정확한 거리 계산 필요)
return 500; // 기본값
})
.sum();
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

도보 거리 계산이 하드코딩된 값 사용

calculateWalkDistance 메서드가 실제 거리를 계산하지 않고 모든 WALK 단계에 대해 500이라는 고정값을 반환하고 있습니다. 이는 경로 정렬 시 부정확한 결과를 초래할 수 있습니다.

실제 거리 계산 로직을 구현해야 합니다. 각 Step의 from과 to 좌표를 사용하여 haversine 함수로 실제 거리를 계산하는 구현이 필요합니다. 이 기능을 구현한 코드를 제공해드릴까요?

🤖 Prompt for AI Agents
In src/main/java/com/wayble/server/direction/service/TransportationService.java
around lines 301 to 309, replace the hardcoded 500-per-WALK-step with a real
distance calculation: for each Step with mode == DirectionType.WALK, extract the
from and to coordinates (lat/lon), compute the great-circle distance using a
haversine helper (use Math.sin/Math.cos/Math.asin/Math.sqrt) and return the
distance in meters, sum those distances and return the total as an int; include
null/empty-coordinate guards and a small helper method signature like
haversine(lat1, lon1, lat2, lon2) -> double (meters) to keep code clean.

Comment on lines +70 to +76
@GetMapping("/validate")
public CommonResponse<WaybleZoneSearchResponseDto> findIsValidWaybleZone(
@Valid @ModelAttribute WaybleZoneSearchConditionDto conditionDto
)
{
return CommonResponse.success(waybleZoneSearchService.isValidWaybleZone(conditionDto));
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

유사 존 미발견 시의 HTTP 응답을 명확히 처리하세요.

현재 서비스가 null을 반환할 수 있으나 컨트롤러는 그대로 200 OK + null data를 반환합니다. API 계약을 명확히 하기 위해 미발견 시 404(Not Found) 또는 204(No Content)로 응답하는 것을 권장합니다. 공통 응답 규약(CommonResponse)에 맞춰 에러/빈 응답 처리가 있으면 그 방식을 사용하세요.

간단한 404 처리 예시:

     @GetMapping("/validate")
     public CommonResponse<WaybleZoneSearchResponseDto> findIsValidWaybleZone(
             @Valid @ModelAttribute WaybleZoneSearchConditionDto conditionDto
     )
     {
-        return CommonResponse.success(waybleZoneSearchService.isValidWaybleZone(conditionDto));
+        WaybleZoneSearchResponseDto result = waybleZoneSearchService.isValidWaybleZone(conditionDto);
+        if (result == null) {
+            throw new ResponseStatusException(HttpStatus.NOT_FOUND, "30m 이내에서 유사한 웨이블존을 찾지 못했습니다.");
+        }
+        return CommonResponse.success(result);
     }

추가 import:

import org.springframework.http.HttpStatus;
import org.springframework.web.server.ResponseStatusException;
🤖 Prompt for AI Agents
In
src/main/java/com/wayble/server/explore/controller/WaybleZoneSearchController.java
around lines 70 to 76, the controller currently returns 200 OK with null data
when the service finds no matching zone; change it to handle "not found"
explicitly by checking the service result before wrapping it in CommonResponse
and either (a) throw a ResponseStatusException(HttpStatus.NOT_FOUND, "Wayble
zone not found") when the service returns null, or (b) if your CommonResponse
has a standard empty/404 helper, use that helper to return the correct response;
also add the necessary imports for org.springframework.http.HttpStatus and
org.springframework.web.server.ResponseStatusException if you choose the
exception approach.

Comment on lines +156 to +164
// 부분 매치도 포함 (공백 제거 후 검색)
String cleanedName = cond.zoneName().replaceAll("\\s+", "");
b.should(s -> s
.wildcard(w -> w
.field("zoneName")
.value("*" + cleanedName + "*")
.boost(1.0f)
)
);
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

wildcard 쿼리를 분석 필드(text)에 적용하면 매칭 정확도가 떨어집니다.

wildcard는 보통 keyword(비분석) 서브필드에 적용해야 기대한 부분매치가 동작합니다. 현재 zoneName이 text 필드라면 토큰 단위로 매칭되어 의도와 다르게 동작하거나 누락/오탐이 발생할 수 있습니다. 매핑에 zoneName.keyword가 있다면 해당 필드로 바꾸세요.

-                    b.should(s -> s
-                            .wildcard(w -> w
-                                    .field("zoneName")
-                                    .value("*" + cleanedName + "*")
-                                    .boost(1.0f)
-                            )
-                    );
+                    b.should(s -> s
+                            .wildcard(w -> w
+                                    .field("zoneName.keyword") // keyword 서브필드로 변경
+                                    .value("*" + cleanedName + "*")
+                                    .boost(1.0f)
+                            )
+                    );

추가 개선(선택):

  • 한국어/공백/오탈자까지 고려한 부분 매칭은 edge-ngram 필드 도입이 더 적합합니다(예: zoneName.ngrammatch/match_phrase_prefix).

아래 스크립트로 WaybleZoneDocumentzoneName 매핑/필드 정의를 확인해 주세요(예: @Field 애노테이션, 서브필드 존재 여부).


🏁 Script executed:

#!/bin/bash
fd -a "WaybleZoneDocument.java"
rg -n "class WaybleZoneDocument|zoneName|@Field" -A 3 -B 3

Length of output: 63167


조치 필요 — wildcard를 text(zoneName) 필드에 적용하지 마세요 (매핑에 .keyword 없음)

검증 결과: zoneName은 text 필드로 korean_edge_ngram_analyzer / korean_search_analyzer로 색인되어 있습니다 (src/main/java/com/wayble/server/explore/entity/WaybleZoneDocument.java, src/main/resources/elasticsearch/settings/wayble_zone_mappings.json). 따라서 text 필드에 wildcard를 쓰면 토큰화와 충돌해 누락/오탐이 발생할 수 있고, 현재 매핑에 .keyword 서브필드가 없어 zoneName.keyword로 바로 바꿀 수 없습니다.

수정 권장 위치:

  • src/main/java/com/wayble/server/explore/repository/search/WaybleZoneQuerySearchRepository.java (현재 wildcard 블록: 약 156–164행) — wildcard 블록 제거 권장.

권장 변경(diff):

-                    // 부분 매치도 포함 (공백 제거 후 검색)
-                    String cleanedName = cond.zoneName().replaceAll("\\s+", "");
-                    b.should(s -> s
-                            .wildcard(w -> w
-                                    .field("zoneName")
-                                    .value("*" + cleanedName + "*")
-                                    .boost(1.0f)
-                            )
-                    );
+                    // wildcard 제거 — zoneName은 korean_edge_ngram_analyzer로 색인되어 있으므로 match / fuzzy 로 부분 매칭을 처리합니다

대안(필요 시):

  • wildcard가 꼭 필요하면 매핑에 keyword 서브필드 또는 별도 ngram/keyword 필드를 추가하고(예: zoneName.fields.keyword) 해당 필드로 조회하도록 변경한 뒤 재색인하세요. 예시 매핑 변경:
 "zoneName": {
-  "type": "text",
-  "analyzer": "korean_edge_ngram_analyzer",
-  "search_analyzer":"korean_search_analyzer"
+  "type": "text",
+  "analyzer": "korean_edge_ngram_analyzer",
+  "search_analyzer":"korean_search_analyzer",
+  "fields": {
+    "keyword": { "type": "keyword", "ignore_above": 256 }
+  }
 }
  • 하지만 권장 접근은 현재 설정(edge-ngram)으로 match / match_phrase_prefix / fuzzy 조합을 사용해 부분매칭을 처리하는 것입니다(성능/정확도 측면에서 더 적합).

요약: wildcard 블록을 제거하거나, 정말 wildcard가 필요하면 매핑(및 재색인)을 먼저 추가한 후 zoneName.keyword로 쿼리하도록 변경하세요.

📝 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
// 부분 매치도 포함 (공백 제거 후 검색)
String cleanedName = cond.zoneName().replaceAll("\\s+", "");
b.should(s -> s
.wildcard(w -> w
.field("zoneName")
.value("*" + cleanedName + "*")
.boost(1.0f)
)
);
// wildcard 제거 — zoneName은 korean_edge_ngram_analyzer로 색인되어 있으므로 match / fuzzy 로 부분 매칭을 처리합니다

Comment on lines +186 to +205
// 정렬: 점수 + 거리 조합
SortOptions scoreSort = SortOptions.of(s -> s.score(sc -> sc.order(SortOrder.Desc)));
SortOptions geoSort = SortOptions.of(s -> s
.geoDistance(gds -> gds
.field("address.location")
.location(GeoLocation.of(gl -> gl
.latlon(ll -> ll
.lat(cond.latitude())
.lon(cond.longitude())
)
))
.order(SortOrder.Asc)
)
);

NativeQuery nativeQuery = NativeQuery.builder()
.withQuery(query)
.withSort(scoreSort)
.withSort(geoSort)
.withPageable(PageRequest.of(0, 1)) // 첫 번째 결과만
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

정렬값 인덱스 가정으로 인한 런타임 예외 가능성(IndexOutOfBounds/잘못된 캐스팅).

_scoregeo_distance를 함께 정렬할 때, getSortValues()_score가 포함되지 않는 클라이언트/버전 조합이 있습니다. 이 경우 정렬값 리스트가 1개만 반환되어 현재의 “두 번째 값이 거리” 가정이 깨질 수 있습니다. 또한 _score 값이 포함되는 경우에도 Double 캐스팅이 안전하지 않을 수 있습니다.

정렬값의 “마지막 요소를 거리로 간주”하고, Number로 캐스팅 후 doubleValue()를 사용하는 방식으로 견고하게 처리하세요.

-        WaybleZoneDocument doc = hits.getSearchHit(0).getContent();
-        Double distanceInMeters = (Double) hits.getSearchHit(0).getSortValues().get(1); // 거리는 두 번째 정렬값
-        Double distanceInKm = distanceInMeters / 1000.0;
-        
-        return WaybleZoneSearchResponseDto.from(doc, distanceInKm);
+        WaybleZoneDocument doc = hits.getSearchHit(0).getContent();
+        var sortValues = hits.getSearchHit(0).getSortValues();
+        if (sortValues == null || sortValues.isEmpty()) {
+            // 방어적 처리: 거리 계산 불가 시 0으로 간주하거나(권장 X) 하버사인 계산으로 대체 고려
+            return WaybleZoneSearchResponseDto.from(doc, 0.0);
+        }
+        Number distanceInMeters = (Number) sortValues.get(sortValues.size() - 1); // 마지막 값을 거리로 간주
+        double distanceInKm = distanceInMeters.doubleValue() / 1000.0;
+        return WaybleZoneSearchResponseDto.from(doc, distanceInKm);

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 186 to 205, the code assumes sortValues[1] is the geo distance and
casts directly to Double which can throw IndexOutOfBounds or ClassCastException
for some client/version combos; change the logic to treat the last element of
getSortValues() as the distance, first check that getSortValues() is non-empty,
then obtain the last element, convert it safely by checking if it's a Number and
calling number.doubleValue(), otherwise parse a Double from its toString(), and
handle the empty/malformed case with a sensible default or fallback so no
unchecked casting or index assumptions remain.

Comment on lines +46 to +48
public WaybleZoneSearchResponseDto isValidWaybleZone(WaybleZoneSearchConditionDto condition) {
return waybleZoneQuerySearchRepository.findSimilarWaybleZone(condition);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

메서드 명과 반환 계약이 모호합니다 (boolean처럼 보이지만 DTO를 반환하고, 실패 시 null).

  • isValidWaybleZone라는 이름은 boolean 반환을 연상시키지만 실제로는 DTO를 반환합니다. 또한 유사 항목이 없을 때 null을 반환해 상위 레이어에서의 처리가 모호합니다(200 OK + null data인지, 404/204인지 등).
  • 서비스 계층에서 실패 계약을 명확히 하거나 Optional로 래핑해 의도를 드러내는 것을 권장합니다.

다음과 같이 개선을 제안합니다.

  • 메서드명을 findSimilarWaybleZone(또는 validateAndFindSimilarWaybleZone)로 변경
  • 반환 타입을 Optional<WaybleZoneSearchResponseDto>로 변경하여 null 회피
  • 실패 정책(예: 미발견 시 예외)을 컨트롤러와 합의

예시(서비스 메서드 시그니처만):

- public WaybleZoneSearchResponseDto isValidWaybleZone(WaybleZoneSearchConditionDto condition) {
-     return waybleZoneQuerySearchRepository.findSimilarWaybleZone(condition);
- }
+ public Optional<WaybleZoneSearchResponseDto> findSimilarWaybleZone(WaybleZoneSearchConditionDto condition) {
+     return Optional.ofNullable(waybleZoneQuerySearchRepository.findSimilarWaybleZone(condition));
+ }
📝 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 WaybleZoneSearchResponseDto isValidWaybleZone(WaybleZoneSearchConditionDto condition) {
return waybleZoneQuerySearchRepository.findSimilarWaybleZone(condition);
}
public Optional<WaybleZoneSearchResponseDto> findSimilarWaybleZone(WaybleZoneSearchConditionDto condition) {
return Optional.ofNullable(waybleZoneQuerySearchRepository.findSimilarWaybleZone(condition));
}
🤖 Prompt for AI Agents
In src/main/java/com/wayble/server/explore/service/WaybleZoneSearchService.java
around lines 46 to 48, the method name isValidWaybleZone is misleading (suggests
boolean) and it returns a DTO or null; change the method to a clearly named
finder like findSimilarWaybleZone (or validateAndFindSimilarWaybleZone) and
change the signature to return Optional<WaybleZoneSearchResponseDto> instead of
returning null; update the implementation to wrap the repository result in
Optional.ofNullable(...), update all callers (controller/service tests) to
handle Optional or decide on a failure policy (map Optional.empty() to a
specific exception/HTTP status) so null is never propagated.

Comment on lines +536 to +541
List<WaybleZone> waybleZoneList = waybleZoneRepository.findAll();
WaybleZone waybleZone = waybleZoneList.get(0);
String zoneName = waybleZone.getZoneName();
MvcResult result = mockMvc.perform(get(baseUrl + "/validate")
.header("Authorization", "Bearer " + token)
.param("latitude", String.valueOf(waybleZone.getAddress().getLatitude()))
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

테스트 안전성: 데이터 비어있을 때의 방어 로직 추가.

샘플 데이터가 의도치 않게 비어있는 경우 waybleZoneList.get(0)에서 IndexOutOfBoundsException이 발생할 수 있습니다. 방어적 체크를 추가해 테스트 안정성을 높이세요.

-        List<WaybleZone> waybleZoneList = waybleZoneRepository.findAll();
-        WaybleZone waybleZone = waybleZoneList.get(0);
+        List<WaybleZone> waybleZoneList = waybleZoneRepository.findAll();
+        assertThat(waybleZoneList).isNotEmpty();
+        WaybleZone waybleZone = waybleZoneList.get(0);

🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="src/test/java/com/wayble/server/explore/WaybleZoneSearchApiIntegrationTest.java"

if [ ! -f "$file" ]; then
  echo "FILE_NOT_FOUND: $file"
  rg -n "WaybleZoneSearchApiIntegrationTest" || true
  exit 0
fi

echo "== $file: lines 520-545 =="
sed -n '520,545p' "$file"

Length of output: 1834


테스트 안정성: waybleZoneList가 비어있을 때 방어 로직 추가

테스트에서 waybleZoneRepository.findAll() 반환값이 비어있을 경우 waybleZoneList.get(0)에서 IndexOutOfBoundsException이 발생할 수 있으므로 조기 실패(assert)로 안정성을 높이세요.

  • 파일: src/test/java/com/wayble/server/explore/WaybleZoneSearchApiIntegrationTest.java
  • 위치: findIsValidWaybleZoneTest() 내부, waybleZoneList.get(0) 호출 직전

제안하는 변경:

-        List<WaybleZone> waybleZoneList = waybleZoneRepository.findAll();
-        WaybleZone waybleZone = waybleZoneList.get(0);
+        List<WaybleZone> waybleZoneList = waybleZoneRepository.findAll();
+        assertThat(waybleZoneList).isNotEmpty();
+        WaybleZone waybleZone = waybleZoneList.get(0);
📝 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
List<WaybleZone> waybleZoneList = waybleZoneRepository.findAll();
WaybleZone waybleZone = waybleZoneList.get(0);
String zoneName = waybleZone.getZoneName();
MvcResult result = mockMvc.perform(get(baseUrl + "/validate")
.header("Authorization", "Bearer " + token)
.param("latitude", String.valueOf(waybleZone.getAddress().getLatitude()))
List<WaybleZone> waybleZoneList = waybleZoneRepository.findAll();
assertThat(waybleZoneList).isNotEmpty();
WaybleZone waybleZone = waybleZoneList.get(0);
String zoneName = waybleZone.getZoneName();
MvcResult result = mockMvc.perform(get(baseUrl + "/validate")
.header("Authorization", "Bearer " + token)
.param("latitude", String.valueOf(waybleZone.getAddress().getLatitude()))
🤖 Prompt for AI Agents
In
src/test/java/com/wayble/server/explore/WaybleZoneSearchApiIntegrationTest.java
around lines 536 to 541, the test calls waybleZoneList.get(0) without checking
that waybleZoneRepository.findAll() returned any elements; add a defensive
assertion right after obtaining waybleZoneList to fail fast if the list is empty
(e.g., assertFalse(waybleZoneList.isEmpty(), "Expected at least one WaybleZone
in repository") or assertThat/Assertions.assertTrue with a clear message), or
alternatively arrange/create a WaybleZone fixture before calling get(0) so the
test never depends on an empty repository.

@KiSeungMin KiSeungMin merged commit 2e9d7f0 into main Aug 14, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release 프로덕션 서버에 배포

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feat] 대중교통 api가 여러 경로를 추천

3 participants