-
Notifications
You must be signed in to change notification settings - Fork 1
[FEAT] 길찾기 중 추가적인 정보 반영 #137
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Walkthrough오픈데이터 연동을 위한 설정·DTO·HTTP 클라이언트와 BusInfoService가 추가되고, 대중교통 DTO 패키 구조가 재배치되며 TransportationService가 경로 병합 및 단계별(버스/지하철) 추가 정보를 첨부하도록 변경되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant Controller
participant TransportationService as Service
participant BusInfoService as BusInfo
participant FacilityService as Facility
participant OpenDataAPI as OpenData
Client->>Controller: 요청(TransportationRequestDto)
Controller->>Service: findTransportation(request)
Service->>Service: 엣지 그룹화 및 Step 생성
alt Step 타입 == BUS
Service->>BusInfo: getBusInfo(stationName,busId,x,y)
BusInfo->>OpenData: 정류장 검색 API 호출
OpenData-->>BusInfo: StationSearchResponse
BusInfo->>OpenData: 도착정보 조회 API 호출
OpenData-->>BusInfo: OpenDataResponse
BusInfo-->>Service: BusInfo (isShuttleBus/isLowFloor/dispatchInterval)
else Step 타입 == SUBWAY
Service->>Facility: getNodeInfo(...)
Facility-->>Service: NodeInfo
Service->>Service: SubwayInfo 매핑
end
Service-->>Controller: TransportationResponseDto
Controller-->>Client: 200 OK (응답 JSON)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Assessment against linked issues
Possibly related PRs
Suggested reviewers
Poem
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 12
🔭 Outside diff range comments (1)
src/main/java/com/wayble/server/direction/service/FacilityService.java (1)
80-92: NPE 가능성: 응답/body/item null 처리 누락 및 예외 로깅 개선 필요
- response, response.body(), response.body().item()이 null일 때 이후 for-each에서 NPE가 발생할 수 있습니다.
- 예외 로깅은 스택트레이스를 남길 수 있도록
e를 마지막 파라미터로 전달하는 것이 좋습니다. 또한 빈 맵 반환 시Map.of()가 더 의도를 드러냅니다.다음과 같이 보완을 제안합니다:
KricToiletRawResponse response = kricWebClient .get() .uri(uri) .retrieve() .bodyToMono(KricToiletRawResponse.class) .block(); - - items = response.body().item(); + if (response == null || response.body() == null || response.body().item() == null) { + log.warn("역사 화장실 api 응답이 비어있음: {}", uri); + return Map.of(); + } + items = response.body().item(); } catch(Exception e){ - log.info("역사 화장실 api 호출 중 에러 발생: {}: {}", uri, e.getCause()); - return new HashMap<>(); + log.warn("역사 화장실 api 호출 중 에러 발생. uri: {}", uri, e); + return Map.of(); }
🧹 Nitpick comments (6)
src/main/java/com/wayble/server/direction/repository/RouteRepository.java (2)
3-9: N+1 방지를 위한 EntityGraph 메서드 추가를 고려해 주세요.서비스 계층에서 Route 조회 시 startNode/endNode를 자주 직렬화한다면 LAZY 로딩으로 인한 N+1 가능성이 있습니다. ReviewRepository에서와 같이 @entitygraph를 활용한 조회 메서드를 추가해두면 안전합니다. 필요 시 아래와 같이 확장할 수 있습니다.
-import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.EntityGraph; +import java.util.Collection; +import java.util.List; +import java.util.Optional; public interface RouteRepository extends JpaRepository<Route, Long>{ - + + @EntityGraph(attributePaths = {"startNode", "endNode"}) + Optional<Route> findByRouteId(Long routeId); + + @EntityGraph(attributePaths = {"startNode", "endNode"}) + List<Route> findAllByRouteIdIn(Collection<Long> routeIds); }
7-9: 향후 조회 패턴에 맞춰 파생 쿼리 메서드 정의를 준비해 두세요.노선명/유형 기반 탐색(예: BUS vs SUBWAY 또는 특정 노선명)이 빈번하다면, 파생 메서드 추가(예: findAllByRouteType(...), findByRouteTypeAndRouteName(...))가 DTO 매핑 구간에서의 조건 분기를 줄여줍니다. 현재 PR 범위를 벗어나면 이후 단계에서 반영해도 무방합니다.
src/main/java/com/wayble/server/common/config/HttpClientConfig.java (1)
3-12: 불필요한 @requiredargsconstructor 제거 제안.본 클래스는 생성자 주입 필드가 없고, @value 필드만 존재합니다. @requiredargsconstructor는 효과가 없으므로 제거해도 됩니다.
적용 diff:
-import lombok.RequiredArgsConstructor; @@ -@RequiredArgsConstructor public class HttpClientConfig {src/main/java/com/wayble/server/direction/service/BusInfoService.java (1)
70-85: busId가 null일 때 버스 정보 제한이 불필요함busId가 null일 때 최대 1개 노선만 처리하는 로직이 있습니다(Line 71). 그러나 이미 Line 61에서 정류소 도착 정보를 조회할 때 busId로 필터링이 되므로, 이 제한은 불필요합니다.
루프 제한 로직을 제거하여 코드를 단순화할 수 있습니다:
-int count = 0; for (OpenDataResponse.Item item : openDataResponse.msgBody().itemList()) { - if (count >= 1) break; // busId가 null일 때는 최대 1개 노선만 // busType1과 busType2 추가 isLowFloor.add("1".equals(item.busType1())); isLowFloor.add("1".equals(item.busType2())); // term을 정수로 변환 try { dispatchInterval = Integer.parseInt(item.term()); } catch (NumberFormatException e) { dispatchInterval = 0; } - - count++; + break; // 첫 번째 아이템만 처리 }src/main/java/com/wayble/server/direction/service/TransportationService.java (1)
316-317: 마을버스 판단 로직 중복마을버스 여부를 판단하는 로직이 BusInfoService와 중복되어 있습니다. 이미 BusInfoService에서 처리하므로 여기서는 불필요합니다.
중복된 마을버스 판단 로직을 제거하세요:
if (currentType == DirectionType.BUS) { - boolean isShuttle = routeName != null && routeName.contains("마포"); // 마을버스 구분 - Long stationId = currentEdge.getStartNode() != null ? currentEdge.getStartNode().getId() : null;src/main/java/com/wayble/server/direction/dto/response/TransportationResponseDto.java (1)
51-56: NodeInfo record가 SubwayInfo와 중복됨
NodeInfo와SubwayInfo가 동일한 필드를 가지고 있어 중복됩니다. 코드 관리의 복잡성을 증가시킬 수 있습니다.NodeInfo를 제거하고 SubwayInfo를 재사용하거나, 상속 관계를 명확히 하세요:
-// 지하철 시설 정보 묶음 (서비스 내부에서 사용) -public record NodeInfo( - List<LocationInfo> wheelchair, - List<LocationInfo> elevator, - Boolean accessibleRestroom -) {} +// NodeInfo를 SubwayInfo의 별칭으로 사용 +public static class NodeInfo extends SubwayInfo { + public NodeInfo(List<LocationInfo> wheelchair, List<LocationInfo> elevator, Boolean accessibleRestroom) { + super(wheelchair, elevator, accessibleRestroom); + } +}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (15)
src/main/java/com/wayble/server/ServerApplication.java(2 hunks)src/main/java/com/wayble/server/common/config/HttpClientConfig.java(1 hunks)src/main/java/com/wayble/server/direction/controller/TransportationController.java(1 hunks)src/main/java/com/wayble/server/direction/dto/TransportationResponseDto.java(0 hunks)src/main/java/com/wayble/server/direction/dto/request/TransportationRequestDto.java(1 hunks)src/main/java/com/wayble/server/direction/dto/response/BusInfo.java(1 hunks)src/main/java/com/wayble/server/direction/dto/response/TransportationResponseDto.java(1 hunks)src/main/java/com/wayble/server/direction/external/opendata/OpenDataProperties.java(1 hunks)src/main/java/com/wayble/server/direction/external/opendata/dto/Arrival.java(1 hunks)src/main/java/com/wayble/server/direction/external/opendata/dto/OpenDataResponse.java(1 hunks)src/main/java/com/wayble/server/direction/external/opendata/dto/StationSearchResponse.java(1 hunks)src/main/java/com/wayble/server/direction/repository/RouteRepository.java(1 hunks)src/main/java/com/wayble/server/direction/service/BusInfoService.java(1 hunks)src/main/java/com/wayble/server/direction/service/FacilityService.java(1 hunks)src/main/java/com/wayble/server/direction/service/TransportationService.java(5 hunks)
💤 Files with no reviewable changes (1)
- src/main/java/com/wayble/server/direction/dto/TransportationResponseDto.java
🧰 Additional context used
🧬 Code Graph Analysis (12)
src/main/java/com/wayble/server/direction/repository/RouteRepository.java (9)
src/main/java/com/wayble/server/direction/entity/transportation/Route.java (1)
Entity(9-36)src/main/java/com/wayble/server/direction/repository/PlaceRepository.java (1)
PlaceRepository(6-7)src/main/java/com/wayble/server/direction/repository/DirectionElasticsearchRepository.java (1)
DirectionElasticsearchRepository(6-7)src/main/java/com/wayble/server/direction/repository/NodeRepository.java (1)
NodeRepository(6-7)src/main/java/com/wayble/server/direction/repository/EdgeRepository.java (1)
EdgeRepository(6-7)src/main/java/com/wayble/server/direction/repository/FacilityRepository.java (1)
FacilityRepository(10-12)src/main/java/com/wayble/server/review/repository/ReviewRepository.java (1)
ReviewRepository(9-16)src/main/java/com/wayble/server/review/repository/ReviewImageRepository.java (1)
ReviewImageRepository(6-7)src/main/java/com/wayble/server/wayblezone/repository/WaybleZoneImageRepository.java (1)
WaybleZoneImageRepository(6-7)
src/main/java/com/wayble/server/direction/service/FacilityService.java (1)
src/main/java/com/wayble/server/direction/dto/TransportationResponseDto.java (3)
Schema(9-37)NodeInfo(27-31)Step(14-20)
src/main/java/com/wayble/server/ServerApplication.java (5)
src/main/java/com/wayble/server/common/client/tmap/TMapProperties.java (1)
ConfigurationProperties(5-10)src/main/java/com/wayble/server/common/config/WebClientConfig.java (1)
Configuration(10-36)src/main/java/com/wayble/server/common/config/SwaggerConfig.java (1)
Configuration(12-34)src/main/java/com/wayble/server/direction/external/kric/KricProperties.java (1)
ConfigurationProperties(5-10)src/main/java/com/wayble/server/common/config/security/JwtProperties.java (1)
Component(6-34)
src/main/java/com/wayble/server/direction/external/opendata/OpenDataProperties.java (2)
src/main/java/com/wayble/server/direction/external/kric/KricProperties.java (1)
ConfigurationProperties(5-10)src/main/java/com/wayble/server/common/client/tmap/TMapProperties.java (1)
ConfigurationProperties(5-10)
src/main/java/com/wayble/server/common/config/HttpClientConfig.java (2)
src/main/java/com/wayble/server/common/config/WebClientConfig.java (4)
Configuration(10-36)Bean(17-21)Bean(30-35)Bean(23-28)src/main/java/com/wayble/server/common/config/ElasticsearchConfig.java (2)
Configuration(8-22)Override(14-21)
src/main/java/com/wayble/server/direction/external/opendata/dto/OpenDataResponse.java (7)
src/main/java/com/wayble/server/direction/dto/TransportationResponseDto.java (2)
Schema(9-37)Step(14-20)src/main/java/com/wayble/server/common/client/tmap/dto/response/TMapParsingResponse.java (1)
Builder(8-74)src/main/java/com/wayble/server/direction/dto/TransportationRequestDto.java (1)
Schema(5-17)src/main/java/com/wayble/server/review/dto/ReviewResponseDto.java (1)
ReviewResponseDto(6-14)src/main/java/com/wayble/server/wayblezone/dto/WaybleZoneListResponseDto.java (1)
Builder(6-17)src/main/java/com/wayble/server/common/client/tmap/dto/response/TMapResponse.java (1)
TMapResponse(5-43)src/main/java/com/wayble/server/auth/dto/TokenResponseDto.java (1)
TokenResponseDto(3-3)
src/main/java/com/wayble/server/direction/dto/response/BusInfo.java (3)
src/main/java/com/wayble/server/direction/dto/TransportationResponseDto.java (4)
Schema(9-37)NodeInfo(27-31)Step(14-20)LocationInfo(33-36)src/main/java/com/wayble/server/direction/dto/TransportationRequestDto.java (2)
Schema(5-17)Location(12-16)src/main/java/com/wayble/server/direction/entity/transportation/Route.java (1)
Entity(9-36)
src/main/java/com/wayble/server/direction/external/opendata/dto/StationSearchResponse.java (2)
src/main/java/com/wayble/server/direction/dto/TransportationRequestDto.java (1)
Schema(5-17)src/main/java/com/wayble/server/common/client/tmap/dto/response/TMapParsingResponse.java (1)
Builder(8-74)
src/main/java/com/wayble/server/direction/dto/request/TransportationRequestDto.java (1)
src/main/java/com/wayble/server/direction/dto/TransportationRequestDto.java (2)
Schema(5-17)Location(12-16)
src/main/java/com/wayble/server/direction/controller/TransportationController.java (2)
src/main/java/com/wayble/server/direction/dto/TransportationResponseDto.java (2)
Schema(9-37)Step(14-20)src/main/java/com/wayble/server/direction/dto/TransportationRequestDto.java (2)
Schema(5-17)Location(12-16)
src/main/java/com/wayble/server/direction/dto/response/TransportationResponseDto.java (2)
src/main/java/com/wayble/server/direction/dto/TransportationResponseDto.java (5)
Schema(9-37)Step(14-20)NodeInfo(27-31)PageInfo(22-25)LocationInfo(33-36)src/main/java/com/wayble/server/direction/dto/TransportationRequestDto.java (2)
Schema(5-17)Location(12-16)
src/main/java/com/wayble/server/direction/service/TransportationService.java (2)
src/main/java/com/wayble/server/direction/dto/TransportationResponseDto.java (2)
Schema(9-37)Step(14-20)src/main/java/com/wayble/server/direction/dto/TransportationRequestDto.java (1)
Schema(5-17)
🔇 Additional comments (7)
src/main/java/com/wayble/server/direction/repository/RouteRepository.java (1)
1-9: LGTM — 표준 JpaRepository 선언이며 기존 레포지토리들과 일관적입니다.
- Route 엔티티의 @id 타입(Long)과 제네릭 파라미터가 일치합니다.
- 패키지 구성 및 네이밍도 Node/Edge/Place 등 기존 레포지토리들과 동일한 스타일을 따릅니다.
src/main/java/com/wayble/server/direction/dto/request/TransportationRequestDto.java (1)
1-1: 패키지 경로 변경 검증 완료
com.wayble.server.direction.dto.TransportationRequestDto(구 FQN) 사용처가 더 이상 존재하지 않으며, 모든 import가 신규 패키지(.dto.request/.dto.response)로 올바르게 반영된 것을 확인했습니다.src/main/java/com/wayble/server/direction/external/opendata/OpenDataProperties.java (1)
7-10: 키 노출 위험 없음 확인
OpenDataProperties 인스턴스 또는toString()호출이 로그에 출력되는 코드 흔적이 없습니다. 추가 조치 없이도 현재 키가 노출되지 않음을 확인했습니다.src/main/java/com/wayble/server/direction/external/opendata/dto/OpenDataResponse.java (1)
34-38: 배차 간격(term) 타입 확인 필요OpenData의 배차 간격(term)이 숫자형으로 제공되는 경우가 많습니다. 현재 String으로 두어도 문제는 없지만, 계산/정렬에 사용할 계획이면 Integer로 매핑하는 편이 안전합니다. 실제 응답 스키마와 샘플을 기준으로 타입을 재검토해 주세요.
확인 후 Integer 매핑이 맞다면 다음과 같이 변경할 수 있습니다:
- @JsonProperty("term") String term, + @JsonProperty("term") Integer term,src/main/java/com/wayble/server/direction/service/FacilityService.java (1)
3-3: DTO 패키지 분리 반영한 import 변경 LGTM응답 DTO 패키지 분리에 따른 import 경로 변경이 일관성 있게 적용되었습니다.
src/main/java/com/wayble/server/direction/controller/TransportationController.java (1)
4-5: DTO 패키지 경로 변경 반영 LGTM요청/응답 DTO의 패키지 리팩터링에 맞춰 import가 정확하게 반영되었습니다. 컨트롤러의 공개 API 표면은 유지됩니다.
src/main/java/com/wayble/server/ServerApplication.java (1)
20-20: OpenDataProperties 프로퍼티 바인딩 활성화 LGTM신규 OpenData 연동을 위한 프로퍼티 바인딩이 애플리케이션 레벨에서 활성화되었습니다.
애플리케이션 설정(application.yml/properties)에 OpenDataProperties에서 요구하는 프로퍼티(prefix 포함)가 누락되지 않았는지 확인해 주세요. 예: 키, 베이스 URL, 엔드포인트 경로 등.
src/main/java/com/wayble/server/direction/dto/response/TransportationResponseDto.java
Outdated
Show resolved
Hide resolved
| public record Arrival ( | ||
| Integer busType1, // 1이면 저상 | ||
| Integer busType2, // 1이면 저상 | ||
| Integer term // 배차 간격 | ||
| ) {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
불리언/의미 있는 필드명으로 리팩터하고 단위를 명시하세요.
- busType1/busType2는 “1이면 저상”인 불리언 성격의 값입니다. Integer 대신 Boolean(또는 원 API 값 유지 시 enum/flag)로 노출하고, 필드명을 lowFloor1/lowFloor2 등 의미 전달이 되는 이름으로 변경하는 편이 DTO 소비 측 가독성과 오용 방지에 좋습니다.
- term은 헤드웨이(배차 간격)로 보입니다. 단위를 명확히(분/초) 하고 필드명에 담아 주세요. 예: headwayMinutes.
적용 예시(diff):
-public record Arrival (
- Integer busType1, // 1이면 저상
- Integer busType2, // 1이면 저상
- Integer term // 배차 간격
-) {}
+public record Arrival(
+ Boolean lowFloor1, // true면 저상
+ Boolean lowFloor2, // true면 저상
+ Integer headwayMinutes // 배차 간격(분)
+) {}참고: OpenDataResponse.Item의 원천 값이 문자열("1"/"0")이라면 변환 과정에서 null/이상치(그 외 값) 처리 정책을 명확히 해 주세요. 필요 시 정적 팩토리 메서드에서 검증/매핑을 수행하는 것을 권장합니다.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| public record Arrival ( | |
| Integer busType1, // 1이면 저상 | |
| Integer busType2, // 1이면 저상 | |
| Integer term // 배차 간격 | |
| ) {} | |
| public record Arrival( | |
| Boolean lowFloor1, // true면 저상 | |
| Boolean lowFloor2, // true면 저상 | |
| Integer headwayMinutes // 배차 간격(분) | |
| ) {} |
| public record ComMsgHeader( | ||
| @JsonProperty("errMsg") String errMsg, | ||
| @JsonProperty("responseTime") String responseTime, | ||
| @JsonProperty("requestMsgID") String requestMsgID, | ||
| @JsonProperty("responseMsgID") String responseMsgID, | ||
| @JsonProperty("successYN") String successYN, | ||
| @JsonProperty("returnCode") String returnCode | ||
| ) {} | ||
| public record MsgHeader( | ||
| @JsonProperty("headerMsg") String headerMsg, | ||
| @JsonProperty("headerCd") String headerCd, | ||
| @JsonProperty("itemCount") Integer itemCount | ||
| ) {} | ||
|
|
||
| public record MsgBody( | ||
| @JsonProperty("itemList") List<Item> itemList | ||
| ) {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
중첩 레코드에도 @JsonIgnoreProperties(ignoreUnknown = true) 적용 권장
상위 레벨에만 ignoreUnknown이 적용되어 있어, 하위 레벨(ComMsgHeader, MsgHeader, MsgBody)에 신규 필드가 추가될 경우 역직렬화 실패 가능성이 있습니다. 중첩 레코드에도 동일 옵션을 부여해 방어적으로 대응하는 것이 안전합니다.
다음과 같이 보완을 제안합니다:
) {}
- public record MsgHeader(
+ @JsonIgnoreProperties(ignoreUnknown = true)
+ public record MsgHeader(
@JsonProperty("headerMsg") String headerMsg,
@JsonProperty("headerCd") String headerCd,
@JsonProperty("itemCount") Integer itemCount
) {}
- public record MsgBody(
+ @JsonIgnoreProperties(ignoreUnknown = true)
+ public record MsgBody(
@JsonProperty("itemList") List<Item> itemList
) {}
+ @JsonIgnoreProperties(ignoreUnknown = true)
- public record ComMsgHeader(
+ public record ComMsgHeader(
@JsonProperty("errMsg") String errMsg,
@JsonProperty("responseTime") String responseTime,
@JsonProperty("requestMsgID") String requestMsgID,
@JsonProperty("responseMsgID") String responseMsgID,
@JsonProperty("successYN") String successYN,
@JsonProperty("returnCode") String returnCode
) {}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| public record ComMsgHeader( | |
| @JsonProperty("errMsg") String errMsg, | |
| @JsonProperty("responseTime") String responseTime, | |
| @JsonProperty("requestMsgID") String requestMsgID, | |
| @JsonProperty("responseMsgID") String responseMsgID, | |
| @JsonProperty("successYN") String successYN, | |
| @JsonProperty("returnCode") String returnCode | |
| ) {} | |
| public record MsgHeader( | |
| @JsonProperty("headerMsg") String headerMsg, | |
| @JsonProperty("headerCd") String headerCd, | |
| @JsonProperty("itemCount") Integer itemCount | |
| ) {} | |
| public record MsgBody( | |
| @JsonProperty("itemList") List<Item> itemList | |
| ) {} | |
| @JsonIgnoreProperties(ignoreUnknown = true) | |
| public record ComMsgHeader( | |
| @JsonProperty("errMsg") String errMsg, | |
| @JsonProperty("responseTime") String responseTime, | |
| @JsonProperty("requestMsgID") String requestMsgID, | |
| @JsonProperty("responseMsgID") String responseMsgID, | |
| @JsonProperty("successYN") String successYN, | |
| @JsonProperty("returnCode") String returnCode | |
| ) {} | |
| @JsonIgnoreProperties(ignoreUnknown = true) | |
| public record MsgHeader( | |
| @JsonProperty("headerMsg") String headerMsg, | |
| @JsonProperty("headerCd") String headerCd, | |
| @JsonProperty("itemCount") Integer itemCount | |
| ) {} | |
| @JsonIgnoreProperties(ignoreUnknown = true) | |
| public record MsgBody( | |
| @JsonProperty("itemList") List<Item> itemList | |
| ) {} |
🤖 Prompt for AI Agents
In
src/main/java/com/wayble/server/direction/external/opendata/dto/OpenDataResponse.java
around lines 14 to 30, the nested record types ComMsgHeader, MsgHeader and
MsgBody lack @JsonIgnoreProperties(ignoreUnknown = true) so unknown future
fields can break deserialization; add the annotation above each nested record
declaration and ensure the Jackson import
(com.fasterxml.jackson.annotation.JsonIgnoreProperties) is present at the top of
the file so unknown properties on those nested records are safely ignored during
deserialization.
| double stationX = Double.parseDouble(tmXStr); | ||
| double stationY = Double.parseDouble(tmYStr); | ||
|
|
||
| double distance = Math.sqrt(Math.pow(stationX - x, 2) + Math.pow(stationY - y, 2)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
TM 좌표계와 위경도 좌표계 불일치 문제
거리 계산 시 TM 좌표(tmX, tmY)와 위경도 좌표(x, y)를 직접 비교하고 있습니다. 좌표계가 다르면 잘못된 정류소가 선택될 가능성이 있습니다.
좌표계 변환이 필요한지 확인하고, 필요하다면 변환 로직을 추가하세요. 현재 구현이 올바른지 검증하기 위해 다음 스크립트를 실행하세요:
🏁 Script executed:
#!/bin/bash
# TM 좌표계 사용 여부 확인
rg -A 5 "tmX|tmY" --type java
# 좌표 변환 관련 유틸리티 존재 여부 확인
fd -e java -x grep -l "coordinate.*convert\|TM.*WGS\|좌표.*변환" {} \;Length of output: 3133
🏁 Script executed:
#!/bin/bash
# BusInfoService.java의 시작 부분과 메서드 시그니처, 그리고 거리 계산 로직 전후 맥락 확인
sed -n '1,300p' src/main/java/com/wayble/server/direction/service/BusInfoService.javaLength of output: 8448
🏁 Script executed:
#!/bin/bash
# getBusInfo 호출 위치 확인
rg -n "getBusInfo" -g "*.java"Length of output: 529
TM 좌표계와 위경도 좌표계 일치시키기
현재 BusInfoService.findClosestStation 메서드에서 station.tmX/tmY(TM 좌표)와 x/y(위경도)를 그대로 사용해 유클리드 거리를 계산하고 있어 잘못된 정류소가 선택될 수 있습니다.
조치 사항:
- src/main/java/com/wayble/server/direction/service/BusInfoService.java
findClosestStation 메서드 내 거리 계산 로직(Math.sqrt(Math.pow(stationX - x, 2) + Math.pow(stationY - y, 2))) - src/main/java/com/wayble/server/direction/service/TransportationService.java
getBusInfo 호출부에서 전달하는 x(위도), y(경도)
위 문제를 해결하려면 다음 중 하나를 선택해 적용하세요:
- TM 좌표(TM=Tangent Mercator, EPSG:5179 등)를 WGS84 위경도(EPSG:4326)로 변환 후 거리 계산
- 사용자로부터 받은 위경도(x,y)를 TM 좌표로 변환 후 거리 계산
Proj4J, GeoTools와 같은 검증된 라이브러리를 쓰거나, 공식 변환 공식을 직접 구현해 좌표계를 통일한 뒤 거리 계산 로직을 수정해 주세요.
🤖 Prompt for AI Agents
In src/main/java/com/wayble/server/direction/service/BusInfoService.java around
line 188 and in
src/main/java/com/wayble/server/direction/service/TransportationService.java
where getBusInfo is called, you are mixing TM coordinates (station.tmX/tmY) with
WGS84 lat/lon (x/y) when computing Euclidean distance; choose one approach and
convert coordinates so both sides are in the same CRS before distance
calculation. Fix by adding a coordinate transformation step (use a library such
as Proj4J or GeoTools, or implement the official EPSG:5179 <-> EPSG:4326
formulas), then either (A) convert station.tmX/tmY to WGS84 and compute
great-circle/haversine distance or (B) convert incoming x/y (lat,lon) to TM and
compute planar Euclidean distance; implement the conversion inside
BusInfoService (or convert once in TransportationService before calling
getBusInfo), update the distance calculation to use the unified coordinate
values, add the chosen library dependency and unit tests verifying
nearest-station results.
| if (!Objects.equals(currentEdge.getRoute(), nextEdge.getRoute())) break; | ||
| j++; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Route 객체 비교 시 null 안전성 보장 필요
Route 객체를 비교할 때 equals 메서드 사용 시 null 처리가 명시적이지 않습니다. Objects.equals가 null-safe하긴 하지만, Route 클래스의 equals 구현을 확인해야 합니다.
Route 클래스의 equals 메서드 구현을 확인하세요:
🏁 Script executed:
#!/bin/bash
# Route 클래스의 equals 메서드 구현 확인
ast-grep --pattern 'class Route {
$$$
equals($_) {
$$$
}
$$$
}'
# Route 클래스 전체 구조 확인
fd -e java -x grep -l "class Route\|record Route" {} \; | xargs catLength of output: 1037
Route 객체 논리적 동등성 비교 보강 필요
Objects.equals를 사용하면 null 안전성은 확보되나, Route 클래스에 equals/hashCode가 오버라이드되어 있지 않아 참조 동등성만 비교됩니다. 다른 인스턴스인 동일 노선을 논리적으로 같은 것으로 간주하려면 아래를 반영해주세요.
• 파일: src/main/java/com/wayble/server/direction/entity/transportation/Route.java
– 현재 equals/hashCode 미구현
추천 조치:
- Route 클래스에 비즈니스 키(예: routeId) 기반으로 equals/hashCode를 구현
또는 - 비교 로직을 명시적으로 routeId 간 비교로 변경
if (!Objects.equals( currentEdge.getRoute().getRouteId(), nextEdge.getRoute().getRouteId() )) { break; }
🤖 Prompt for AI Agents
In src/main/java/com/wayble/server/direction/service/TransportationService.java
around lines 282-283, the code uses Objects.equals(currentEdge.getRoute(),
nextEdge.getRoute()) which only does reference equality because Route lacks
equals/hashCode; fix by either implementing equals and hashCode in
src/main/java/com/wayble/server/direction/entity/transportation/Route.java based
on the business key (e.g., routeId) with proper null handling, or change the
comparison here to compare routeId explicitly (e.g., compare
currentEdge.getRoute().getRouteId() and nextEdge.getRoute().getRouteId() with
null-safety) so logically identical routes are treated as equal.
src/main/java/com/wayble/server/direction/service/TransportationService.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 13
🧹 Nitpick comments (12)
src/main/java/com/wayble/server/direction/dto/request/TransportationRequestDto.java (1)
12-16: 중첩 record 선언 가독성 개선 제안중괄호와 중첩 record 선언이 같은 라인에 있어 가독성이 떨어집니다. 선언을 라인 분리하면 코드 가독성이 좋아집니다.
아래처럼 정리하는 것을 권장합니다:
-) { public record Location( - String name, - double latitude, - double longitude -) {} +) { + public record Location( + String name, + double latitude, + double longitude + ) {}src/main/java/com/wayble/server/direction/dto/response/BusInfo.java (1)
5-11: 도착 정보 타입 명확화 제안arrival1/arrival2가 문자열로 포맷된 문구인지(예: "3분 후") 또는 초/분 단위의 수치인지가 불명확합니다. API 소비자 일관성을 위해 Duration(또는 초/분 단위 수치)로 노출하고, 포맷은 클라이언트 레이어에서 처리하도록 분리하는 것을 권장합니다.
src/main/java/com/wayble/server/direction/external/opendata/dto/StationSearchResponse.java (1)
16-20: 좌표 타입 명확화 검토tmX/tmY가 숫자 좌표라면 String 대신 Double 등 수치형으로 파싱하여 제공하는 것이 이후 계산(거리/좌표 변환)에 안전합니다. 원본 API가 문자열을 반환하더라도 DTO에서는 수치형을 사용하고, 파싱 오류 시 null 처리 정책을 명확히 하는 것을 권장합니다.
src/main/java/com/wayble/server/common/config/HttpClientConfig.java (1)
3-3: 불필요한 @requiredargsconstructor 제거현재 final 필드나 생성자 주입이 없어 @requiredargsconstructor는 의미가 없습니다.
-import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ @Configuration -@RequiredArgsConstructor public class HttpClientConfig {Also applies to: 11-11
src/main/java/com/wayble/server/direction/external/opendata/dto/OpenDataResponse.java (1)
34-37: 필드 타입의 도메인 모델링 및 파싱 안정성 검토 권고busType1, busType2, term이 모두 String으로 선언되어 있습니다. 실제 API는 숫자 코드/숫자 문자열로 내려오는 경우가 많아, 서비스에서 정수/불리언으로 변환 시 NumberFormatException/빈 문자열 처리 예외가 발생할 수 있습니다.
권장:
- 서비스 단 파싱 시 빈 문자열/비숫자 케이스를 안전하게 처리(디폴트/Optional 등).
- 장기적으로는 도메인 친화적으로 타입 모델링(예: term → Integer, busType → enum 혹은 Boolean 매핑 유틸)하여 변환 로직을 중앙화.
필요하다면 변환 유틸/매퍼를 제안 드리겠습니다.
src/main/java/com/wayble/server/direction/dto/response/TransportationResponseDto.java (4)
46-49: JSON 필드명 일관성: 'Longitude' → 'longitude'로 스네이크/카멜 규칙 유지대문자 L로 시작하는 Longitude는 다른 필드와 네이밍 규칙이 불일치합니다. 클라이언트 UX/문서 일관성을 위해 소문자 camelCase를 권장합니다. 다만, 이는 API 호환성에 영향이 있으므로 변경 시 버전 호환성을 확인해주세요.
public record LocationInfo( Double latitude, - Double Longitude + Double longitude ) {}
34-38: 불린/리스트 필드의 네이밍 개선 제안 ('is' 접두사 제거)Jackson Record 컴포넌트명 기반 직렬화에서는 JSON 키가 'isShuttleBus', 'isLowFloor'로 노출됩니다. API 응답 키로는 'shuttleBus', 'lowFloor'가 더 자연스럽고 보편적입니다. 변경 시 클라이언트 영향 범위를 확인해주세요.
public record BusInfo( - boolean isShuttleBus, // routeName에 "마포" 포함시 true - @Nullable List<Boolean> isLowFloor, // Open API(busType1,busType2) 기반 저상 여부 리스트 + boolean shuttleBus, // routeName에 "마포" 포함시 true + @Nullable List<Boolean> lowFloor, // Open API(busType1,busType2) 기반 저상 여부 리스트 @Nullable Integer dispatchInterval // Open API(term) 기반 배차간격 ){}
15-23: null 필드 미노출을 위한 @JsonInclude 적용 제안moveInfo, routeName, busInfo, subwayInfo가 @nullable입니다. null 값을 응답에서 생략하면 페이로드가 간결해지고 클라이언트 처리가 단순해집니다. 전역 설정이 없다면 Step에 한정해 적용을 권장합니다.
import com.wayble.server.direction.entity.DirectionType; import org.springframework.lang.Nullable; import io.swagger.v3.oas.annotations.media.Schema; +import com.fasterxml.jackson.annotation.JsonInclude; @@ - public record Step( + @JsonInclude(JsonInclude.Include.NON_NULL) + public record Step( DirectionType mode, // 예: START, WALK, SUBWAY, BUS, FINISH @Nullable List<MoveInfo> moveInfo, // 같은 Step으로 이동한 정류장(Node) 정보 (중간 정류장만) @Nullable String routeName, Integer moveNumber, // 같은 Step(route)로 이동한 횟수 @Nullable BusInfo busInfo, // 버스일 경우에만 생성, 이외의 경우 null @Nullable SubwayInfo subwayInfo, // 지하철일 경우에만 생성, 이외의 경우 null String from, String to ) {}
51-56: 내부 전용 타입은 응답 DTO 파일에서 분리 권장NodeInfo는 “서비스 내부에서 사용”이라고 주석 처리되어 있으나, public nested record로 외부에 노출 가능한 형태입니다. 응답 패키지/클래스에서 분리하거나 접근 제한(패키지 프라이빗)으로 오해를 줄이는 것이 좋습니다.
src/main/java/com/wayble/server/direction/repository/RouteRepository.java (1)
7-9: LGTM, 기본 CRUD 리포지토리 정의 적절현재 요구사항 기준으로 충분합니다. 다만 마을버스 판별 로직에서 routeName의 특정 키워드(예: "마포") 포함 여부를 빈번히 조회한다면, 파생 쿼리 추가를 고려할 수 있습니다.
예시:
public interface RouteRepository extends JpaRepository<Route, Long>{ - + Optional<Route> findByRouteNameContaining(String keyword); }src/main/java/com/wayble/server/direction/service/BusInfoService.java (1)
177-198: 좌표 유효성 검증 추가 필요좌표 파싱 시 null/empty 체크는 하지만, 유효한 좌표 범위인지 확인하지 않습니다. 한국의 TM 좌표계 범위를 벗어난 값에 대한 검증이 필요합니다.
double stationX = Double.parseDouble(tmXStr); double stationY = Double.parseDouble(tmYStr); + // TM 좌표계 유효 범위 검증 (한국 중부원점 기준) + if (stationX < 100000 || stationX > 300000 || stationY < 400000 || stationY > 600000) { + log.warn("정류소 좌표가 유효 범위를 벗어남: {} - tmX={}, tmY={}", + station.stNm(), stationX, stationY); + continue; + } + double distance = Math.sqrt(Math.pow(stationX - x, 2) + Math.pow(stationY - y, 2));src/main/java/com/wayble/server/direction/service/TransportationService.java (1)
293-301: moveInfo 리스트 처리 로직 개선 가능빈 리스트를 null로 설정하는 대신 빈 리스트를 유지하는 것이 일관성 있고 null 체크를 줄일 수 있습니다.
List<TransportationResponseDto.MoveInfo> moveInfoList = new ArrayList<>(); for (int k = i + 1; k < j; k++) { Edge e = pathEdges.get(k); if (e.getStartNode() != null && e.getStartNode().getStationName() != null) { moveInfoList.add(new TransportationResponseDto.MoveInfo(e.getStartNode().getStationName())); } } - if (moveInfoList.isEmpty()) moveInfoList = null; + // moveInfoList를 빈 리스트로 유지하면 클라이언트에서 null 체크 불필요
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (15)
src/main/java/com/wayble/server/ServerApplication.java(2 hunks)src/main/java/com/wayble/server/common/config/HttpClientConfig.java(1 hunks)src/main/java/com/wayble/server/direction/controller/TransportationController.java(1 hunks)src/main/java/com/wayble/server/direction/dto/TransportationResponseDto.java(0 hunks)src/main/java/com/wayble/server/direction/dto/request/TransportationRequestDto.java(1 hunks)src/main/java/com/wayble/server/direction/dto/response/BusInfo.java(1 hunks)src/main/java/com/wayble/server/direction/dto/response/TransportationResponseDto.java(1 hunks)src/main/java/com/wayble/server/direction/external/opendata/OpenDataProperties.java(1 hunks)src/main/java/com/wayble/server/direction/external/opendata/dto/Arrival.java(1 hunks)src/main/java/com/wayble/server/direction/external/opendata/dto/OpenDataResponse.java(1 hunks)src/main/java/com/wayble/server/direction/external/opendata/dto/StationSearchResponse.java(1 hunks)src/main/java/com/wayble/server/direction/repository/RouteRepository.java(1 hunks)src/main/java/com/wayble/server/direction/service/BusInfoService.java(1 hunks)src/main/java/com/wayble/server/direction/service/FacilityService.java(1 hunks)src/main/java/com/wayble/server/direction/service/TransportationService.java(5 hunks)
💤 Files with no reviewable changes (1)
- src/main/java/com/wayble/server/direction/dto/TransportationResponseDto.java
🧰 Additional context used
🧬 Code Graph Analysis (10)
src/main/java/com/wayble/server/direction/repository/RouteRepository.java (1)
src/main/java/com/wayble/server/direction/entity/transportation/Route.java (1)
Entity(9-36)
src/main/java/com/wayble/server/direction/dto/request/TransportationRequestDto.java (1)
src/main/java/com/wayble/server/direction/dto/TransportationRequestDto.java (2)
Schema(5-17)Location(12-16)
src/main/java/com/wayble/server/direction/external/opendata/OpenDataProperties.java (2)
src/main/java/com/wayble/server/direction/external/kric/KricProperties.java (1)
ConfigurationProperties(5-10)src/main/java/com/wayble/server/common/config/WebClientConfig.java (1)
Configuration(10-36)
src/main/java/com/wayble/server/direction/external/opendata/dto/StationSearchResponse.java (1)
src/main/java/com/wayble/server/direction/dto/TransportationRequestDto.java (1)
Schema(5-17)
src/main/java/com/wayble/server/direction/service/FacilityService.java (1)
src/main/java/com/wayble/server/direction/dto/TransportationResponseDto.java (4)
Schema(9-37)NodeInfo(27-31)Step(14-20)LocationInfo(33-36)
src/main/java/com/wayble/server/direction/dto/response/BusInfo.java (3)
src/main/java/com/wayble/server/direction/dto/TransportationResponseDto.java (4)
Schema(9-37)Step(14-20)LocationInfo(33-36)NodeInfo(27-31)src/main/java/com/wayble/server/direction/dto/TransportationRequestDto.java (2)
Schema(5-17)Location(12-16)src/main/java/com/wayble/server/wayblezone/dto/WaybleZoneDetailResponseDto.java (1)
Builder(9-28)
src/main/java/com/wayble/server/ServerApplication.java (3)
src/main/java/com/wayble/server/common/client/tmap/TMapProperties.java (1)
ConfigurationProperties(5-10)src/main/java/com/wayble/server/common/config/WebClientConfig.java (1)
Configuration(10-36)src/main/java/com/wayble/server/direction/external/kric/KricProperties.java (1)
ConfigurationProperties(5-10)
src/main/java/com/wayble/server/direction/controller/TransportationController.java (2)
src/main/java/com/wayble/server/direction/dto/TransportationRequestDto.java (2)
Schema(5-17)Location(12-16)src/main/java/com/wayble/server/direction/dto/TransportationResponseDto.java (2)
Schema(9-37)Step(14-20)
src/main/java/com/wayble/server/direction/external/opendata/dto/OpenDataResponse.java (4)
src/main/java/com/wayble/server/direction/dto/TransportationResponseDto.java (3)
Schema(9-37)Step(14-20)NodeInfo(27-31)src/main/java/com/wayble/server/direction/dto/TransportationRequestDto.java (1)
Schema(5-17)src/main/java/com/wayble/server/common/client/tmap/dto/response/TMapParsingResponse.java (1)
Builder(8-74)src/main/java/com/wayble/server/common/client/tmap/dto/response/TMapResponse.java (1)
TMapResponse(5-43)
src/main/java/com/wayble/server/direction/service/TransportationService.java (3)
src/main/java/com/wayble/server/direction/dto/TransportationResponseDto.java (3)
Schema(9-37)Step(14-20)NodeInfo(27-31)src/main/java/com/wayble/server/direction/dto/TransportationRequestDto.java (1)
Schema(5-17)src/main/java/com/wayble/server/direction/entity/transportation/Route.java (1)
Entity(9-36)
🔇 Additional comments (7)
src/main/java/com/wayble/server/direction/dto/request/TransportationRequestDto.java (2)
6-16: 요청 DTO 구조는 적절합니다레코드 구조(중첩 Location 포함)와 필드 선택(double vs Integer 선택 포함)가 목적에 부합합니다. null 허용이 필요한 cursor/size만 래퍼 타입을 사용한 점도 일관됩니다.
1-1: 레거시 패키지 참조 없음 확인
com.wayble.server.direction.dto.TransportationRequestDto에 대한 참조가 코드 전반에서 모두 제거되어 추가 조치가 필요 없습니다.src/main/java/com/wayble/server/direction/controller/TransportationController.java (1)
4-5: DTO 패키지 경로 변경 반영 확인 완료요청/응답 DTO의 패키지 이동에 따른 import 업데이트가 정확합니다. 컨트롤러 시그니처 및 Swagger 스키마 참조도 일치합니다.
src/main/java/com/wayble/server/direction/service/FacilityService.java (1)
3-3: 올바른 임포트 경로 업데이트
TransportationResponseDto가 새로운dto.response패키지로 이동한 것을 반영한 적절한 변경입니다.src/main/java/com/wayble/server/ServerApplication.java (1)
5-5: OpenDataProperties 설정 추가 완료새로운 외부 API 연동을 위한
OpenDataProperties설정이 적절히 추가되었습니다.Also applies to: 20-20
src/main/java/com/wayble/server/direction/service/BusInfoService.java (1)
71-85: busId가 null일 때 여러 노선 정보 처리 로직 확인 필요busId가 null일 때 최대 1개 노선만 처리하도록 제한하고 있지만(71행), 실제로는 리스트의 첫 번째 항목에서만
isLowFloor와dispatchInterval을 추출합니다. 이 동작이 의도된 것인지 확인이 필요합니다.busId가 null일 때의 사용 케이스와 여러 노선이 있을 때 첫 번째 노선만 선택하는 로직이 비즈니스 요구사항과 일치하는지 확인해주세요. 필요하다면 주석을 추가하여 이 동작의 의도를 명확히 하는 것이 좋겠습니다.
src/main/java/com/wayble/server/direction/service/TransportationService.java (1)
4-5: DTO 패키지 재구성 및 BusInfoService 의존성 추가 확인DTO 패키지가 request/response로 재구성되고 BusInfoService가 추가된 것이 적절합니다.
Also applies to: 29-29
| @Value("${http.client.request-timeout:30}") | ||
| private int requestTimeout; | ||
|
|
||
| @Bean | ||
| public HttpClient httpClient() { | ||
| return HttpClient.newBuilder() | ||
| .connectTimeout(Duration.ofSeconds(connectTimeout)) | ||
| .build(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
requestTimeout 프로퍼티가 적용되지 않아 외부 API 호출이 무기한 대기할 수 있습니다
HttpClient는 connectTimeout만 클라이언트 레벨에서 설정됩니다. 요청 타임아웃은 HttpRequest 단위에서 설정해야 하는데, 현재 requestTimeout 값이 어디에도 쓰이지 않습니다. 외부 OpenData API 호출 실패 시 쓰레드가 블로킹될 수 있습니다.
제안 1: requestTimeout을 다른 빈으로 노출해 서비스에서 HttpRequest.Builder.timeout(Duration)로 사용
@Bean
public HttpClient httpClient() {
return HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(connectTimeout))
.build();
}
+
+ @Bean
+ public Duration httpClientRequestTimeout() {
+ return Duration.ofSeconds(requestTimeout);
+ }추가 작업(다른 파일): BusInfoService에서 HttpRequest 생성 시 builder.timeout(httpClientRequestTimeout) 적용. 적용 여부 확인 부탁드립니다. 적용되어 있다면 이 코멘트는 무시하셔도 됩니다.
🏁 Script executed:
#!/bin/bash
# Search for usage of the requestTimeout field elsewhere in the codebase
rg "requestTimeout" -n src
# Search for any HttpRequest.Builder.timeout(...) invocations
rg "timeout(" -n srcLength of output: 219
🏁 Script executed:
#!/bin/bash
# HttpRequest 수준의 timeout 설정 사용 여부 확인
rg -n -F 'timeout(' src
# HttpRequest.Builder 생성 위치 확인
rg -n 'HttpRequest.newBuilder' srcLength of output: 632
HttpClientConfig의 requestTimeout 프로퍼티 미사용: 제거 또는 일관된 사용 적용 필요
확인 결과, BusInfoService에서 openDataProperties.timeout()으로 이미 HttpRequest.Builder.timeout(...)을 설정하고 있어,
HttpClientConfig에 정의된 requestTimeout 필드 및 빈은 실제로 사용되지 않고 있습니다.
따라서 다음 중 하나를 선택해 반영해 주세요:
-
제거:
• 파일src/main/java/com/wayble/server/common/config/HttpClientConfig.java
• Lines 17–24 (private int requestTimeout;및 관련 빈 노출 메서드)
→ 미사용 코드 제거로 가독성·유지보수성 향상 -
일관된 공통 설정으로 활용:
•HttpClientConfig에Duration httpClientRequestTimeout()빈 등록
•BusInfoService의builder.timeout(Duration.ofSeconds(openDataProperties.timeout()))대신 해당 빈 사용
위 방안 중 프로젝트 정책에 맞는 쪽으로 선택하여 반영 부탁드립니다.
🤖 Prompt for AI Agents
In src/main/java/com/wayble/server/common/config/HttpClientConfig.java around
lines 17–24, the requestTimeout field and the exposed HttpClient bean are
unused; either remove the unused private int requestTimeout and the associated
bean method (lines 17–24) to eliminate dead code, OR convert that configuration
into a shared Duration/timeout bean (e.g. Duration httpClientRequestTimeout())
and update BusInfoService to inject and use that bean instead of calling
openDataProperties.timeout(), ensuring consistent timeout configuration across
the app.
| package com.wayble.server.direction.dto.response; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| public record BusInfo(List<BusArrival> buses, String stationName) { | ||
| public record BusArrival( | ||
| String busNumber, | ||
| String arrival1, | ||
| String arrival2 | ||
| ) {} | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
이름 충돌/중복 가능성 확인: BusInfo 중복 선언 여부 점검
응답 DTO 내부에 동명이인의 중첩 타입(TransportationResponseDto.BusInfo)이 존재하면 혼동/충돌을 야기할 수 있습니다. 코드베이스 내 BusInfo 선언을 점검해 주세요.
다음 스크립트로 BusInfo record 선언을 모두 확인해 주세요:
🏁 Script executed:
#!/bin/bash
# BusInfo record 선언 위치 확인
rg -n --glob '!**/build/**' --glob '!**/out/**' $'record\\s+BusInfo\\b' -A 3Length of output: 1119
BusInfo 레코드 중복 선언 발견 – 이름 충돌 위험
코드베이스에 동일한 단순 이름 BusInfo를 가진 레코드가 두 곳에서 선언되어 있어, import 시 충돌 및 혼동이 발생할 수 있습니다. 다음 파일을 참조해 중복을 해소해주세요.
• src/main/java/com/wayble/server/direction/dto/response/BusInfo.java
• src/main/java/com/wayble/server/direction/dto/response/TransportationResponseDto.java (34–37행: public record BusInfo(...))
제안
- 하나의
BusInfo레코드명을 더 구체적인 이름(예:StationBusInfo,TransportationBusInfo)으로 변경 - 변경 시 API 계약(직렬화 포맷) 영향 여부 점검 후 리팩터링
🤖 Prompt for AI Agents
In src/main/java/com/wayble/server/direction/dto/response/BusInfo.java around
lines 1–11 (and noting the conflicting record in
src/main/java/com/wayble/server/direction/dto/response/TransportationResponseDto.java
lines 34–37), there is a duplicate simple record name BusInfo causing
import/name collisions; rename the record in one location to a more specific
name (e.g., StationBusInfo or TransportationBusInfo), update all imports/usages
and tests to the new name, verify and adjust any JSON
serialization/deserialization configuration or API contracts affected by the
rename, and run the build/tests to ensure no references remain to the old
BusInfo.
| public record BusInfo(List<BusArrival> buses, String stationName) { | ||
| public record BusArrival( | ||
| String busNumber, | ||
| String arrival1, | ||
| String arrival2 | ||
| ) {} | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
PR 목표 대비 필드 누락: 저상 여부/마을버스 여부/배차 간격 포함 필요
현재 BusArrival에는 노선번호와 도착 정보 문자열만 포함되어 있어, PR 목표(저상버스 여부, 마을버스 여부, 배차 간격)가 표현되지 않습니다. OpenData DTO(Arrival: busType1/busType2/term)와의 매핑을 고려해 최소한 다음 정보가 필요합니다.
- 저상버스 여부: arrival1/arrival2 각각에 대해 Boolean
- 마을버스 여부: Boolean (또는 버스 유형 코드/문자열)
- 배차 간격: Integer (분)
하위 호환을 유지하면서 필드를 확장하는 패치를 제안합니다.
-public record BusInfo(List<BusArrival> buses, String stationName) {
- public record BusArrival(
- String busNumber,
- String arrival1,
- String arrival2
- ) {}
-}
+public record BusInfo(List<BusArrival> buses, String stationName) {
+ public record BusArrival(
+ String busNumber,
+ String arrival1,
+ String arrival2,
+ Boolean lowFloor1, // 1st 도착 버스 저상 여부
+ Boolean lowFloor2, // 2nd 도착 버스 저상 여부
+ Boolean townBus, // 마을버스 여부(또는 유형 코드로 대체)
+ Integer headway // 배차 간격(분)
+ ) {}
+}필요하시다면 BusInfoService에서 Arrival DTO 매핑 코드도 함께 제안드리겠습니다.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| public record BusInfo(List<BusArrival> buses, String stationName) { | |
| public record BusArrival( | |
| String busNumber, | |
| String arrival1, | |
| String arrival2 | |
| ) {} | |
| } | |
| public record BusInfo(List<BusArrival> buses, String stationName) { | |
| public record BusArrival( | |
| String busNumber, | |
| String arrival1, | |
| String arrival2, | |
| Boolean lowFloor1, // 1st 도착 버스 저상 여부 | |
| Boolean lowFloor2, // 2nd 도착 버스 저상 여부 | |
| Boolean townBus, // 마을버스 여부(또는 유형 코드로 대체) | |
| Integer headway // 배차 간격(분) | |
| ) {} | |
| } |
🤖 Prompt for AI Agents
In src/main/java/com/wayble/server/direction/dto/response/BusInfo.java around
lines 5-11, the BusArrival record lacks fields for low-floor flags per arrival,
village-bus/type info, and dispatch interval (term) required by the PR; update
the BusArrival record to keep existing String busNumber, arrival1, arrival2
fields and add Boolean arrival1LowFloor, Boolean arrival2LowFloor, String
busType (or isVillageBus Boolean if you prefer a simple flag) and Integer
termMinutes (dispatch interval in minutes), initialize them to nullable defaults
so callers that only use the old fields keep working, and then update the
BusInfoService mapping code to populate these new fields from the OpenData
Arrival (busType1/busType2/term) values.
| public record Arrival ( | ||
| Integer busType1, // 1이면 저상 | ||
| Integer busType2, // 1이면 저상 | ||
| Integer term // 배차 간격 | ||
| ) {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
알 수 없는 필드 무시 설정 추가 권장
대외 API 스키마 변경 시 역직렬화 실패를 방지하려면 @JsonIgnoreProperties(ignoreUnknown = true)를 부여하는 것이 안전합니다. 상위/형제 DTO에도 동일한 정책을 적용하고 있으므로 일관성 차원에서도 권장됩니다.
아래 패치를 적용해 주세요:
-package com.wayble.server.direction.external.opendata.dto;
+package com.wayble.server.direction.external.opendata.dto;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-public record Arrival (
+@JsonIgnoreProperties(ignoreUnknown = true)
+public record Arrival (
Integer busType1, // 1이면 저상
Integer busType2, // 1이면 저상
Integer term // 배차 간격
) {}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| public record Arrival ( | |
| Integer busType1, // 1이면 저상 | |
| Integer busType2, // 1이면 저상 | |
| Integer term // 배차 간격 | |
| ) {} | |
| package com.wayble.server.direction.external.opendata.dto; | |
| import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | |
| @JsonIgnoreProperties(ignoreUnknown = true) | |
| public record Arrival ( | |
| Integer busType1, // 1이면 저상 | |
| Integer busType2, // 1이면 저상 | |
| Integer term // 배차 간격 | |
| ) {} |
🤖 Prompt for AI Agents
In src/main/java/com/wayble/server/direction/external/opendata/dto/Arrival.java
around lines 3 to 7, add the Jackson annotation
@JsonIgnoreProperties(ignoreUnknown = true) to the Arrival record declaration
and import com.fasterxml.jackson.annotation.JsonIgnoreProperties so unknown
fields are ignored during deserialization; update sibling DTOs the same way for
consistency.
| public record MsgBody( | ||
| @JsonProperty("itemList") List<Item> itemList | ||
| ) {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
OpenAPI 응답에서 단일 객체가 itemList로 내려오는 변종 대응 필요
여러 공공데이터 API가 단건 응답 시 배열 대신 객체로 내려보내는 케이스가 있습니다. Jackson에 단일 값을 배열로 허용하도록 설정하면 파싱 실패를 예방할 수 있습니다.
- public record MsgBody(
- @JsonProperty("itemList") List<Item> itemList
- ) {}
+ public record MsgBody(
+ @JsonProperty("itemList")
+ @com.fasterxml.jackson.annotation.JsonFormat(with = com.fasterxml.jackson.annotation.JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
+ List<Item> itemList
+ ) {}추가 import가 필요하면 아래를 추가하세요:
import com.fasterxml.jackson.annotation.JsonFormat;🤖 Prompt for AI Agents
In
src/main/java/com/wayble/server/direction/external/opendata/dto/OpenDataResponse.java
around lines 28 to 30, the MsgBody.record's itemList fails when the API returns
a single object instead of an array; annotate the itemList property with
@JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) so Jackson
will accept a single object as a one-element array, and add the import statement
import com.fasterxml.jackson.annotation.JsonFormat; to the file.
|
|
||
| String uri = openDataProperties.baseUrl() + | ||
| openDataProperties.endpoints().stationByName() + | ||
| "?serviceKey=" + serviceKey + | ||
| "&stSrch=" + stationName + | ||
| "&resultType=json"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
URL 인코딩 처리 확인 필요
stationName 파라미터가 한글이나 특수문자를 포함할 경우 URL 인코딩이 필요할 수 있습니다. 현재 인코딩 없이 직접 URL에 포함시키고 있습니다.
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
String uri = openDataProperties.baseUrl() +
openDataProperties.endpoints().stationByName() +
"?serviceKey=" + serviceKey +
- "&stSrch=" + stationName +
+ "&stSrch=" + URLEncoder.encode(stationName, StandardCharsets.UTF_8) +
"&resultType=json";📝 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.
| String uri = openDataProperties.baseUrl() + | |
| openDataProperties.endpoints().stationByName() + | |
| "?serviceKey=" + serviceKey + | |
| "&stSrch=" + stationName + | |
| "&resultType=json"; | |
| // at the top of the file, alongside the other imports | |
| import java.net.URLEncoder; | |
| import java.nio.charset.StandardCharsets; | |
| // … | |
| String uri = openDataProperties.baseUrl() + | |
| openDataProperties.endpoints().stationByName() + | |
| "?serviceKey=" + serviceKey + | |
| "&stSrch=" + URLEncoder.encode(stationName, StandardCharsets.UTF_8) + | |
| "&resultType=json"; |
🤖 Prompt for AI Agents
In src/main/java/com/wayble/server/direction/service/BusInfoService.java around
lines 142-147, the code concatenates stationName (and other query values)
directly into the URL which breaks for Korean or special characters; update the
construction to URL-encode the query parameters (at minimum stationName, and
preferably serviceKey) using URLEncoder.encode(value, StandardCharsets.UTF_8)
(or build the URI with a proper URI/URIBuilder), replace the plain concatenation
with the encoded values, and add the necessary import (java.net.URLEncoder and
java.nio.charset.StandardCharsets) so the request URL is safe for non-ASCII
characters.
| int j = i + 1; | ||
| while (j < pathEdges.size()) { | ||
| Edge nextEdge = pathEdges.get(j); | ||
| String nextRouteName = (nextEdge.getRoute() != null) ? nextEdge.getRoute().getRouteName() : null; | ||
|
|
||
| // 같은 노선이 아니면 중단 | ||
| if (nextEdge.getEdgeType() != currentType || | ||
| !Objects.equals(currentRouteName, nextRouteName)) { | ||
| if (nextEdge.getEdgeType() != currentType) break; | ||
| if (!Objects.equals(currentEdge.getRoute(), nextEdge.getRoute())) break; | ||
| j++; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Route 객체 비교 로직의 안정성 개선 필요
Route 객체를 직접 비교하고 있는데, equals 메서드가 제대로 구현되어 있는지 확인이 필요합니다. Route ID로 비교하는 것이 더 명확할 수 있습니다.
🏁 Script executed:
#!/bin/bash
# Route 엔티티의 equals 메서드 구현 확인
ast-grep --pattern 'class Route {
$$$
equals($_) {
$$$
}
$$$
}'
# Route 엔티티 파일 내용 확인
fd -e java -x grep -l "class Route" | xargs cat | grep -A 20 "class Route"Length of output: 632
Route.equals 미구현으로 인한 참조 비교 문제: routeId 기반 비교 또는 equals/hashCode 구현 필요
현재 Objects.equals(currentEdge.getRoute(), nextEdge.getRoute())는 Route 클래스에 equals/hashCode가 오버라이드되어 있지 않아 단순 참조(identity) 비교를 수행합니다. 같은 노선이라도 서로 다른 인스턴스로 로딩될 경우 의도치 않게 false가 반환될 수 있습니다.
수정 사항 제안:
- src/main/java/com/wayble/server/direction/service/TransportationService.java (278–284줄)
- 기존:
if (!Objects.equals(currentEdge.getRoute(), nextEdge.getRoute())) break;
- 대안1: routeId로 직접 비교
if (!Objects.equals(currentEdge.getRoute().getRouteId(), nextEdge.getRoute().getRouteId())) break;
- 대안2: Route 클래스에 equals/hashCode 오버라이드 추가
@Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Route)) return false; Route that = (Route) o; return Objects.equals(routeId, that.routeId); } @Override public int hashCode() { return Objects.hash(routeId); }
- 기존:
- 위 둘 중 하나를 선택해 일관된 비교 로직을 적용해 주세요.
🤖 Prompt for AI Agents
In src/main/java/com/wayble/server/direction/service/TransportationService.java
around lines 278–284, Objects.equals(currentEdge.getRoute(),
nextEdge.getRoute()) currently does identity comparison because Route does not
override equals/hashCode; replace this with a null-safe routeId comparison
(compare currentEdge.getRoute().getRouteId() to
nextEdge.getRoute().getRouteId()) or alternatively implement equals() and
hashCode() in the Route class based on routeId (and ensure both methods handle
null routeId), then update the comparison accordingly so two Route instances
with the same routeId are treated as equal.
| boolean isShuttle = routeName != null && routeName.contains("마포"); // 마을버스 구분 | ||
|
|
||
| Long stationId = currentEdge.getStartNode() != null ? currentEdge.getStartNode().getId() : null; | ||
| List<Boolean> lowFloors = null; | ||
| List<Integer> intervals = null; | ||
| try { | ||
| if (stationId != null) { | ||
| TransportationResponseDto.BusInfo busInfoData = busInfoService.getBusInfo(currentEdge.getStartNode().getStationName(), null, currentEdge.getStartNode().getLatitude(), currentEdge.getStartNode().getLongitude()); | ||
| busInfo = busInfoData; | ||
| } | ||
| } catch (Exception e) { | ||
| log.error("버스 정보 조회 실패: {}", e.getMessage(), e); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BusInfoService 호출 시 예외 처리 개선 필요
busInfoService.getBusInfo()가 null을 반환할 수 있는데, 이에 대한 처리가 없습니다. BusInfoService의 89행에서 예외 발생 시 null을 반환하므로 이를 처리해야 합니다.
try {
if (stationId != null) {
TransportationResponseDto.BusInfo busInfoData = busInfoService.getBusInfo(currentEdge.getStartNode().getStationName(), null, currentEdge.getStartNode().getLatitude(), currentEdge.getStartNode().getLongitude());
- busInfo = busInfoData;
+ if (busInfoData != null) {
+ busInfo = busInfoData;
+ } else {
+ log.warn("버스 정보가 null로 반환됨: {}", currentEdge.getStartNode().getStationName());
+ busInfo = new TransportationResponseDto.BusInfo(false, new ArrayList<>(), null);
+ }
}
} catch (Exception e) {
log.error("버스 정보 조회 실패: {}", e.getMessage(), e);
+ busInfo = new TransportationResponseDto.BusInfo(false, new ArrayList<>(), null);
}📝 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.
| boolean isShuttle = routeName != null && routeName.contains("마포"); // 마을버스 구분 | |
| Long stationId = currentEdge.getStartNode() != null ? currentEdge.getStartNode().getId() : null; | |
| List<Boolean> lowFloors = null; | |
| List<Integer> intervals = null; | |
| try { | |
| if (stationId != null) { | |
| TransportationResponseDto.BusInfo busInfoData = busInfoService.getBusInfo(currentEdge.getStartNode().getStationName(), null, currentEdge.getStartNode().getLatitude(), currentEdge.getStartNode().getLongitude()); | |
| busInfo = busInfoData; | |
| } | |
| } catch (Exception e) { | |
| log.error("버스 정보 조회 실패: {}", e.getMessage(), e); | |
| } | |
| } | |
| boolean isShuttle = routeName != null && routeName.contains("마포"); // 마을버스 구분 | |
| Long stationId = currentEdge.getStartNode() != null ? currentEdge.getStartNode().getId() : null; | |
| List<Boolean> lowFloors = null; | |
| List<Integer> intervals = null; | |
| try { | |
| if (stationId != null) { | |
| TransportationResponseDto.BusInfo busInfoData = | |
| busInfoService.getBusInfo( | |
| currentEdge.getStartNode().getStationName(), | |
| null, | |
| currentEdge.getStartNode().getLatitude(), | |
| currentEdge.getStartNode().getLongitude() | |
| ); | |
| if (busInfoData != null) { | |
| busInfo = busInfoData; | |
| } else { | |
| log.warn("버스 정보가 null로 반환됨: {}", currentEdge.getStartNode().getStationName()); | |
| busInfo = new TransportationResponseDto.BusInfo(false, new ArrayList<>(), null); | |
| } | |
| } | |
| } catch (Exception e) { | |
| log.error("버스 정보 조회 실패: {}", e.getMessage(), e); | |
| busInfo = new TransportationResponseDto.BusInfo(false, new ArrayList<>(), null); | |
| } | |
| } |
🤖 Prompt for AI Agents
In src/main/java/com/wayble/server/direction/service/TransportationService.java
around lines 316-329, the call to busInfoService.getBusInfo(...) can return null
but the code assumes a non-null result; update the try block to check the
returned busInfoData for null before assigning to busInfo, and if it's null log
a warning and leave busInfo as null or set a safe default; ensure downstream
code that uses busInfo guards against null to avoid NPEs.
src/main/java/com/wayble/server/direction/service/TransportationService.java
Outdated
Show resolved
Hide resolved
seung-in-Yoo
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
수고하셨습니다! 👍 공공데이터 포털 api key 가져오면 WebClient 사용에서 호환이 잘 안되는건가요!?
맞아요 ㅠㅠ 공공데이터 포털 api key는 /를 포함하고 있는데 이것 때문에 서비스키가 중복 인코딩되는 경우가 잦아요 막는 방법이 있다곤 하는데 전 계속 시도해도 안 돼서 일단 HttpClient로 구현했습니다! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (3)
src/main/java/com/wayble/server/direction/service/TransportationService.java (3)
282-283: Route 객체 참조 비교 문제: routeId 기반 비교로 변경 필요현재
Objects.equals(currentEdge.getRoute(), nextEdge.getRoute())는 Route 클래스에 equals/hashCode가 오버라이드되어 있지 않아 단순 참조 비교를 수행합니다. 동일한 노선이라도 서로 다른 인스턴스일 경우 의도치 않게 false가 반환될 수 있습니다.routeId 기반 비교로 변경하세요:
-if (!Objects.equals(currentEdge.getRoute(), nextEdge.getRoute())) break; +if (!Objects.equals(currentEdge.getRoute().getRouteId(), nextEdge.getRoute().getRouteId())) break;
323-323: getBusInfo 호출 시 routeId 파라미터 전달 승인이전 리뷰에서 지적된 null 파라미터 문제가 해결되어 currentEdge.getRoute().getRouteId()를 적절히 전달하고 있습니다.
321-328: BusInfoService 호출 시 예외 처리 강화 필요
busInfoService.getBusInfo()가 null을 반환할 수 있는데, 현재 코드는 반환값에 대한 null 체크 없이 바로 할당하고 있습니다.null 체크를 추가하세요:
try { if (stationId != null) { TransportationResponseDto.BusInfo busInfoData = busInfoService.getBusInfo(currentEdge.getStartNode().getStationName(), currentEdge.getRoute().getRouteId(), currentEdge.getStartNode().getLatitude(), currentEdge.getStartNode().getLongitude()); - busInfo = busInfoData; + if (busInfoData != null) { + busInfo = busInfoData; + } else { + log.warn("버스 정보가 null로 반환됨: {}", currentEdge.getStartNode().getStationName()); + } } } catch (Exception e) { log.error("버스 정보 조회 실패: {}", e.getMessage(), e); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/main/java/com/wayble/server/common/config/HttpClientConfig.java(1 hunks)src/main/java/com/wayble/server/direction/dto/response/TransportationResponseDto.java(1 hunks)src/main/java/com/wayble/server/direction/service/BusInfoService.java(1 hunks)src/main/java/com/wayble/server/direction/service/TransportationService.java(5 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- src/main/java/com/wayble/server/common/config/HttpClientConfig.java
- src/main/java/com/wayble/server/direction/service/BusInfoService.java
- src/main/java/com/wayble/server/direction/dto/response/TransportationResponseDto.java
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/main/java/com/wayble/server/direction/service/TransportationService.java (2)
src/main/java/com/wayble/server/direction/dto/TransportationResponseDto.java (3)
Schema(9-37)Step(14-20)NodeInfo(27-31)src/main/java/com/wayble/server/direction/dto/TransportationRequestDto.java (1)
Schema(5-17)
🔇 Additional comments (7)
src/main/java/com/wayble/server/direction/service/TransportationService.java (7)
4-5: 패키지 구조 개선 승인DTO 클래스들을 request/response 패키지로 분리한 것은 코드 구조를 명확하게 하는 좋은 개선사항입니다.
29-29: BusInfoService 의존성 추가 승인버스 정보 조회를 위한 새로운 서비스 의존성이 적절히 추가되었습니다.
218-218: 로깅 레벨 개선 승인경로를 찾을 수 없는 경우를 warn에서 info로 변경한 것은 적절합니다. 이는 일반적인 비즈니스 로직의 결과이므로 경고 수준의 로그가 아닙니다.
262-275: 도보 구간 Step 생성 로직 승인도보 구간에 대해 새로운 Step 구조에 맞게 null 값들을 적절히 설정한 것이 올바릅니다.
286-301: 중간 정류장 수집 로직 개선moveInfo 리스트를 구성하는 로직이 명확하고 적절합니다. 중간 정류장만 수집하고 빈 리스트는 null로 처리하는 것도 좋습니다.
330-349: 지하철 시설 정보 처리 로직 승인지하철역 시설 정보 조회 로직이 잘 구현되었습니다. 예외 발생 시 기본값으로 빈 리스트와 false를 설정하는 것도 적절합니다.
351-362: 새로운 Step 구조 적용 승인moveNumber, moveInfoList, busInfo, subwayInfo 등 새로운 필드들이 적절히 Step 생성자에 전달되고 있습니다. PR 목표에 부합하는 구현입니다.
| TransportationResponseDto.BusInfo busInfo = null; | ||
| TransportationResponseDto.SubwayInfo subwayInfo = null; | ||
| if (currentType == DirectionType.BUS) { | ||
| boolean isShuttle = routeName != null && routeName.contains("마포"); // 마을버스 구분 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
마을버스 구분 로직 개선 필요
현재 routeName에 "마포"가 포함되어 있는지로만 마을버스를 구분하고 있는데, 이는 너무 단순한 방식입니다. 더 정확한 구분 로직이 필요합니다.
마을버스 구분을 위한 더 정교한 로직을 구현하거나, Route 엔티티에 버스 타입 정보를 추가하는 것을 고려해보세요:
-boolean isShuttle = routeName != null && routeName.contains("마포"); // 마을버스 구분
+boolean isShuttle = isVillageBus(routeName); // 별도 메서드로 분리private boolean isVillageBus(String routeName) {
if (routeName == null) return false;
// 마을버스 패턴 정의 (예: 마포01, 마포02 등)
return routeName.matches("^마포\\d+$") ||
routeName.startsWith("마을") ||
routeName.matches("^\\d{2,3}번$"); // 기타 마을버스 패턴
}🤖 Prompt for AI Agents
In src/main/java/com/wayble/server/direction/service/TransportationService.java
around line 316, the current village-bus check uses routeName != null &&
routeName.contains("마포"), which is too simplistic; replace this with a robust
detection or use explicit type information from the Route entity: add a private
helper method isVillageBus(String routeName) that validates null and matches
stronger patterns (e.g. specific prefixes, numeric suffix patterns, or known
"마을" keywords) and call it instead of the contains check, or preferably add a
busType (enum or string) to the Route entity, populate it at data ingestion, and
use route.getBusType() == VILLAGE_BUS to decide isShuttle; update the single
location where isShuttle is computed to use the new helper/entity field and
adjust any affected unit tests.
헉 그렇군요,,, 이건 저도 나중에 참고해서 짜야겠네요 수고하셨습니다!! |
✔️ 연관 이슈
📝 작업 내용
스크린샷 (선택)
Summary by CodeRabbit
New Features
Refactor
Chores