웹개발

Swagger 를 사용해서 api 문서화 자동화

slown 2023. 11. 27. 19:41

 

목차

1.Swagger?

2.Swagger 설정 및 프로젝트 적용

 

1. Swagger?

Swagger는 Api스펙 명세 및 관리를 목적으로 하며, 실제 서버에 요청을 보내는 방식으로 Api에  대해 테스트를 해 볼 수 있는 Ui를 제공해주는 개발도구이다. 

 

2.Swagger 설정 및 프로젝트 적용

우선 사진과 같이 스프링 프로젝트에 라이브러리를 gradle에 넣는다. 

swagger 라이브러리 주입

그 다음 Swagger에 관련된 설정 클래스와 설정 properties를 작성한다.

swagger에 사용될 설정 properties

 

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import springfox.documentation.builders.*;
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 {

    @Bean
    public Docket api() {

        return new Docket(DocumentationType.OAS_30)
                .useDefaultResponseMessages(false)// Swagger 에서 제공해주는 기본 응답 코드를 표시할 것이면 true
                .ignoredParameterTypes(AuthenticationPrincipal.class)//Spring Security에 사용될 경우 설정
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.example")) // Controller가 들어있는 패키지. 이 경로의 하위에 있는 api만 표시됨.
                .paths(PathSelectors.ant("/api/**")) // 위 패키지 안의 api 중 지정된 path만 보여줌. (any()로 설정 시 모든 api가 보여짐)
                .build();
    }

    public ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("Coffies Rest API Documentation")//swagger ui 에 나오는 제목
                .description("CoffiesVol.02")//swagger ui에 api 설명
                .version("0.2")//version
                .build();
    }
}

 

이렇게 기본적인 설정이 끝난 뒤에는 url 에 localhost: port번호/swagger-ui/index.html 을 입력해서 들어가면 위와 같은 화면을 볼수 있습니다.

 

 

 

위의 주소로 들어오게 되면 개발자가 작성한 api 목록을 볼 수 있고 각 api를 상세하게 볼 수 있고 응답값까지 볼 수 있다.

 

그럼 스웨거를 코드에 어떻게 적용을 했는지 보도록 하자.

@Api(tags = "Board api",value = "자유게시판 관련 api 컨트롤러")
@RestController
@RequestMapping("/api/board")
@RequiredArgsConstructor
public class BoardApiController {
    private final BoardService boardService;

    @Operation(summary = "게시글 목록", description = "자유게시판에서 목록을 조회하는 컨트롤러", responses = {
            @ApiResponse(responseCode = "200",description = "정상적으로 응답하는 경우",content = @Content(mediaType = "application/json",schema = @Schema(implementation = BoardResponse.class)))
    })
    @GetMapping(path = "/list")
    public CommonResponse<?>boardList(@ApiIgnore @PageableDefault(sort = "id",direction = Sort.Direction.DESC, size = 5) Pageable pageable){

        Page<BoardResponse> list = boardService.boardAllList(pageable);
        //게시글이 없는 경우
        if(list.isEmpty()){
            throw new CustomExceptionHandler(ERRORCODE.BOARD_NOT_FOUND);
        }
        return new CommonResponse<>(HttpStatus.OK.value(),list);
    }

    @Operation(summary = "게시글 검색", description = "자유게시판에서 게시물을 검색하는 컨트롤러", responses = {
            @ApiResponse(responseCode = "200",description = "정상적으로 응답하는 경우",content = @Content(mediaType = "application/json",schema = @Schema(implementation = BoardResponse.class)))
    })
    @GetMapping(path = "/search")
    public CommonResponse<?>boardSearch(
            @ApiIgnore @PageableDefault(sort = "id",direction = Sort.Direction.DESC, size = 5) Pageable pageable,
            @Parameter(description = "게시물 검색 타입",in = ParameterIn.QUERY)
            @RequestParam(value = "searchType",required = false) SearchType searchType,
            @Parameter(description = "게시글에 사용되는 검색어",in=ParameterIn.QUERY)
            @RequestParam(value = "searchVal",required = false) String searchVal){

        Page<BoardResponse> list = null;
        //검색어가 없는 경우
        if(searchVal==null||searchVal.equals("")||searchType.getValue()==null||searchType.getValue().equals("")){
            return new CommonResponse<>(HttpStatus.OK.value(),ERRORCODE.NOT_SEARCH_VALUE.getMessage());
        }

        try {
            list = boardService.boardSearchAll(searchType,searchVal,pageable);
        }catch (Exception e){
            e.printStackTrace();
        }

        return new CommonResponse<>(HttpStatus.OK.value(),list);
    }
}

 

위의 코드는 내가 만들었던 프로젝트에 스웨거를 적용한 코드의 일부분이다. 

2-1. @Api

@Api 의 어노테이션은 컨트롤러에 붙이면 해당 컨트롤러 내에 있는 api를 분류해서 볼 수 있다.

  • tag = 태그의 이름
  • value = 태그에 대한 자세한 설명

예시) 아래의 예시와 같이 태그명을 적을 수 있고 그에 대한 설명을 붙일 수 있다.

@Api(tags = "Board api",value = "자유게시판 관련 api 컨트롤러")

2-2. @Operation 

@Operation 어노테이션은 컨트롤러에 있는 메서드를 상세하게 설명하기 위해서 사용되는 어노테이션이다.

  • summary = api의 명칭
  • description = api의 자세한 설명
  • response = 호출한 api의 응답값을 자세하게 설정이 가능하다.

@Operation(summary = "게시글 목록", description = "자유게시판에서 목록을 조회하는 컨트롤러", responses = {
            @ApiResponse(responseCode = "200",description = "정상적으로 응답하는 경우",content = @Content(mediaType = "application/json",schema = @Schema(implementation = BoardResponse.class)))
    })

 

2-3. @ApiResponse 

@ApiResponse 는 api가 호출 되었을 때 응답코드에 따라서 api의 응답값을 설정할 수 있는 어노테이션이다.

  • responseCode = 응답코드
  • description = 응답코드의 자세한 설명
  • content = Response payload 구조
    • schema: payload에서 이용하는 Schema
      • hidden: Schema 숨김 여부
      • implementation: Schema 대상 클래스

예시)

@ApiResponse(responseCode = "200",description = "정상적으로 응답하는 경우",

content = @Content(mediaType = "application/json",schema = @Schema(implementation = BoardResponse.class)))

 

2-4.@Parameter

@Parameter 어노테이션은 api에서 사용되는 파라미터를 설명하기 위한 어노테이션이다. 

  • name : 파라미터의 명
  • description : 파라미터의 자세한 설명
  • in : 파라미터의 종류 ( query, header, path, cookie )

예시)

@Parameter(description = "게시물 검색 타입",in = ParameterIn.QUERY)