From 6ca4daed8dda231b261941a76dc0d6db4fc544fe Mon Sep 17 00:00:00 2001 From: hiondal Date: Tue, 9 Sep 2025 01:32:24 +0900 Subject: [PATCH] =?UTF-8?q?Swagger=20=EC=84=A4=EC=A0=95=20=EA=B0=9C?= =?UTF-8?q?=EC=84=A0=20=EB=B0=8F=20context-path=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 주요 변경사항: - 모든 서비스 context-path 제거 (user-service: /api/v1, bill-service: /bill-service, product-service: /api/v1, kos-mock: /kos-mock) - 포트 번호 조정 (bill-service: 8082, kos-mock: 8084) - 모든 서비스에 표준화된 SwaggerConfig 클래스 추가 - SecurityConfig에서 Swagger 관련 URL 무인증 처리 개선 - JWT Bearer Authentication 스키마 추가 - 서버 URL 설정 및 커스텀 변수 지원 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .../phonebill/bill/config/SwaggerConfig.java | 63 +++++++++++++++++ .../src/main/resources/application.yml | 3 +- .../kosmock/config/SwaggerConfig.java | 70 ++++++++++++------- kos-mock/src/main/resources/application.yml | 4 +- .../product/config/SecurityConfig.java | 5 +- .../product/config/SwaggerConfig.java | 63 +++++++++++++++++ .../src/main/resources/application.yml | 5 +- .../phonebill/user/config/SecurityConfig.java | 5 +- .../phonebill/user/config/SwaggerConfig.java | 63 +++++++++++++++++ .../src/main/resources/application.yml | 2 - 10 files changed, 243 insertions(+), 40 deletions(-) create mode 100644 bill-service/src/main/java/com/phonebill/bill/config/SwaggerConfig.java create mode 100644 product-service/src/main/java/com/unicorn/phonebill/product/config/SwaggerConfig.java create mode 100644 user-service/src/main/java/com/phonebill/user/config/SwaggerConfig.java diff --git a/bill-service/src/main/java/com/phonebill/bill/config/SwaggerConfig.java b/bill-service/src/main/java/com/phonebill/bill/config/SwaggerConfig.java new file mode 100644 index 0000000..2249705 --- /dev/null +++ b/bill-service/src/main/java/com/phonebill/bill/config/SwaggerConfig.java @@ -0,0 +1,63 @@ +package com.phonebill.bill.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.security.SecurityRequirement; +import io.swagger.v3.oas.models.security.SecurityScheme; +import io.swagger.v3.oas.models.servers.Server; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * Swagger/OpenAPI 설정 + * Bill Service API 문서화를 위한 설정 + */ +@Configuration +public class SwaggerConfig { + + @Bean + public OpenAPI openAPI() { + return new OpenAPI() + .info(apiInfo()) + .addServersItem(new Server() + .url("http://localhost:8082") + .description("Local Development")) + .addServersItem(new Server() + .url("{protocol}://{host}:{port}") + .description("Custom Server") + .variables(new io.swagger.v3.oas.models.servers.ServerVariables() + .addServerVariable("protocol", new io.swagger.v3.oas.models.servers.ServerVariable() + ._default("http") + .description("Protocol (http or https)") + .addEnumItem("http") + .addEnumItem("https")) + .addServerVariable("host", new io.swagger.v3.oas.models.servers.ServerVariable() + ._default("localhost") + .description("Server host")) + .addServerVariable("port", new io.swagger.v3.oas.models.servers.ServerVariable() + ._default("8082") + .description("Server port")))) + .addSecurityItem(new SecurityRequirement().addList("Bearer Authentication")) + .components(new Components() + .addSecuritySchemes("Bearer Authentication", createAPIKeyScheme())); + } + + private Info apiInfo() { + return new Info() + .title("Bill Service API") + .description("통신요금 관리 서비스 - 요금 조회 및 관리 API") + .version("1.0.0") + .contact(new Contact() + .name("PhoneBill Development Team") + .email("dev@phonebill.com")); + } + + private SecurityScheme createAPIKeyScheme() { + return new SecurityScheme() + .type(SecurityScheme.Type.HTTP) + .bearerFormat("JWT") + .scheme("bearer"); + } +} \ No newline at end of file diff --git a/bill-service/src/main/resources/application.yml b/bill-service/src/main/resources/application.yml index 485b11b..2e1f40a 100644 --- a/bill-service/src/main/resources/application.yml +++ b/bill-service/src/main/resources/application.yml @@ -94,9 +94,8 @@ spring: # 서버 설정 server: - port: ${SERVER_PORT:8081} + port: ${SERVER_PORT:8082} servlet: - context-path: /bill-service encoding: charset: UTF-8 enabled: true diff --git a/kos-mock/src/main/java/com/phonebill/kosmock/config/SwaggerConfig.java b/kos-mock/src/main/java/com/phonebill/kosmock/config/SwaggerConfig.java index fde5984..a69804d 100644 --- a/kos-mock/src/main/java/com/phonebill/kosmock/config/SwaggerConfig.java +++ b/kos-mock/src/main/java/com/phonebill/kosmock/config/SwaggerConfig.java @@ -1,45 +1,63 @@ package com.phonebill.kosmock.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.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import java.util.List; - /** * Swagger/OpenAPI 설정 + * KOS Mock Service API 문서화를 위한 설정 */ @Configuration public class SwaggerConfig { - @Value("${server.servlet.context-path:/}") - private String contextPath; - @Bean - public OpenAPI kosMockOpenAPI() { + public OpenAPI openAPI() { return new OpenAPI() - .info(new Info() - .title("KOS Mock Service API") - .description("KT 통신사 시스템(KOS-Order)을 모방한 Mock 서비스 API") - .version("v1.0.0") - .contact(new Contact() - .name("개발팀") - .email("dev@phonebill.com")) - .license(new License() - .name("Internal Use Only") - .url("http://www.phonebill.com/license"))) - .servers(List.of( - new Server() - .url("http://localhost:8080" + contextPath) - .description("개발 환경"), - new Server() - .url("https://kos-mock.phonebill.com" + contextPath) - .description("운영 환경") - )); + .info(apiInfo()) + .addServersItem(new Server() + .url("http://localhost:8084") + .description("Local Development")) + .addServersItem(new Server() + .url("{protocol}://{host}:{port}") + .description("Custom Server") + .variables(new io.swagger.v3.oas.models.servers.ServerVariables() + .addServerVariable("protocol", new io.swagger.v3.oas.models.servers.ServerVariable() + ._default("http") + .description("Protocol (http or https)") + .addEnumItem("http") + .addEnumItem("https")) + .addServerVariable("host", new io.swagger.v3.oas.models.servers.ServerVariable() + ._default("localhost") + .description("Server host")) + .addServerVariable("port", new io.swagger.v3.oas.models.servers.ServerVariable() + ._default("8084") + .description("Server port")))) + .addSecurityItem(new SecurityRequirement().addList("Bearer Authentication")) + .components(new Components() + .addSecuritySchemes("Bearer Authentication", createAPIKeyScheme())); + } + + private Info apiInfo() { + return new Info() + .title("KOS Mock Service API") + .description("통신요금 관리 서비스 - KOS 시스템 Mock API") + .version("1.0.0") + .contact(new Contact() + .name("PhoneBill Development Team") + .email("dev@phonebill.com")); + } + + private SecurityScheme createAPIKeyScheme() { + return new SecurityScheme() + .type(SecurityScheme.Type.HTTP) + .bearerFormat("JWT") + .scheme("bearer"); } } \ No newline at end of file diff --git a/kos-mock/src/main/resources/application.yml b/kos-mock/src/main/resources/application.yml index a0cd182..ed22fe2 100644 --- a/kos-mock/src/main/resources/application.yml +++ b/kos-mock/src/main/resources/application.yml @@ -5,9 +5,7 @@ spring: active: dev server: - port: ${SERVER_PORT:8080} - servlet: - context-path: /kos-mock + port: ${SERVER_PORT:8084} management: endpoints: diff --git a/product-service/src/main/java/com/unicorn/phonebill/product/config/SecurityConfig.java b/product-service/src/main/java/com/unicorn/phonebill/product/config/SecurityConfig.java index 64b7269..3d6303c 100644 --- a/product-service/src/main/java/com/unicorn/phonebill/product/config/SecurityConfig.java +++ b/product-service/src/main/java/com/unicorn/phonebill/product/config/SecurityConfig.java @@ -66,8 +66,9 @@ public class SecurityConfig { // 권한 설정 .authorizeHttpRequests(authorize -> authorize // Health Check 및 문서화 API는 인증 불필요 - .requestMatchers("/actuator/health", "/actuator/info").permitAll() - .requestMatchers("/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html").permitAll() + .requestMatchers("/actuator/**").permitAll() + .requestMatchers("/v3/api-docs/**", "/api-docs/**", "/swagger-ui/**", "/swagger-ui.html").permitAll() + .requestMatchers("/swagger-resources/**", "/webjars/**").permitAll() // OPTIONS 요청은 인증 불필요 (CORS Preflight) .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll() diff --git a/product-service/src/main/java/com/unicorn/phonebill/product/config/SwaggerConfig.java b/product-service/src/main/java/com/unicorn/phonebill/product/config/SwaggerConfig.java new file mode 100644 index 0000000..b5bc481 --- /dev/null +++ b/product-service/src/main/java/com/unicorn/phonebill/product/config/SwaggerConfig.java @@ -0,0 +1,63 @@ +package com.unicorn.phonebill.product.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.security.SecurityRequirement; +import io.swagger.v3.oas.models.security.SecurityScheme; +import io.swagger.v3.oas.models.servers.Server; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * Swagger/OpenAPI 설정 + * Product Service API 문서화를 위한 설정 + */ +@Configuration +public class SwaggerConfig { + + @Bean + public OpenAPI openAPI() { + return new OpenAPI() + .info(apiInfo()) + .addServersItem(new Server() + .url("http://localhost:8083") + .description("Local Development")) + .addServersItem(new Server() + .url("{protocol}://{host}:{port}") + .description("Custom Server") + .variables(new io.swagger.v3.oas.models.servers.ServerVariables() + .addServerVariable("protocol", new io.swagger.v3.oas.models.servers.ServerVariable() + ._default("http") + .description("Protocol (http or https)") + .addEnumItem("http") + .addEnumItem("https")) + .addServerVariable("host", new io.swagger.v3.oas.models.servers.ServerVariable() + ._default("localhost") + .description("Server host")) + .addServerVariable("port", new io.swagger.v3.oas.models.servers.ServerVariable() + ._default("8083") + .description("Server port")))) + .addSecurityItem(new SecurityRequirement().addList("Bearer Authentication")) + .components(new Components() + .addSecuritySchemes("Bearer Authentication", createAPIKeyScheme())); + } + + private Info apiInfo() { + return new Info() + .title("Product Service API") + .description("통신요금 관리 서비스 - 상품 변경 및 관리 API") + .version("1.0.0") + .contact(new Contact() + .name("PhoneBill Development Team") + .email("dev@phonebill.com")); + } + + private SecurityScheme createAPIKeyScheme() { + return new SecurityScheme() + .type(SecurityScheme.Type.HTTP) + .bearerFormat("JWT") + .scheme("bearer"); + } +} \ No newline at end of file diff --git a/product-service/src/main/resources/application.yml b/product-service/src/main/resources/application.yml index 262831e..dc10ee0 100644 --- a/product-service/src/main/resources/application.yml +++ b/product-service/src/main/resources/application.yml @@ -80,14 +80,11 @@ spring: date-format: yyyy-MM-dd'T'HH:mm:ss # HTTP 설정 - webflux: - base-path: /api/v1 + webflux: {} # Server 설정 server: port: ${SERVER_PORT:8083} - servlet: - context-path: /api/v1 compression: enabled: true mime-types: application/json,application/xml,text/html,text/xml,text/plain diff --git a/user-service/src/main/java/com/phonebill/user/config/SecurityConfig.java b/user-service/src/main/java/com/phonebill/user/config/SecurityConfig.java index c8262fe..22289bf 100644 --- a/user-service/src/main/java/com/phonebill/user/config/SecurityConfig.java +++ b/user-service/src/main/java/com/phonebill/user/config/SecurityConfig.java @@ -52,8 +52,11 @@ public class SecurityConfig { "/actuator/info", "/actuator/prometheus", "/v3/api-docs/**", + "/api-docs/**", "/swagger-ui/**", - "/swagger-ui.html" + "/swagger-ui.html", + "/swagger-resources/**", + "/webjars/**" ).permitAll() // Protected endpoints (인증 필요) diff --git a/user-service/src/main/java/com/phonebill/user/config/SwaggerConfig.java b/user-service/src/main/java/com/phonebill/user/config/SwaggerConfig.java new file mode 100644 index 0000000..0e429fa --- /dev/null +++ b/user-service/src/main/java/com/phonebill/user/config/SwaggerConfig.java @@ -0,0 +1,63 @@ +package com.phonebill.user.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.security.SecurityRequirement; +import io.swagger.v3.oas.models.security.SecurityScheme; +import io.swagger.v3.oas.models.servers.Server; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * Swagger/OpenAPI 설정 + * User Service API 문서화를 위한 설정 + */ +@Configuration +public class SwaggerConfig { + + @Bean + public OpenAPI openAPI() { + return new OpenAPI() + .info(apiInfo()) + .addServersItem(new Server() + .url("http://localhost:8081") + .description("Local Development")) + .addServersItem(new Server() + .url("{protocol}://{host}:{port}") + .description("Custom Server") + .variables(new io.swagger.v3.oas.models.servers.ServerVariables() + .addServerVariable("protocol", new io.swagger.v3.oas.models.servers.ServerVariable() + ._default("http") + .description("Protocol (http or https)") + .addEnumItem("http") + .addEnumItem("https")) + .addServerVariable("host", new io.swagger.v3.oas.models.servers.ServerVariable() + ._default("localhost") + .description("Server host")) + .addServerVariable("port", new io.swagger.v3.oas.models.servers.ServerVariable() + ._default("8081") + .description("Server port")))) + .addSecurityItem(new SecurityRequirement().addList("Bearer Authentication")) + .components(new Components() + .addSecuritySchemes("Bearer Authentication", createAPIKeyScheme())); + } + + private Info apiInfo() { + return new Info() + .title("User Service API") + .description("통신요금 관리 서비스 - 사용자 인증 및 관리 API") + .version("1.0.0") + .contact(new Contact() + .name("PhoneBill Development Team") + .email("dev@phonebill.com")); + } + + private SecurityScheme createAPIKeyScheme() { + return new SecurityScheme() + .type(SecurityScheme.Type.HTTP) + .bearerFormat("JWT") + .scheme("bearer"); + } +} \ No newline at end of file diff --git a/user-service/src/main/resources/application.yml b/user-service/src/main/resources/application.yml index 6796e41..c40789c 100644 --- a/user-service/src/main/resources/application.yml +++ b/user-service/src/main/resources/application.yml @@ -32,8 +32,6 @@ spring: # 서버 설정 server: port: ${SERVER_PORT:8081} - servlet: - context-path: /api/v1 # JWT 토큰 설정 jwt: