본문 바로가기

개발공부/SPRING

[Spring] Swagger API 연동하기

💡 코드가 보이지 않으시다면 드래그 혹은 오른쪽 아래 🌜 아이콘을 눌러 테마 색을 변경해주세요.

 

 

안녕하세요!

키크니 개발자 입니다. 🦒

 

기존 프로젝트에서는 API 문서를 Spring Rest Doc으로 진행하다가,

이번에는 Swagger로 진행하였습니다. 진행하면서 참고 될 만한 것들을 적어보았습니다!

 

Swagger란?

  • Open Api Specification(OAS)를 위한 프레임워크이다.
  • API들이 가지고 있는 스펙(spec)을 명세, 관리할 수 있는 프로젝트/문서
  • API 사용 방법을 사용자에게 알려주는 문서
  • Springboot에서 Swagger를 사용하면, 컨트롤러에 명시된 어노테이션을 해석하여 API문서를 자동으로 만들어준다.
  • 참고로 Swagger는 Java에 종속된 라이브러리가 아니다.
  • URL에 /swagger-ui.heml으로 접근하면 swagger가 만들어주는 페이지에 접근할 수 있다.
  • 공식 사이트

Swagger를 설정하는 위한 라이브러리는 2가지가 있습니다.

Spring-Fox,  Spring-Doc 2가지 중에 사용하면 됩니다.

 

Spring-Fox

  • 약 2015년정도에 나온 라이브러리 입니다.
  • 2020년 이후로 업데이트가 되고 있지 않습니다.
  • 그래서 Spring Boot 2.6이상 버전에서는 바로 적용이 되지 않습니다.
  • 참고 URL

Spring-Doc

약 2019년에 나온 라이브러리 입니다.

업데이트가 최근까지도 이루어지고 있습니다.

Spring Boot 2.6이상 버전에서도 지원이 됩니다.

 

현재 Spring boot 2.7.1 버전으로

Spring-Fox로 Swgger를 적용했었는데 아래와 같은 에러가 발생하였습니다.

(Spring boot 2.6.x 버전에서도 같은 에러가 발생하였습니다.)

org.springframework.context.ApplicationContextException:
Failed to start bean 'documentationPluginsBootstrapper';
nested exception is java.lang.NullPointerException:
Cannot invoke "org.springframework.web.servlet.mvc.condition.PatternsRequestCondition.getPatterns()"
because "this.condition" is null

에러 해결 방법을 찾아보니 대부분 spring boot 2.6.0부터 요청 경로를 ControllerHandler에 매칭시키기 위한 전략의 기본값이 ant_path_matcher 전략 -> path_pattern_parser 전략으로 변경되었기 때문에 에러가 발생하는 것이고,

이를 해결하기 위해 application.properties 에서 아래와 같이 설정하는 것이었습니다.

spring.mvc.pathmatch.matching-strategy=ant_path_matcher

하지만 계속적으로 같은 에러가 발생하였습니다. 🥲

그 외로 @EnableSwagger2 어노테이션을 제거하는 방법, @EnableWebMvc로 적용하는 방법을 모두 사용하였지만

역시나 똑같은 에러가 발생하면서 되지 않았습니다.

대부분은 유지보수 되지 않고 버그가 많은 springfox 대신 springdoc 사용을 고려해 보라고 권장하기 때문에

springdoc으로 다시 적용해보자 했습니다.

 

SpringDoc Swagger 적용하기

Pom.xml, Build.gradle 의존성 추가하기

현재 spring boot 2.7.1 버전을 사용하고 있으며,

2.7.1 버전에 springdoc의 가장 최신 버전인 implementation 'org.springdoc:springdoc-openapi-ui:1.6.10' 를 적용했었는데,

아래와 같이 No operations defined in spec!  이 발생하였습니다. 이는 springdoc 버전을 1.5.7로 내리니까 해결되었습니다!

참고해주세요! 🥹

<!-- https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-ui -->
<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-ui</artifactId>
    <version>1.5.7</version>
</dependency>


// https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-ui
implementation 'org.springdoc:springdoc-openapi-ui:1.5.7'

Maven 또는 Gradle 의존성 추가입니다.

 

application.properties 파일 설정

# swaggerdoc
springdoc.packages-to-scan=com.example.swagger  // (1)
springdoc.swagger-ui.version=v1.0.0 // (2)
springdoc.swagger-ui.path=/api-docs  // (3)
springdoc.swagger-ui.tags-sorter=alpha
springdoc.swagger-ui.operations-sorter=alpha
springdoc.api-docs.path=/api-docs/json
springdoc.api-docs.groups.enabled=true
springdoc.cache.disabled=true

// (4)
springdoc.packages-to-exclude:	
springdoc.paths-to-exclude:

// (5) 
springdoc.api-docs.path: /api-docs/json
springdoc.api-docs.groups.enabled: true
springdoc.default-consumes-media-type=application/json;charset=UTF-8
springdoc.default-produces-media-type=application/json;charset=UTF-8

(1) swagger를 적용하기 위해 스캔할 패키지를 지정합니다.

(2) 이어서 나올 내용인 OpenAPI bean 등록 시 사용됩니다.

(3) swagger-ui를 연결할 주소를 지정할 수 있으며, 지정하지 않았을 경우에는 localhost:{post}/swagger-ui/index.html의 경로로 접근할 수 있습니다. 현재는 /api-docs를 경로로 지정했기 떄문에 실행 후 해당 경로로 접근하면 swagger가 적용된 것을 볼 수 있습니다.

나머지 그 아래 설정들은 정렬 방식, 캐시, consumes, produces 타입에 관련 된 것입니다.

(4) 혹시나 제외하고 싶은 package나 path가 있으면 사용하면 됩니다.

(5) 저같은 경우는 4가지를 설정해주지 않으면 아래와 화면이 보여졌습니다.

(기본적인 옵션들이며, 더 자세한 옵션들과 내용들은 포스팅 맨 하당 공식 문서를 참고 부탁드리겠습니다!)

 

OpenAPI bean 등록

@Configuration
public class OpenApiConfig {

  @Bean
  public OpenAPI openAPI(@Value("${springdoc.version}") String springdocVersion) {
    Info info = new Info()
        .title("타이틀 입력")
        .version(springdocVersion)
        .description("API에 대한 설명 부분");

    return new OpenAPI()
        .components(new Components())
        .info(info);
  }
}

OpenAPI bean을 등록하기 위해 Configuration 클래스를 생성합니다.

OpenAPI bean에 관한 내용 역시 가장 기본적인 title, version, description에 대한 것만 담았으며,

@Value 어노테이션을 통해 application.properties에서 등록한 springdoc.swagger-ui.version 값을 가지고 오는 것을 확인할 수 있습니다.

 

@Controller 설정

@Tag(name = "인증", description = "인증 관련 api 입니다.")	// (1) 
@RestController
@RequestMapping("/api/auth")
public class AuthController {

    @Operation(summary = "로그인 메서드", description = "로그인 메서드입니다.")	// (2)
    @ApiResponses(value = {	// (3)
    	// (4)
        @ApiResponse(responseCode = "200", description = "successful operation", content = @Content(schema = @Schema(implementation = LoginResponse.class))),
        @ApiResponse(responseCode = "400", description = "bad request operation", content = @Content(schema = @Schema(implementation = LoginResponse.class)))
    })
    @PostMapping(value = "login")
    public ResponseEntity<LoginResponse> login(LoginRequest loginRequest) {
        LoginResponse loginResponse = new LoginResponse("accessTokenValue", "refreshTokenValue");
        return ResponseEntity.ok().body(loginResponse);
    }
}

(1) @Tag : api 그룹 설정을 위한 어노테이션 입니다.

name 속성으로 태그의 이름을 설정할 수 있고, description 속성으로 태그에 대한 설명을 추가할 수 있습니다.

@Tag에 설정된 name이 같은 것 끼리 하나의 api 그룹으로 묶게 됩니다.

 

(2) @Operation : api 상세 정보를 위한 어노테이션 입니다.

summary 속성으로 api에 대한 간략한 설명, description 속성으로 api에 대한 상세 설명을 추가할 수 있으며, responses, parameters 속성 등을 추가로 적용할 수 있습니다.

 

(3) @ApiResponses : 바로 아래에서 설명하는 여러 개의 @ApiReponse를 묶기 위한 어노테이션 입니다.

 

(4)@ApiResponse : api의 response 설정을 위한 어노테이션 입니다.

responseCode 속성으로 http 상태 코드를 설정할 수 있고, description으로 response에 대한 설명을 추가할 수 있습니다. @ApiResponse 설정을 통해 응답 결과로 나올 수 있는 response 구조를 미리 확인할 수 있게 됩니다.

api 조회 성공 및 실패 시 발생될 상태 코드 및 Response 구조를 설정하고자 할 때 유용하게 사용될 수 있습니다.

(implementation에는 responseBody로 제공될 클래스 타입만 설정할 수 있습니다.)

 

그외 예시에는 없지만 

@Parameter : api parameter 설정을 위한 어노테이션 입니다.

name으로 파라미터의 이름, description으로 설명, in으로 파라미터의 위치를 설정할 수 있습니다.

 

Request, Response 객체 설정

@Getter
public static class LoginRequest {
    @Schema(description = "아이디", defaultValue = "testId")	// (1)
    public String id;
    @Schema(description = "비밀번호", defaultValue = "testPassword")
    public String password;
}
  
@Getter
@AllArgsConstructor
public static class LoginResponse {
    @Schema(description = "엑세스 토큰")
    private String accessToken;
    @Schema(description = "리프레시 토큰")
    private String refreshToken;
}

(1) @Schema : Request, Response 객체에 대한 설정을 위한 어노테이션 입니다.

description으로 설명을 추가할 수 있고, defaultValue으로 기본적으로 사용할 값을 설정할 수 있으며, example을 통해 예시를 설정할 수도 있습니다.

 

 

정말 기본이 되는 어노테이션과 옵션들만 적용했기 때문에 추가적으로 필요한 부분은 아래 공식 문서를 참고하여 추가로 적용해주시면 됩니다.

 

 

 

References

https://springdoc.org/

https://doozi316.github.io/web/2020/10/16/WEB29/

https://shanepark.tistory.com/366

https://velog.io/@ohjinseo/SpringBoot-2.6-%EC%9D%B4%EC%83%81-springfox-swagger3.0-%EC%A0%81%EC%9A%A9-%EC%8B%9C-%EC%97%90%EB%9F%AC-%ED%95%B4%EA%B2%B0

https://wildeveloperetrain.tistory.com/156

 

 

 

 

 

반응형