Swagger

백엔드 개발에서 Web API를 문서화하기 위한 도구(제품의 설명서)

  • 프로젝트의 API목록을 웹에서 확인 및 테스트 가능하게 하는 라이브러리
  • 특히 RESTful API 문서화, 관리에 많이 쓰임

1. 의존성추가

  • build.gradle
// swagger
implementation group: 'io.springfox', name: 'springfox-boot-starter', version: '3.0.0'
implementation group: 'io.springfox', name: 'springfox-swagger-ui', version: '3.0.0'
  • application.yml
    (Spring boot 2.6버전 이후에 spring.mvc.pathmatch.matching-strategy 값이 ant_apth_matcher에서 path_pattern_parser로 변경되면서 몇몇 라이브러리에서 오류가 발생)
spring: 
  mvc: 
    pathmatch:
      matching-strategy: ANT_PATH_MATCHER

2. 프로젝트에 Swagger 설정 Bean 등록

  • SwaggerConfig.java : Docket의 Bean 등록을 위한 클래스

    • @EnableSwagger2 : Swagger2 사용가능
    • Docket : Swagger 설정의 핵심이 되는 문서화 객체
      • select() : ApiSelectorBuilder를 통해 객체 생성함
    • ApiInfo : API의 정보를 담고있음
      • apis() : api를 탐색할 위치 설정
      • paths() : path조건에 해당하는 API를 찾아서 문서화함
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
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
@EnableAutoConfiguration
public class SwaggerConfig {

    private final String version = "v1";

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("Seulmeal API")
                .description("Seulmeal Purchase API")
                .build();
    }

    @Bean
    public Docket apiV1() {
        return new Docket(DocumentationType.SWAGGER_2)
                .groupName(version)
                .useDefaultResponseMessages(false)
                .apiInfo(this.apiInfo())
                .tags(new Tag("PurchaseRestController", ""))
                .select()
                .apis(RequestHandlerSelectors.basePackage("shop.seulmeal.web.purchase"))
                .paths(PathSelectors.any())
                .build();
    }
}


=> {host 주소}/swagger-ui/index.html (Swagger-ui 3.x버전) 로 접속하면 기본적인 Swagger 동작

제목 없음


3. Annotation

  • @ApiResponse : method의 response에 대한 설명 작성
    • @ApiResponses로 @ApiResponse 여러개 설명추가 가능
    • SwaggerConfig Docket에 useDefaultResponseMessages(false) 설정 : @ApiResponse로 설명하지 않은 응답들 사라짐
@ApiResponses({
    @ApiResponse(code = 200, message = "Success"),
    @ApiResponse(code = 201, message = "Success"),
    @ApiResponse(code = 400, message = "Bad Request"),
    @ApiResponse(code = 500, message = "Internal Server Error")
})

@RestController
@RequestMapping("/api/v1/purchase/*")
@RequiredArgsConstructor 
@Api(tags = "PurchaseRestController")
public class PurchaseRestController {



  • @ApiOperation(value="", notes="") : method 설명
  • @ApiImplicitParam : 해당 API method 호출에 필요한 parameter들의 설명 추가가능
    • dataType, paramType, required의 경우 자동으로 채워져서 생략가능
  • @APiParam : DTO field 설명
    • Controller에서 parameter에도 바로 적용가능(비추)
    • 처음에 이렇게 했다가 @ApiImplicitParam로 변경함,, 결과는 같음
@ApiOperation(
    value = "자동완성", 
    notes = "<h3> 추가할 재료 검색 시, 검색어가 포함된 재료목록 출력</h3>"
        + "- insertCustomProduct.jsp, listPurchaseCart.jsp 에서 사용")
@PostMapping("autocomplete")
public ResponseEntity<Map<String, Object>> autocomplete(
    @RequestBody @ApiParam(value="검색어", defaultValue="") Map<String, Object> paramMap
    ) throws Exception{

위에서 아래로 변경

@ApiOperation(
    value = "자동완성", 
    notes = "<h3> 추가할 재료 검색 시, 검색어가 포함된 재료목록 출력</h3>"
      + "- insertCustomProduct.jsp, listPurchaseCart.jsp 에서 사용")
@ApiImplicitParam(name="paramMap", value="검색어", defaultValue="")
@PostMapping("autocomplete")
public ResponseEntity<Map<String, Object>> autocomplete(
    @RequestBody Map<String, Object> paramMap) throws Exception{



  • @ApiImplicitParams 로 @ApiImplicitParam 여러개 가능
@ApiOperation(
    value = "장바구니에서 수량변경", 
    notes = "<h3> 장바구니에 담긴 상품의 수량을 변경 <br> 수량변경에 성공하면 1 리턴</h3>"
      + "- listPurchaseCart.jsp 에서 사용")
@ApiImplicitParams({
    @ApiImplicitParam(name="customProductNo", value="커스터마이징상품 고유키", defaultValue="650"),
    @ApiImplicitParam(name="count", value="변경수량", defaultValue="3")
})
@PutMapping("cart/{customProductNo}/{count}")
public ResponseEntity<Integer> updateCusotmProduct(
    @PathVariable int customProductNo, 
    @PathVariable int count) throws Exception {



  • @ApiIgnore : swagger UI에서 무시
    • @ApiImplictParam 으로 선언하지않은 parameter정보들 무시할 수 있음
    • 나는 UI상에서 RestController만 뜨게, Controller에 붙여줌
@Controller
@RequestMapping("/api/v1/purchase/*")
@RequiredArgsConstructor
@ApiIgnore
public class PurchaseController {



  • @ApiModel, @ApiModelProperty : parameter의 example value 설정
@ApiModel
public class Purchase {
  @ApiModelProperty(example="682")
  private int purchaseNo;
  ...
  @ApiModelProperty(example="4")
  ...
  @ApiModelProperty(example="imp_514829371298")
  private String imp_uid;
  @ApiModelProperty(example="200")
  private int amount;
  ...
}



  • 최종

swagger



4. Swagger API test

  • Postman처럼 API test 가능

swaggertest

Try it out 버튼누르고 parameters의 value에 메소드가 받을 수 있는 형태의 데이터를 JSON 형식으로 채움
{“value” : “양”}
=> 양파, 양고기 출력



Reference
https://velog.io/@banjjoknim/Swagger
https://jojoldu.tistory.com/31
https://wildeveloperetrain.tistory.com/3
https://velog.io/@gillog/Swagger-UI-Annotation-%EC%84%A4%EB%AA%85

업데이트: