package com.snp.batch.global.config; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Contact; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.info.License; import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.security.SecurityScheme; import io.swagger.v3.oas.models.servers.Server; import org.springdoc.core.models.GroupedOpenApi; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.List; /** * Swagger/OpenAPI 3.0 설정 * * Swagger UI 접속 URL: * - Swagger UI: http://localhost:8041/snp-api/swagger-ui/index.html * - API 문서 (JSON): http://localhost:8041/snp-api/v3/api-docs * - API 문서 (YAML): http://localhost:8041/snp-api/v3/api-docs.yaml * * 환경별 노출: * - dev: 모든 API 그룹 노출 * - prod: Bypass API 그룹만 노출 */ @Configuration public class SwaggerConfig { @Value("${server.port:8081}") private int serverPort; @Value("${server.servlet.context-path:}") private String contextPath; @Value("${app.environment:dev}") private String environment; @Bean @ConditionalOnProperty(name = "app.environment", havingValue = "dev", matchIfMissing = true) public GroupedOpenApi batchManagementApi() { return GroupedOpenApi.builder() .group("1. Batch Management") .pathsToMatch("/api/batch/**") .addOpenApiCustomizer(openApi -> openApi.info(new Info() .title("Batch Management API") .description("배치 Job 실행, 이력 조회, 스케줄 관리 API") .version("v1.0.0"))) .build(); } @Bean @ConditionalOnProperty(name = "app.environment", havingValue = "dev", matchIfMissing = true) public GroupedOpenApi bypassConfigApi() { return GroupedOpenApi.builder() .group("2. Bypass Config") .pathsToMatch("/api/bypass-config/**") .addOpenApiCustomizer(openApi -> openApi.info(new Info() .title("Bypass Config API") .description("Bypass API 설정 및 코드 생성 관리 API") .version("v1.0.0"))) .build(); } @Bean @ConditionalOnProperty(name = "app.environment", havingValue = "dev", matchIfMissing = true) public GroupedOpenApi screeningGuideApi() { return GroupedOpenApi.builder() .group("4. Screening Guide") .pathsToMatch("/api/screening-guide/**") .addOpenApiCustomizer(openApi -> openApi.info(new Info() .title("Screening Guide API") .description("Risk & Compliance Screening Guide 조회 API") .version("v1.0.0"))) .build(); } @Bean public GroupedOpenApi bypassApi() { return GroupedOpenApi.builder() .group("3. Bypass API") .pathsToMatch("/api/**") .pathsToExclude("/api/batch/**", "/api/bypass-config/**", "/api/screening-guide/**", "/api/bypass-account/**") .addOpenApiCustomizer(openApi -> { openApi.info(new Info() .title("Bypass API") .description("S&P Global 선박/해운 데이터를 제공합니다.") .version("v1.0.0")); openApi.addSecurityItem(new SecurityRequirement().addList("basicAuth")); }) .build(); } @Bean @ConditionalOnProperty(name = "app.environment", havingValue = "dev", matchIfMissing = true) public GroupedOpenApi bypassAccountApi() { return GroupedOpenApi.builder() .group("5. Bypass Account") .pathsToMatch("/api/bypass-account/**") .addOpenApiCustomizer(openApi -> openApi.info(new Info() .title("Bypass Account Management API") .description("Bypass API 계정 및 신청 관리 API") .version("v1.0.0"))) .build(); } @Bean public OpenAPI openAPI() { List servers = "prod".equals(environment) ? List.of( new Server() .url("https://guide.gc-si.dev" + contextPath) .description("GC 도메인")) : List.of( new Server() .url("http://localhost:" + serverPort + contextPath) .description("로컬 개발 서버"), new Server() .url("http://211.208.115.83:" + serverPort + contextPath) .description("중계 서버"), new Server() .url("https://guide.gc-si.dev" + contextPath) .description("GC 도메인")); return new OpenAPI() .info(defaultApiInfo()) .servers(servers) .components(new Components() .addSecuritySchemes("basicAuth", new SecurityScheme() .type(SecurityScheme.Type.HTTP) .scheme("basic") .description("Bypass API 접근 계정 (발급된 ID/PW 사용)"))); } private Info defaultApiInfo() { return new Info() .title("SNP Batch REST API") .description(""" ## SNP Batch 시스템 REST API 문서 해양 데이터 통합 배치 시스템의 REST API 문서입니다. ### 제공 API - **Batch Management API**: 배치 Job 실행, 이력 조회, 스케줄 관리 - **AIS Target API**: AIS 선박 위치 정보 조회 (캐시 기반, 공간/조건 검색) ### 주요 기능 - 배치 Job 실행 및 중지 - Job 실행 이력 조회 - 스케줄 관리 (Quartz) - AIS 선박 실시간 위치 조회 (MMSI 단건/다건, 시간/공간 범위 검색) - 항해 조건 필터 검색 (SOG, COG, Heading, 목적지, 항행상태) - 폴리곤/WKT 범위 검색, 거리 포함 검색, 항적 조회 ### 버전 정보 - API Version: v1.0.0 - Spring Boot: 3.2.1 - Spring Batch: 5.1.0 """) .version("v1.0.0") .contact(new Contact() .name("SNP Batch Team") .email("support@snp-batch.com") .url("https://github.com/snp-batch")) .license(new License() .name("Apache 2.0") .url("https://www.apache.org/licenses/LICENSE-2.0")); } }