Swagger 설정 개선 및 context-path 제거

주요 변경사항:
- 모든 서비스 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 <noreply@anthropic.com>
This commit is contained in:
hiondal 2025-09-09 01:32:24 +09:00
parent b489c73201
commit 6ca4daed8d
10 changed files with 243 additions and 40 deletions

View File

@ -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");
}
}

View File

@ -94,9 +94,8 @@ spring:
# 서버 설정 # 서버 설정
server: server:
port: ${SERVER_PORT:8081} port: ${SERVER_PORT:8082}
servlet: servlet:
context-path: /bill-service
encoding: encoding:
charset: UTF-8 charset: UTF-8
enabled: true enabled: true

View File

@ -1,45 +1,63 @@
package com.phonebill.kosmock.config; 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.OpenAPI;
import io.swagger.v3.oas.models.info.Contact; import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info; 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 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.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import java.util.List;
/** /**
* Swagger/OpenAPI 설정 * Swagger/OpenAPI 설정
* KOS Mock Service API 문서화를 위한 설정
*/ */
@Configuration @Configuration
public class SwaggerConfig { public class SwaggerConfig {
@Value("${server.servlet.context-path:/}")
private String contextPath;
@Bean @Bean
public OpenAPI kosMockOpenAPI() { public OpenAPI openAPI() {
return new OpenAPI() return new OpenAPI()
.info(new Info() .info(apiInfo())
.title("KOS Mock Service API") .addServersItem(new Server()
.description("KT 통신사 시스템(KOS-Order)을 모방한 Mock 서비스 API") .url("http://localhost:8084")
.version("v1.0.0") .description("Local Development"))
.contact(new Contact() .addServersItem(new Server()
.name("개발팀") .url("{protocol}://{host}:{port}")
.email("dev@phonebill.com")) .description("Custom Server")
.license(new License() .variables(new io.swagger.v3.oas.models.servers.ServerVariables()
.name("Internal Use Only") .addServerVariable("protocol", new io.swagger.v3.oas.models.servers.ServerVariable()
.url("http://www.phonebill.com/license"))) ._default("http")
.servers(List.of( .description("Protocol (http or https)")
new Server() .addEnumItem("http")
.url("http://localhost:8080" + contextPath) .addEnumItem("https"))
.description("개발 환경"), .addServerVariable("host", new io.swagger.v3.oas.models.servers.ServerVariable()
new Server() ._default("localhost")
.url("https://kos-mock.phonebill.com" + contextPath) .description("Server host"))
.description("운영 환경") .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");
} }
} }

View File

@ -5,9 +5,7 @@ spring:
active: dev active: dev
server: server:
port: ${SERVER_PORT:8080} port: ${SERVER_PORT:8084}
servlet:
context-path: /kos-mock
management: management:
endpoints: endpoints:

View File

@ -66,8 +66,9 @@ public class SecurityConfig {
// 권한 설정 // 권한 설정
.authorizeHttpRequests(authorize -> authorize .authorizeHttpRequests(authorize -> authorize
// Health Check 문서화 API는 인증 불필요 // Health Check 문서화 API는 인증 불필요
.requestMatchers("/actuator/health", "/actuator/info").permitAll() .requestMatchers("/actuator/**").permitAll()
.requestMatchers("/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html").permitAll() .requestMatchers("/v3/api-docs/**", "/api-docs/**", "/swagger-ui/**", "/swagger-ui.html").permitAll()
.requestMatchers("/swagger-resources/**", "/webjars/**").permitAll()
// OPTIONS 요청은 인증 불필요 (CORS Preflight) // OPTIONS 요청은 인증 불필요 (CORS Preflight)
.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll() .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()

View File

@ -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");
}
}

View File

@ -80,14 +80,11 @@ spring:
date-format: yyyy-MM-dd'T'HH:mm:ss date-format: yyyy-MM-dd'T'HH:mm:ss
# HTTP 설정 # HTTP 설정
webflux: webflux: {}
base-path: /api/v1
# Server 설정 # Server 설정
server: server:
port: ${SERVER_PORT:8083} port: ${SERVER_PORT:8083}
servlet:
context-path: /api/v1
compression: compression:
enabled: true enabled: true
mime-types: application/json,application/xml,text/html,text/xml,text/plain mime-types: application/json,application/xml,text/html,text/xml,text/plain

View File

@ -52,8 +52,11 @@ public class SecurityConfig {
"/actuator/info", "/actuator/info",
"/actuator/prometheus", "/actuator/prometheus",
"/v3/api-docs/**", "/v3/api-docs/**",
"/api-docs/**",
"/swagger-ui/**", "/swagger-ui/**",
"/swagger-ui.html" "/swagger-ui.html",
"/swagger-resources/**",
"/webjars/**"
).permitAll() ).permitAll()
// Protected endpoints (인증 필요) // Protected endpoints (인증 필요)

View File

@ -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");
}
}

View File

@ -32,8 +32,6 @@ spring:
# 서버 설정 # 서버 설정
server: server:
port: ${SERVER_PORT:8081} port: ${SERVER_PORT:8081}
servlet:
context-path: /api/v1
# JWT 토큰 설정 # JWT 토큰 설정
jwt: jwt: