도찐개찐

[SpringBoot] Swagger API 문서 자동화 본문

JAVA/SpringBoot

[SpringBoot] Swagger API 문서 자동화

도개진 2023. 2. 21. 08:55

Rest Api 애플리케이션 개발에 있어 API 스펙에 대한 문서작업은 적지 않은 시간을 요구합니다.

또한 운영을 하게 되면서 지속적으로 문서를 업데이트하는 것 또한 많은 리소스가 필요합니다.

 

이러한 시간을 단축시키기 위해 문서 자동화 프레임 워크를 이용하는 방법이 있습니다.

대표적으로 Swagger, Spring REST Docs가 있는데 그중 Swagger 적용 방법에 대해 알아보겠습니다.

 

 

1. Dependency 설정

Maven

<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>

Gradle

// https://mvnrepository.com/artifact/io.springfox/springfox-swagger2
compile group: 'io.springfox', name: 'springfox-swagger2', version: '2.9.2'

// https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui
compile group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2'

 

 

 

2. SwaggerConfig

@EnableSwagger2 어노테이션을 추가하여 Swagger 관련된 설정을 추가합니다.

 

package kr.co.sample.sampleapi.common.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class SwaggerConfig {
    private ApiInfo commonInfo() {
        return new ApiInfoBuilder()
                .title("USER API")
                //.description("")
                //.license("leeys")
                //.licenseUrl("http://leeys.tistory.com")
                .version("1.0")
                .build();
    }

    @Bean
    public Docket allApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("USER")
                .useDefaultResponseMessages(false)
                .select()
                //.apis(RequestHandlerSelectors.any())
                .apis(RequestHandlerSelectors.basePackage("kr.co.sample.sampleapi.controller"))
                .paths(PathSelectors.any())
                .build()
                .apiInfo(commonInfo());
    }
}

 

 

3. Swagger 어노테이션 적용

이제 Swagger 사용을 위한 설정은 완료되었고 Controller에 해당 API에 대한 내용을 Swagger 어노테이션을 사용하여 작성해주면 자동으로 추가됩니다.

추가 어노테이션 정보는 Swagger GitHub 에서 확인 가능합니다.

 

namedescription

@Api Swagger 리소스로 사용될 클래스를 마킹
@ApiImplicitParam Api 의 파라미터(하나)
@ApiImplicitPrams Api 의 파라미터(value ={} 로 @ApiImplicitParam 을 여러개 포함할 수 있음)
@ApiModel Swagger model 에 정보를 추가(모델 클래스)
@ApiModelProperty model 의 프로퍼티 정보
@ApiOperation http method 에 대한 api 정보
@ApiParam api 파라미터에 직접 설명을 붙임
@ApiResponse api 응답에 관한 정의
@ApiResponses api 응답에 관한 정의(value ={} 로 @ApiResponse 을 여러개 포함할 수 있음)
@Authorization 권한에 대한 설명
@AuthorizationScope oauth2 의 authorization scope에 대해 설명

 

Controller

package kr.co.sample.sampleapi.controller;

import io.swagger.annotations.ApiOperation;
import kr.co.sample.sampleapi.entity.User;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

@RestController
public class TestController {
    @ApiOperation(value = "사용자 정보 조회", notes = "UserId를 이용하여 사용자 정보를 조회합니다.")
    @GetMapping(value = "/users/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
    public Object findUser(
            @ApiParam(value = "user id", required = true, example = "1")
            @PathVariable(value = "id", required = true) String id,
            @ApiParam(value = "User Agent Type ", required = true, example = "Mozila")
            @RequestHeader(value = "User-Agent") String userAgent,
            @ApiParam(value = "parameter1 ", required = false)
            @RequestParam(value = "param1", required = false) String param1,
            @ApiParam(value = "parameter2 ", required = false)
            @RequestParam(value = "param2", required = false) String param2){

        return true;
    }

    @ApiOperation(value = "사용자 리스트 조회", notes = "특정 조건에 맞는 사용자 리스트를 조회합니다.")
    @GetMapping(value = "/users", produces = MediaType.APPLICATION_JSON_VALUE)
    public Object findUsers(
            @RequestHeader(value = "User-Agent") String userAgent,
            @ModelAttribute User user){

        return true;
    }

    @ApiOperation(value = "사용자 생성", notes = "신규 사용자를 생성합니다.")
    @PostMapping(value = "/users", produces = MediaType.APPLICATION_JSON_VALUE)
    public Object CreateUser(
            @RequestHeader(value = "User-Agent") String userAgent,
            @RequestBody(required = true) User user){

        return true;
    }
}

 

User Model

package kr.co.sample.sampleapi.entity;

import io.swagger.annotations.ApiParam;
import lombok.Data;

@Data
public class User {
    @ApiParam(value = "사용자 이름", required = false, example = "홍길동")
    private String userName;
    @ApiParam(value = "휴대폰 번호", required = false, example = "010-0000-0000")
    private String phoneNumber;
}

 

 

 

http://localhost:8080/swagger-ui.html 로 접속하여 추가된 API를 확인합니다.

 

장점

  1. 프로젝트의 규모가 커질수록 개발과 API 문서를 동시에 작성하고, 수정사항이 생기면 반영하고 하는 것을 놓치기 쉽습니다. Swagger 는 Server 코드 내에서 annotation 기반으로 작성하기 때문에 이러한 부분들을 미연에 방지할 수 있습니다.
  2. 브라우저에서 URL 기반으로 접근하여 쉽게 테스트까지 가능하다.
  3. 클라이언트 개발자와의 협업이 용이하다.

단점

  1. API 문서 변경 이력 관리가 안된다. (버전관리시스템의 history를 볼 수 있지만 사실상 문서로는 남기기 어려운 점)
  2. 코드가 지저분해진다. 문서를 작성할 수록 annotation 으로 도배가 되어 코드가 지저분해집니다.

사실 개발을 하면서 개발에 관련된 문서를 정리하는 것이 굉장히 힘들다고 느끼고 있습니다. 여러가지 방법을 적용해보며 고민을 하고 있지만, 소규모 개발팀 + 개발자들의 의지부족 + 리더의 개선의지 없음 등이 합쳐지다보니 여러가지 방법을 도입해보는 데, 결국은 항상 혼자 문서를 작성하게 되더군요. 문서에 대한 부담감을 줄여주는 도구로서 Swagger 사용이 꽤나 도움이 된다고 생각됩니다. 저희팀에도 도입하고 싶다는 생각이 들었습니다.

 

참고URL : 

https://sbs1621.tistory.com/m/51

https://yoon0120.tistory.com/50

728x90
Comments