package com.snp.batch.global.config; 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.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:8031/snp-global/swagger-ui/index.html * - API 문서 (JSON): http://localhost:8031/snp-global/v3/api-docs * - API 문서 (YAML): http://localhost:8031/snp-global/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 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/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")); }) .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); } private Info defaultApiInfo() { return new Info() .title("SNP Global REST API") .description(""" ## S&P Global API - Risk & Compliance 서비스 S&P Global Maritime 데이터 서비스 REST API 문서입니다. ### 제공 API - **Bypass API**: S&P Global 선박/해운 데이터 조회 - **Bypass Config API**: Bypass API 설정 관리 - **Screening Guide API**: Risk & Compliance 스크리닝 가이드 - **Bypass Account API**: API 계정 관리 ### 버전 정보 - API Version: v1.0.0 - Spring Boot: 3.2.1 """) .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")); } }