Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/main/java/com/wayble/server/ServerApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.wayble.server.common.client.tmap.TMapProperties;
import com.wayble.server.direction.external.kric.KricProperties;
import com.wayble.server.direction.external.opendata.OpenDataProperties;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration;
Expand All @@ -16,7 +17,7 @@
)
@EnableJpaAuditing
@EnableScheduling
@EnableConfigurationProperties({TMapProperties.class, KricProperties.class})
@EnableConfigurationProperties({TMapProperties.class, KricProperties.class, OpenDataProperties.class})
@EnableElasticsearchRepositories(basePackages = {"com.wayble.server.explore.repository", "com.wayble.server.logging.repository", "com.wayble.server.direction.repository"})
@EntityScan(basePackages = "com.wayble.server")
public class ServerApplication {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.wayble.server.common.config;

import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.net.http.HttpClient;
import java.time.Duration;

@Configuration
@RequiredArgsConstructor
public class HttpClientConfig {

@Value("${http.client.connect-timeout:10}")
private int connectTimeout;

@Value("${http.client.request-timeout:30}")
private int requestTimeout;

@Bean
public HttpClient httpClient() {
return HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(connectTimeout))
.build();
Comment on lines +17 to +24
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

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 src

Length of output: 219


🏁 Script executed:

#!/bin/bash
# HttpRequest 수준의 timeout 설정 사용 여부 확인
rg -n -F 'timeout(' src

# HttpRequest.Builder 생성 위치 확인
rg -n 'HttpRequest.newBuilder' src

Length 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; 및 관련 빈 노출 메서드)
    → 미사용 코드 제거로 가독성·유지보수성 향상

  • 일관된 공통 설정으로 활용:
    HttpClientConfigDuration httpClientRequestTimeout() 빈 등록
    BusInfoServicebuilder.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.

}

@Bean
public Duration httpRequestTimeout() {
return Duration.ofSeconds(requestTimeout);
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.wayble.server.direction.controller;

import com.wayble.server.common.response.CommonResponse;
import com.wayble.server.direction.dto.TransportationRequestDto;
import com.wayble.server.direction.dto.TransportationResponseDto;
import com.wayble.server.direction.dto.request.TransportationRequestDto;
import com.wayble.server.direction.dto.response.TransportationResponseDto;
import com.wayble.server.direction.service.TransportationService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.wayble.server.direction.dto;
package com.wayble.server.direction.dto.request;

import io.swagger.v3.oas.annotations.media.Schema;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
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
) {}
}
Comment on lines +1 to +11
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

이름 충돌/중복 가능성 확인: BusInfo 중복 선언 여부 점검

응답 DTO 내부에 동명이인의 중첩 타입(TransportationResponseDto.BusInfo)이 존재하면 혼동/충돌을 야기할 수 있습니다. 코드베이스 내 BusInfo 선언을 점검해 주세요.

다음 스크립트로 BusInfo record 선언을 모두 확인해 주세요:


🏁 Script executed:

#!/bin/bash
# BusInfo record 선언 위치 확인
rg -n --glob '!**/build/**' --glob '!**/out/**' $'record\\s+BusInfo\\b' -A 3

Length 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.

Comment on lines +5 to +11
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

⚠️ Potential issue

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.

Suggested change
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.

Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.wayble.server.direction.dto.response;

import com.wayble.server.direction.entity.DirectionType;
import org.springframework.lang.Nullable;
import io.swagger.v3.oas.annotations.media.Schema;

import java.util.List;

@Schema(description = "대중교통 길찾기 응답 DTO")
public record TransportationResponseDto(
List<Step> routes,
PageInfo pageInfo
) {
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
) {}

public record PageInfo(
Integer nextCursor,
boolean hasNext
) {}

public record MoveInfo(
String nodeName // 정류장(Node)의 stationName
){}

public record BusInfo(
boolean isShuttleBus, // routeName에 "마포" 포함시 true
@Nullable List<Boolean> isLowFloor, // Open API(busType1,busType2) 기반 저상 여부 리스트
@Nullable Integer dispatchInterval // Open API(term) 기반 배차간격
){}

public record SubwayInfo(
List<LocationInfo> wheelchair,
List<LocationInfo> elevator,
Boolean accessibleRestroom
) {}

public record LocationInfo(
Double latitude,
Double longitude
) {}

// 지하철 시설 정보 묶음 (서비스 내부에서 사용)
public record NodeInfo(
List<LocationInfo> wheelchair,
List<LocationInfo> elevator,
Boolean accessibleRestroom
) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.wayble.server.direction.external.opendata;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "opendata.api")
public record OpenDataProperties(
String key,
String baseUrl,
String encodedKey,
Endpoints endpoints,
Comment on lines +6 to +10
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

key/encodedKey 동시 보관 운영 리스크

key와 encodedKey를 동시에 프로퍼티로 유지하면 값 불일치 시 장애 요인이 됩니다. 한쪽만 소스오브트루스로 삼고, 다른 한쪽은 런타임 변환(필요 시 유틸 메서드)으로 생성하는 방향을 검토해 주세요.

다음 스크립트로 encodedKey 사용처를 점검해 주세요(실사용이 없다면 제거 검토):


🏁 Script executed:

#!/bin/bash
# encodedKey 실제 사용처 검색
rg -n --fixed-strings 'encodedKey('
rg -n --fixed-strings '.encodedKey'

Length of output: 627


key/encodedKey 동시 보관 위험 및 런타임 변환 전환 제안

key와 encodedKey를 둘 다 프로퍼티로 유지할 경우 값 불일치 시 장애가 발생할 수 있습니다. 실제로 encodedKey는 아래 위치에서 사용되고 있으므로 단순 제거가 불가능하며, 대신 아래와 같이 런타임에 key를 변환하여 제공하는 방안을 검토해 주세요.

  • 사용 위치
    • src/main/java/com/wayble/server/direction/service/BusInfoService.java:97, 141

  • 개선 제안 (예시)

    1. OpenDataProperties.record 수정
      public record OpenDataProperties(
  •       String key,
    
  •       String baseUrl,
    
  •       String encodedKey,
    
  •       String key,
    
  •       String baseUrl,
          Endpoints endpoints
    
    ) {
    •   /** 요청 시점에 key를 인코딩하여 반환 */
      
    •   public String encodedKey() {
      
    •       return URLEncoder.encode(key, StandardCharsets.UTF_8);
      
    •   }
      
      }
      
      
    1. BusInfoService 내 encodedKey() 호출부는 그대로 유지

이렇게 하면 단일 소스(key)만 관리하고, encodedKey는 항상 key 기반으로 일관성 있게 생성됩니다.

🤖 Prompt for AI Agents
In
src/main/java/com/wayble/server/direction/external/opendata/OpenDataProperties.java
around lines 6 to 10, the record currently stores both key and encodedKey which
can diverge; remove the encodedKey field from the record signature and instead
add a derived accessor method encodedKey() that returns a URL-encoded form of
key (e.g., using URLEncoder.encode(key, StandardCharsets.UTF_8) or equivalent),
keep callers (BusInfoService at the noted lines) unchanged so they call
encodedKey(), and add necessary imports for encoding; this ensures a single
source of truth (key) and runtime-consistent encodedKey generation.

int timeout,
String userAgent,
String accept
) {
Comment on lines +3 to +14
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

프로퍼티 유효성 검증 추가 및 민감정보/단위 명확화.

  • 필수 값(key, baseUrl)과 timeout에 대한 제약이 없습니다. 바인딩 오류를 조기에 검출하기 위해 @validated와 제약 애노테이션을 추가하세요.
  • timeout은 단위를 명확히 하거나(Duration 타입 사용 등) 문서로 고지하세요.

예시(diff):

 import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.validation.annotation.Validated;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Positive;

-@ConfigurationProperties(prefix = "opendata.api")
+@ConfigurationProperties(prefix = "opendata.api")
+@Validated
 public record OpenDataProperties(
-        String key,
-        String baseUrl,
+        @NotBlank String key,
+        @NotBlank String baseUrl,
         String encodedKey,
         Endpoints endpoints,
-        int timeout,
+        @Positive int timeout,
         String userAgent,
         String accept
 ) {
     public record Endpoints(String arrivals, String stationByName) {}
 }

추가로 encodedKey는 런타임에서 인코딩해 만들 수 있는 값입니다. 구성 값 이중화로 인한 불일치/오용을 방지하려면 encodedKey를 제거하고, 요청 생성 시 on-the-fly로 생성하는 것을 권장합니다.

🤖 Prompt for AI Agents
In
src/main/java/com/wayble/server/direction/external/opendata/OpenDataProperties.java
around lines 3 to 14, the record lacks validation and contains a redundant
encodedKey; add @Validated to the class-level binding and apply constraint
annotations: mark key and baseUrl as @NotBlank, and validate timeout (use
@Min(1) if keeping an int or change the type to java.time.Duration to make units
explicit). Remove the encodedKey property from the record to avoid duplicated/
inconsistent configuration and compute the encoded value on-the-fly when
building requests, and update any callers to generate the encoded key at
runtime.

public record Endpoints(String arrivals, String stationByName) {}
}
Comment on lines +5 to +16
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

시간 단위/유효성 검증 강화: Duration 사용과 Bean Validation 추가 권장

  • timeout을 int로 보관하면 단위 모호성/오용 위험이 있습니다. java.time.Duration을 사용해 단위를 명확히 하세요.
  • 운영 설정 안정성을 위해 @validated와 Bean Validation 제약(@notblank, @positive 등) 추가를 권장합니다.

아래와 같이 변경을 제안합니다:

-@ConfigurationProperties(prefix = "opendata.api")
-public record OpenDataProperties(
-        String key,
-        String baseUrl,
-        String encodedKey,
-        Endpoints endpoints,
-        int timeout,
-        String userAgent,
-        String accept
-) {
-    public record Endpoints(String arrivals, String stationByName) {}
-}
+@ConfigurationProperties(prefix = "opendata.api")
+public record OpenDataProperties(
+        @jakarta.validation.constraints.NotBlank String key,
+        @jakarta.validation.constraints.NotBlank String baseUrl,
+        String encodedKey,
+        Endpoints endpoints,
+        java.time.Duration timeout,
+        String userAgent,
+        String accept
+) {
+    public record Endpoints(
+            @jakarta.validation.constraints.NotBlank String arrivals,
+            @jakarta.validation.constraints.NotBlank String stationByName
+    ) {}
+}

추가로, 클래스 상단에 @org.springframework.validation.annotation.Validated 애너테이션을 부여해야 합니다(아래 추가 import 참고).
다음 import를 파일 상단에 추가하세요:

import org.springframework.validation.annotation.Validated;

그리고 클래스 선언 위에 @validated를 추가하세요:

@Validated
@ConfigurationProperties(prefix = "opendata.api")
public record OpenDataProperties(...)
🤖 Prompt for AI Agents
In
src/main/java/com/wayble/server/direction/external/opendata/OpenDataProperties.java
around lines 5-16, replace the int timeout with java.time.Duration and add Bean
Validation and @Validated so properties are validated on bind: import
java.time.Duration, org.springframework.validation.annotation.Validated, and
jakarta.validation.constraints annotations; annotate the record with @Validated
above @ConfigurationProperties; add appropriate constraints such as @NotBlank
for strings (key, baseUrl, encodedKey, userAgent, accept), @NotNull for Duration
timeout and Endpoints, and @NotBlank for Endpoints' fields (arrivals,
stationByName) and/or @Positive for numeric-like values if needed; ensure the
record signature uses Duration timeout and that Spring Boot can bind Duration
values from config (e.g., "5s" or "PT5S").

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.wayble.server.direction.external.opendata.dto;

public record Arrival (
Integer busType1, // 1이면 저상
Integer busType2, // 1이면 저상
Integer term // 배차 간격
) {}
Comment on lines +3 to +7
Copy link

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.

Suggested change
public record Arrival (
Integer busType1, // 1이면 저상
Integer busType2, // 1이면 저상
Integer term // 배차 간격
) {}
public record Arrival(
Boolean lowFloor1, // true면 저상
Boolean lowFloor2, // true면 저상
Integer headwayMinutes // 배차 간격(분)
) {}

Comment on lines +3 to +7
Copy link

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.

Suggested change
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.

Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.wayble.server.direction.external.opendata.dto;

import java.util.List;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown = true)
public record OpenDataResponse ( // 버스 정류장 id를 기반으로 배차시간, 저상버스 여부를 확인하는 엔드포인트
@JsonProperty("comMsgHeader") ComMsgHeader comMsgHeader,
@JsonProperty("msgHeader") MsgHeader msgHeader,
@JsonProperty("msgBody") MsgBody msgBody
) {
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
) {}
Comment on lines +14 to +30
Copy link

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.

Suggested change
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.

Comment on lines +28 to +30
Copy link

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.


@JsonIgnoreProperties(ignoreUnknown = true)
public record Item(
@JsonProperty("busType1") String busType1,
@JsonProperty("busType2") String busType2,
@JsonProperty("term") String term,
@JsonProperty("busRouteId") String busRouteId
) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.wayble.server.direction.external.opendata.dto;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import java.util.List;

@JsonIgnoreProperties(ignoreUnknown = true)
public record StationSearchResponse( // 버스 정류장 id를 검색하는 엔드포인트
StationSearchMsgBody msgBody
) {
public record StationSearchMsgBody(
List<StationItem> itemList
) {}
Comment on lines +10 to +12
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

중첩 레코드(StationSearchMsgBody)에도 @JsonIgnoreProperties 적용 권장

msgBody 레벨에 향후 필드가 추가될 경우를 대비해 ignoreUnknown을 부여하면 역직렬화 안전성이 높아집니다.

다음과 같이 보완을 제안합니다:

-    public record StationSearchMsgBody(
+    @JsonIgnoreProperties(ignoreUnknown = true)
+    public record StationSearchMsgBody(
             List<StationItem> itemList
     ) {}
🤖 Prompt for AI Agents
In
src/main/java/com/wayble/server/direction/external/opendata/dto/StationSearchResponse.java
around lines 10 to 12, the nested record StationSearchMsgBody lacks a
JsonIgnoreProperties(ignoreUnknown = true) annotation; add the annotation to the
StationSearchMsgBody declaration and import
com.fasterxml.jackson.annotation.JsonIgnoreProperties so that unknown JSON
fields in msgBody are ignored during deserialization.

Comment on lines +10 to +12
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

중간 레벨 DTO에도 @JsonIgnoreProperties 부여 필요

상위/하위 타입에는 ignoreUnknown이 있지만, StationSearchMsgBody에는 빠져 있어 불명확한 필드가 포함될 경우 역직렬화 예외가 발생할 수 있습니다. 동일 정책을 적용해 주세요.

-    public record StationSearchMsgBody(
+    @JsonIgnoreProperties(ignoreUnknown = true)
+    public record StationSearchMsgBody(
             List<StationItem> itemList
     ) {}
📝 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 record StationSearchMsgBody(
List<StationItem> itemList
) {}
@JsonIgnoreProperties(ignoreUnknown = true)
public record StationSearchMsgBody(
List<StationItem> itemList
) {}
🤖 Prompt for AI Agents
In
src/main/java/com/wayble/server/direction/external/opendata/dto/StationSearchResponse.java
around lines 10 to 12, the intermediate DTO StationSearchMsgBody lacks
@JsonIgnoreProperties(ignoreUnknown = true), so unknown fields will cause
deserialization errors; add the annotation to the StationSearchMsgBody record
declaration (same policy as parent/child types) to ignore unknown JSON
properties during deserialization.


@JsonIgnoreProperties(ignoreUnknown = true)
public record StationItem(
String stId,
String stNm,
String tmX,
String tmY
) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.wayble.server.direction.repository;

import org.springframework.data.jpa.repository.JpaRepository;

import com.wayble.server.direction.entity.transportation.Route;

public interface RouteRepository extends JpaRepository<Route, Long>{

}
Loading