본문 바로가기

spring

Springdoc을 이용해서 Swagger API 만들기

들어가면서

API 문서를 수정하는 것은 좀 귀찮다. API 수정 사항이 있으면 문서를 수정하고 코드도 수정하고 두 번 수정을 해야 하는데
코드의 의도가 자동으로 문서에 반영되면 한 번의 코드 수정으로 문서까지 수정할 수 있다.
이런 수요 때문에 API 자동화 도구들이 생기게 된 것이 아닌가 싶다.

그중에서 Swagger는 사용자 친화적인 예쁜 UI를 가지고 있고 문서에서 직접 API 요청을 만들 수 있어서 매우 유용하다.
Spring에서 이 Swagger를 통합해서 사용할 수 있도록 개발된 라이브러리를 이용해서 API를 자동화를 구현해 보자.

장점

  • 예쁜 UI
  • 확장성이 좋다.
  • 문서에서 HTTP 요청 생성 가능

단점

  • 코드가 오염돼서 로직을 파악하기가 힘들다.
  • 자동으로 생성되었지만 개발자의 실수로 문서의 내용이 틀릴 수 있다.

설정 방법

글 작성일을 기준으로 최신 버전을 사용했다.

  • build.gradle에 해당 의존성을 추가한다.
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0'
  • 스프링을 가동한 이후에 다음 url로 접근하면 swagger 문서를 볼 수 있다.
http://localhost:8080/swagger-ui/index.html

접근 경로를 변경하거나 하는 설정은 공식 문서에서 살펴보자.

Intro 명세

처음 API 명세서를 보여주는 소개글을 적을 수 있다.
이를 위해서 Swagger 설정을 해주는 OpenAPI 클래스 빈을 등록하면 된다.

  • 예시
@Bean
public OpenAPI openAPI(@Value("${springdoc.version}") String appVersion){
        Info info=new Info()
        	.title("내일배움캠프 익명 게시판 서버 만들기")
       		.version(appVersion)
        	.description("이렇게 하는거 맞나요?")
        	.contact(new Contact()
        	.name("donggeun yu")
        	.url("https://github.com/yudonggeun")
        	.email("ydong98@gmail.com"))
        	.license(new License()
        	.name("Apache License Version 2.0")
        	.url("http://www.apache.org/licenses/LICENSE-2.0")
        );

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

이런 설정을 하면 다음 결과물이 나온다.

Parameter 명세

파라미터의 명세를 나타내기 위해서는 @Parameter 어노테이션을 사용한다.
파라미터 어노테이션에 정의된 속성을 사용해서 문서를 만들어주면 된다.

속성 설명
name 실제 요청에서 사용하는 파라미터의 변수의 이름을 설정하는 속성
description 문서에서 어떤 파라미터인지 설명하는 속성
example 가상의 요청을 생성할 때 사용되는 기본값
required 필수값 여부를 나타내는 값
  • 예시 1
@Parameter(name = "id", description = "게시글 id", required = true)
  • 예시 2
@Parameters({
        @Parameter(name = "size", description = "페이지 사이즈 default : 10", example = "10", required = true),
        @Parameter(name = "page", description = "페이지 인덱스 default : 0", example = "0"),
})

Request 명세

Request Header 명세 (Authorization)

스프링 시큐리티를 적용하면 필터에서 header를 통해서 인가 여부를 확인할 수 있는데.. 이때 swagger를 통해서 인증 헤더를 문서화하는 방법을 알아보자.

다음 그림은 swagger 문서에서 인증/인가 스키마에 대한 목록이다. 이러한 인증 방법은 @SecurityScheme 어노테이션을 통해서 문서 자동화를 구현할 수 있다. 예제는 JWT 토큰 인증을 문서화를 다루었다.

 

1. 헤더에 사용되는 인가 헤더 정의하기

@Configuration
@SecurityScheme(
        name = "Bearer Authentication",
        type = SecuritySchemeType.HTTP,
        bearerFormat = "JWT",
        scheme = "bearer"
)
public class SwaggerConfig {
}

스웨거 설정 클래스에서 인증/인가 헤더를 정의한다.

 

2. 컨트롤러에 적용하기

@SecurityRequirement(name = "Bearer Authentication")

정의된 인증 헤더를 적용하기 위해서 다음 어노테이션을 원하는 메서드나 클래스 단위에 적용하면 문서에 반영된다.

Request Body 명세

Http 요청의 body 부분에서 json 형태의 데이터를 받을 때, dto 객체를 선언해서 매핑을 한다.
dto 타입으로 사용하는 객체에 @Scheme어노테이션을 사용해서 문서를 만든다.
@Scheme 어노테이션은 스키마(골격)에 대한 명세를 만들어주어서 문서에 적용해 준다.

속성 설명
description 문서에서 어떤 값인지 설명하는 속성
example 가상의 요청을 생성할 때 사용되는 기본값
  • 예시
public record UpdateBoardRequest(

        @Schema(description = "게시글 id", example = "1")
        Long id,
        @Schema(description = "게시글 제목", example = "고양이 좋아")
        String title,
        @Schema(description = "작성자", example = "현실일상님")
        String author,
        @Schema(description = "비밀번호", example = "1234")
        String password,
        @Schema(description = "게시글 내용", example = "근데 댕댕이가 더 좋아")
        String content
) {
}

Response Body 명세

응답 역시 @Scheme를 사용해서 명세를 작성하지만 응답은 사용자의 요청에 따라서 서버의 상태에 따라서 다른 응답을 하는 경우가 있다.
이를 문서에 녹이기 위한 방법이 필요한데 이것이 ApiResponse이다.

속성 설명
responseCode 응답 상태 코드를 설정하는 속성 ( ex: 200, 404 )
description 어떤 상황에 반환되는 응답인지 설명
content 응답시 어떤 컨텐츠(body)를 반환하는지에 대한 정보
headers 응답 헤더 관련 정보

여기 content 속성에는 @Content정보를 입력하는데 이 어노테이션의 schema 속성에 @Schema를 사용해서
어떤 상황에서 이런 응답을 하는지 문서화할 수 있다.

  • 예시
// FailResponse 는 만든 클래스
@ApiResponses({
            @ApiResponse(responseCode = "200", description = "로그인 성공"
            	headers = @Header(name = "Authorization", description = "Bearer jwt 토큰을 정보입니다.")),
            @ApiResponse(responseCode = "400", description = "필수 정보 누락", 
            	content = @Content(schema = @Schema(implementation = FailResponse.class))),
            @ApiResponse(responseCode = "403", description = "비밀번호가 잘못됨", 
            	content = @Content(schema = @Schema(implementation = FailResponse.class))),
    })

Global Setting

이렇게 문서화를 위한 어노테이션을 설정했지만 contentType이 application/json으로 문서에 반영되지 않았다.
각 API 요청마다 커스텀하는 방법도 있지만 이번에 만드는 서버는 API 서버이기 때문에 글로벌 설정으로 반영을 했다.

  • 예시
springdoc:
  default-consumes-media-type: application/json
  default-produces-media-type: application/json

사용법

만든 API 문서는 특별한 설정을 하지 않는다면 http://localhost:8080/swagger-ui/index.html을 통해서 조회할 수 있다.
만들어진 문서에서 아래의 그림처럼 HTTP 요청을 만들어서 바로 서버에게 요청할 수 있고 데이터를 바꾸어서 요청할 수도 있어서 편하게 테스트를 할 수 있다.

Result

완성된 결과물 코드 저장소다.

 

GitHub - yudonggeun/simple_board

Contribute to yudonggeun/simple_board development by creating an account on GitHub.

github.com

ISSUE

1. ControllerAdvice로 처리한 전체 예외 처리 전략이 모든 API의 문서에 기록되는 문제

@Hidden 어노테이션을 사용하면 문제를 해결할 수 있다.

 

Reference

v1버전의 스택을 v2에서 통합해서 도움이 된다.

 

springdoc-openapi v1.7.0

springdoc-openapi java library helps to automate the generation of API documentation using spring boot projects. springdoc-openapi works by examining an application at runtime to infer API semantics based on spring configurations, class structure and vario

springdoc.org

 

OpenAPI 3 Library for spring-boot

Library for OpenAPI 3 with spring boot projects. Is based on swagger-ui, to display the OpenAPI description.Generates automatically the OpenAPI file.

springdoc.org

 

Documenting a Spring REST API Using OpenAPI 3.0 | Baeldung

Learn how to generate OpenAPI 3.0 specifications for a Spring REST API using SpringDoc.

www.baeldung.com

 

[Spring Boot Tutorial] 15. Open API 3.0 + Swagger v3 상세설정

api 그룹 설정 : @Tag api Schema 설정 : @Schema api 상세 정보 설정 : @Operation api response 설정 : @ApiResponse api parameter 설정 : @Parameter 이전시간에 OpenAPI info 정보만 설정했었습니다. Schemas 에 대한 설명과 들

blog.jiniworld.me