본문 바로가기
개발

Swagger 적용하기 - spring fox

by 공덕뉸나 2023. 7. 17.

실무를 하면서 프론트 작업을 하는 동료들에게 API 문서를 넘겨줘야 할 일이 있었다.

원래는 Spring docs를 사용했었는데 테스트 코드를 하나하나 짜야했고 개발 일정이 길지도 않고 복잡한 코드가 별로 없어서 Swagger를 적용하게 되었다.

swagger에 대한 사전 지식이나 샘플 코드 없이 설정하려니 헤매는 일이 좀 있었다. 

나는 SpringBoot 2.X 버전에서 사용한 것이고 SpringBoot 3부터는 내가 적용한 swagger 설정 방식과는 다르므로 참고하자.

 

1. application.yml 설정하기

spring:
	mvc:
    	pathmatch:
        	matching-strategy: ant_path_matcher

SpringBoot 2.6 버전 이후에 spring.mvc.pathmatch.matching-strategy 값이 ant_path_matcher에서 path_pattern_parser로 변경되면서 몇몇 라이브러리에 오류가 발생할 수도 있다.

이를 해결하기 위해서 application.yml 파일에 설정을 추가했다.

 

2. build.gradle 추가

implementation 'io.springfox:springfox-boot-starter:3.0.0'
implementation 'io.springfox:springfox-swagger-ui:3.0.0'

 

 

3. SwaggerConfig.java 생성

@EnableWebMvc
@EnableSwagger2
@Configuration
public class SwaggerConfig {
    @Bean
    public Docket api() {
        Server serverLocal = new Server("local", "http://localhost:포트번호", 
        "for local usages", Collections.emptyList(), Collections.emptyList());
        Server testServer = new Server("test", "실서버 주소", "for testing", 
        Collections.emptyList(), Collections.emptyList());
        return new Docket(DocumentationType.OAS_30)
            .servers(serverLocal, testServer)
            .useDefaultResponseMessages(false)
            .select()
            .apis(RequestHandlerSelectors.basePackage("패키지명"))
            .paths(PathSelectors.any())
            .build()
            .apiInfo(apiInfo());
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
            .title("Swagger Test")
            .description("SwaggerConfig")
            .version("3.0")
            .build();
    }
}

local에서만 swagger를 실행하려면 Server를 생성할 필요는 없다.

내가 다녔던 회사에서는 테스트 서버와 실서버를 분리해서 테스트를 했기 때문에 테스트 서버에서 실행하기 위해 Server를 분리해서 설정해주었다.

 

실서버에서도 API 문서를 보고 싶다면 Workaround 파일을 생성하여 설정해주어야한다.

위의 코드에서 localServer와 testServer를 추가하지 않으면 실서버에서 swagger index.html 문서를 실행했을 때 https에서 http를 호출해 에러가 나는 경험을 했다.

이를 해결하기 위해서 "https://도메인" 와 같이 https로 실서버 주소를 넣어줘야 한다.

 

4. Workaround.java 생성

@Component
public class Workaround implements WebMvcOpenApiTransformationFilter {
    @Override
    public OpenAPI transform(OpenApiTransformationContext<HttpServletRequest> context) {
        OpenAPI openApi = context.getSpecification();
        Server localServer = new Server();
        localServer.setDescription("local");
        localServer.setUrl("http://localhost:포트번호");

        Server testServer = new Server();
        testServer.setDescription("test");
        testServer.setUrl("실서버 주소");
        openApi.setServers(Arrays.asList(localServer, testServer));
        return openApi;
    }

    @Override
    public boolean supports(DocumentationType documentationType) {
        return documentationType.equals(DocumentationType.OAS_30);
    }
}

 

5. WebSecurityConfig.java 설정 추가

 

String[] permitAllUrl = {"/swagger-ui.html", "/swagger-ui.html/**", 
"/v3/api-docs","/swagger-ui/**", "/swagger*/**", "/api-docs", "/api-docs/**"};

허용되는 URL 경로를 설정해줘야 한다.

 

모든 설정이 끝나면 local의 경우 http://localhost:포트번호/swagger-ui/index.html 

테스트 서버의 경우 https://서버주소/swagger-ui/index.html 로 확인 가능하다.

이것은 주소/v3/api-docs 을 html로 변환시켜주는 것이다.

 

6. Swagger에서 JWT 관련 header 추가하는 방법

보통 개발을 할 때 로그인 기능이 있다. 이 때 JWT를 사용했는데 header에 토근 값이 필요한 API를 swagger에서 그냥 실행하면 에러가 났다.

따라서 SwaggerConfig 파일에 설정을 한 뒤 API를 테스트 해야 한다.

 

(1) SwaggerConfig.java

 

private SecurityContext securityContext() {
    return SecurityContext.builder()
        .securityReferences(defaultAuth())
        .build();
}

private List<SecurityReference> defaultAuth() {
    AuthorizationScope authorizationScope = new AuthorizationScope("global", 
    "accessEverything");
    AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
    authorizationScopes[0] = authorizationScope;
    return Arrays.asList(new SecurityReference("Authorization", authorizationScopes));
}

private ApiKey apiKey() {
    return new ApiKey("Authorization", "Authorization", "header");
}

@Bean
    public Docket api() {
        Server serverLocal = new Server("local", "http://localhost:포트번호", 
        "for local usages", Collections.emptyList(), Collections.emptyList());
        Server testServer = new Server("test", "실서버 주소", "for testing",
        Collections.emptyList(), Collections.emptyList());

        return new Docket(DocumentationType.OAS_30)
            .securityContexts(Arrays.asList(securityContext()))
            .securitySchemes(Arrays.asList(apiKey()))
            .servers(serverLocal, testServer)
            .useDefaultResponseMessages(false)
            .select()
            .apis(RequestHandlerSelectors.basePackage("패키지명"))
            .paths(PathSelectors.any())
            .build()
            .apiInfo(apiInfo());
    }

 

(2) Swagger API 문서

SwaggerConfig 파일에 header를 추가하고 나면 Swagger 문서에서 Authorize 버튼이 생성된다.

여기에 토큰 값을 입력해야 API 테스트가 가능하다.

 

7. Swagger Annotation 적용

(1) @Api

컨트롤러에서 사용되는 것으로 클래스를 swagger의 리소스로 표시한다.

tags를 통해서 리소스명을 지정한다.

(2) @ApiOperation

컨트롤러에서 사용되는 것으로 해당 컨트롤러 안 method의 설명을 추가할 수 있다.

(3) @ApiModelProperty

DTO에서 사용되는 것으로 해당 파라미터에 대한 example 값이 추가된다.

 

SwaggerConfig, Workaround 파일 설정 참고 URL

https://lusida-coding.tistory.com/129 

 

Swagger 서버에 배포시 curl 수정

개요 Swagger를 서버에 배포했을 때 기존 코드로 API 명세서를 실행시키면 curl이 curl -x GET “https://127.0.0.1:8081/”로 실행이 되어서 상태 코드 200인데 안에 데이터가 비어있는 오류가 발생했다. 이를

lusida-coding.tistory.com

 

여기까지가 내가 Swagger를 적용했던 방식이고 나중에는 SpringBoot3에서 적용하는 방법도 알아와보도록 해야겠다.

혹시 나처럼 실서버에서 실행이 안되거나 Swagger를 처음 접한 사람들이 많이 헤매지 않길 바란다. 망망!