From fddcbf537779d9ced905c58cc5c210ad5f9b9232 Mon Sep 17 00:00:00 2001 From: HYOJIN Date: Fri, 13 Mar 2026 10:55:32 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat(risk):=20IMO=20=EA=B8=B0=EB=B0=98=20Ri?= =?UTF-8?q?sk=20=EC=83=81=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20bypass=20API=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20(#39)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../batch/global/config/SwaggerConfig.java | 5 +- .../risk/web/controller/RiskController.java | 56 +++++++++++++++++++ .../risk/web/service/RiskBypassService.java | 56 +++++++++++++++++++ 3 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/snp/batch/jobs/risk/web/controller/RiskController.java create mode 100644 src/main/java/com/snp/batch/jobs/risk/web/service/RiskBypassService.java diff --git a/src/main/java/com/snp/batch/global/config/SwaggerConfig.java b/src/main/java/com/snp/batch/global/config/SwaggerConfig.java index 3e056b9..8cb1a22 100644 --- a/src/main/java/com/snp/batch/global/config/SwaggerConfig.java +++ b/src/main/java/com/snp/batch/global/config/SwaggerConfig.java @@ -47,6 +47,9 @@ public class SwaggerConfig { new Server() .url("http://211.208.115.83:" + serverPort + contextPath) .description("중계 서버"), + new Server() + .url("https://guide.gc-si.dev" + contextPath) + .description("중계 서버 도메인"), new Server() .url("http://10.187.58.58:" + serverPort + contextPath) .description("운영 서버"), @@ -90,4 +93,4 @@ public class SwaggerConfig { .name("Apache 2.0") .url("https://www.apache.org/licenses/LICENSE-2.0")); } -} \ No newline at end of file +} diff --git a/src/main/java/com/snp/batch/jobs/risk/web/controller/RiskController.java b/src/main/java/com/snp/batch/jobs/risk/web/controller/RiskController.java new file mode 100644 index 0000000..9113622 --- /dev/null +++ b/src/main/java/com/snp/batch/jobs/risk/web/controller/RiskController.java @@ -0,0 +1,56 @@ +package com.snp.batch.jobs.risk.web.controller; + +import com.snp.batch.common.web.ApiResponse; +import com.snp.batch.jobs.risk.batch.dto.RiskDto; +import com.snp.batch.jobs.risk.web.service.RiskBypassService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.reactive.function.client.WebClientResponseException; + +import java.util.List; + +/** + * Risk 상세 조회 bypass API + * S&P Maritime API에서 Risk 데이터를 실시간 조회하여 그대로 반환 + */ +@Slf4j +@RestController +@RequestMapping("/api/risk") +@RequiredArgsConstructor +@Tag(name = "Risk", description = "선박 Risk 상세 정보 bypass API") +public class RiskController { + + private final RiskBypassService riskBypassService; + + @Operation( + summary = "IMO 기반 Risk 상세 조회", + description = "S&P API에 IMO 번호로 Risk 상세 데이터를 요청하고 응답을 그대로 반환합니다." + ) + @GetMapping("/{imo}") + public ResponseEntity>> getRiskDetailByImo( + @Parameter(description = "IMO 번호", example = "9321483") + @PathVariable String imo + ) { + try { + List riskData = riskBypassService.getRiskDetailByImo(imo); + return ResponseEntity.ok(ApiResponse.success(riskData)); + } catch (WebClientResponseException e) { + log.error("S&P Risk API 호출 실패 - IMO: {}, status: {}, body: {}", + imo, e.getStatusCode(), e.getResponseBodyAsString()); + return ResponseEntity.status(e.getStatusCode()) + .body(ApiResponse.error("S&P API 호출 실패: " + e.getMessage())); + } catch (Exception e) { + log.error("Risk 상세 조회 중 오류 - IMO: {}", imo, e); + return ResponseEntity.internalServerError() + .body(ApiResponse.error("Risk 조회 실패: " + e.getMessage())); + } + } +} diff --git a/src/main/java/com/snp/batch/jobs/risk/web/service/RiskBypassService.java b/src/main/java/com/snp/batch/jobs/risk/web/service/RiskBypassService.java new file mode 100644 index 0000000..5162dc9 --- /dev/null +++ b/src/main/java/com/snp/batch/jobs/risk/web/service/RiskBypassService.java @@ -0,0 +1,56 @@ +package com.snp.batch.jobs.risk.web.service; + +import com.snp.batch.jobs.risk.batch.dto.RiskDto; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.WebClient; + +import java.util.List; + +/** + * S&P Risk API bypass 서비스 + * 외부 Maritime API에서 Risk 상세 데이터를 실시간 조회하여 그대로 반환 + */ +@Slf4j +@Service +public class RiskBypassService { + + private static final String RISK_API_PATH = "/RiskAndCompliance/RisksByImos"; + + private final WebClient webClient; + + public RiskBypassService( + @Qualifier("maritimeServiceApiWebClient") WebClient webClient + ) { + this.webClient = webClient; + } + + /** + * IMO 번호로 S&P Risk 상세 데이터를 조회합니다. + * + * @param imo IMO 번호 + * @return Risk 상세 데이터 목록 + */ + public List getRiskDetailByImo(String imo) { + log.info("S&P Risk API 호출 - IMO: {}", imo); + + List response = webClient.get() + .uri(uriBuilder -> uriBuilder + .path(RISK_API_PATH) + .queryParam("imos", imo) + .build()) + .retrieve() + .bodyToMono(new ParameterizedTypeReference>() {}) + .block(); + + if (response == null || response.isEmpty()) { + log.warn("S&P Risk API 응답 없음 - IMO: {}", imo); + return List.of(); + } + + log.info("S&P Risk API 응답 완료 - IMO: {}, 건수: {}", imo, response.size()); + return response; + } +} From eb01dde00b75eec0b07846334d4e9caba22f990a Mon Sep 17 00:00:00 2001 From: HYOJIN Date: Fri, 13 Mar 2026 10:56:16 +0900 Subject: [PATCH 2/2] =?UTF-8?q?docs:=20=EB=A6=B4=EB=A6=AC=EC=A6=88=20?= =?UTF-8?q?=EB=85=B8=ED=8A=B8=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/RELEASE-NOTES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/RELEASE-NOTES.md b/docs/RELEASE-NOTES.md index ca92665..ad36c9b 100644 --- a/docs/RELEASE-NOTES.md +++ b/docs/RELEASE-NOTES.md @@ -27,6 +27,7 @@ - 자동 재수집 및 재수집 프로세스 전면 개선 (#30) - 배치 작업 목록 UX 개선: 상태 필터, 카드/테이블 뷰, 정렬, 실행 중 강조 (#33) - 재시도 초과 레코드 초기화 API/UI 추가 +- IMO 기반 Risk 상세 조회 bypass API 추가 (#39) ### 수정 - 자동 재수집 JobParameter 오버플로우 수정 (VARCHAR 2500 제한 해결)