GrowMe

[API 문서화] Swagger의 기본 사용법 본문

About Spring

[API 문서화] Swagger의 기본 사용법

오늘도 타는중 2022. 8. 30. 22:51
Swagger의 기본 사용법
# Swagger
# Swagger의 기본 사용법
# 세부설명서 작성

Swagger란?

  • Swagger 는 REST API를 설계, 빌드, 문서화 및 사용하는 데 도움이되는 OpenAPI 사양을 중심으로 구축 된 오픈 소스 도구 
    (in Swagger Specification)
  • Spring Rest Docs에 비해 문서화하기 까지의 걸리는 시간 비용이 대폭 절감 가능하다. (이는 상당한 매력 포인트)
  • 본래 코드들에 기능과 상관없는 어노테이션을 써야해서 코드가 지저분해질 수도 있지만, 내 기준으론 상관없는 수준이었다.
  • Test할 수 있는 html 파일을 제공한다. Spring Rest Docs는 테스트를 직접 작성하여 통과될때만 문서화가 되어, 한번에 로직에 이상이 없는 API 문서를 제공 가능하지만, Swagger는 일단 문서로 만들고 자체적으로 Test하며 로직을 수정할 수 있다.

*Swagger의 기본 사용법(SpringBoot 환경에서의)

1. 의존성 추가하기(gragle 기준)

implementation group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2'
implementation group: 'io.springfox', name: 'springfox-swagger2', version: '2.9.2'

2. Configuration 설정하기

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.RequestHandler;
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 {

    @Bean
    public Docket restAPI() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("PreProject"))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("Stack Overflow clone Project REST API")
                .version("1.0.0")
                .description("SEB-004 Team의 REST API 입니다.")
                .build();
    }
}
  • @EnableSwagger2 : Swagger2 버전을 활성화한다.
  • Docket : Swagger 설정을 할 수 있게 도와주는 클래스
  • apiInfo(apiInfo()) : 제목, 설명 등 문서에 대한 정보들을 설정하기 위해 호출한다. 여기서는 title("제목"), version("버전명"), description("설명") 을 추가하여 문서에 표시하도록 하였으며, 아래에서 만들어진 문서들을 확인 시, 이를 확인 가능하다.
  • select() : ApiSelectorBuilder를 생성하여 apis()와 paths()를 사용할 수 있게 해준다.
  • apis() : 문서화 대상인 api의 스펙이 작성되어 있는 패키지를 지정한다. 해당 패키지 기준으로 문서화가 진행된다.
  • paths() : apis()로 선택되어진 API중 특정 path 조건에 맞는 API들을 다시 필터링하여 문서화한다.
    -> PathSelectors.any()로 설정하면 패키지 안에 모든 API를 한 번에 볼 수 있다.
    -> PathSelectors.ant("/v1/api/**") 등, URI 패턴을 통해 조건 설정이 가능하다.

-여기까지 작성했다면 서버를 실행시킨 뒤 API가 문서화된 화면을 볼 수 있다.

  • http://localhost:포트번호/swagger-ui.html 로 접속
  • 여기까지만 작성해도 Swagger가 동작하여, Test를 실행 가능하다.


*Swagger의 기본 사용법(세부 설명서 작성)

- Contrller

@ApiResponses({
        @ApiResponse(code = 200, message = "Success"),
        @ApiResponse(code = 400, message = "Bad Request"),
        @ApiResponse(code = 500, message = "Internal Server Error")
})

@RestController
@RequestMapping("/question")
@RequiredArgsConstructor
public class QuestionController {
    private final QuestionService questionService;

    private final QuestionMapper mapper;

    @ApiOperation(value = "질문 등록", notes = "등록된 질문 데이터 반환", response = QuestionDto.Response.class)
    @PostMapping
    public ResponseEntity write(@RequestBody QuestionDto.Post post) {

       Question writed = questionService.write_Service(mapper.questionPostToQuestion(post), post.getMember_id());

       return new ResponseEntity<>(mapper.questionToQuestionResponse(writed), HttpStatus.CREATED);
    }

    @ApiOperation(value = "질문 조회", notes = "1개 질문 데이터 반환", response = QuestionDto.Response.class)
    @ApiImplicitParam(name = "question_id", value = "질문 식별번호")
    @GetMapping("/{question_id}")
    public ResponseEntity read(@PathVariable Long question_id) {
        Question finded = questionService.read_Service(question_id);
        return new ResponseEntity<>(mapper.questionToQuestionResponse(finded), HttpStatus.OK);
    }

    @ApiOperation(value = "질문 리스트 조회", notes = "페이지 별 질문리스트 반환", response = MultiResponseDto.class)
    @GetMapping("list")
    public ResponseEntity get_list(
            @ApiParam(value = "현재 페이지", required = true, example = "1")
            @RequestParam int page,
            @ApiParam(value = "페이지 크기", required = true, example = "10")
            @RequestParam int size) {
        Page<Question> page_list = questionService.get_list_Service(page, size);
        List<Question> finded_list = page_list.getContent();

        return new ResponseEntity<>(new MultiResponseDto<>(mapper.questionsToQuestionResponseDtos(finded_list), page_list)
        , HttpStatus.OK);
    }

    @ApiOperation(value = "질문 수정", notes = "질문 데이터 수정", response = String.class)
    @PatchMapping
    public ResponseEntity modify(@RequestBody QuestionDto.Patch patch) {
        questionService.modify_Service(mapper.questionPatchToQuestion(patch), patch.getMember_id());

        return new ResponseEntity<>("수정이 완료되었습니다.", HttpStatus.OK);
    }

    @ApiOperation(value = "질문 삭제", notes = "1개 질문 삭제", response = String.class)
    @ApiImplicitParam(name = "question_id", value = "질문 식별번호")
    @DeleteMapping("/{question_id}")
    public ResponseEntity delete(@PathVariable Long question_id) {
        questionService.delete_Service(question_id);
        return new ResponseEntity<>("삭제가 완료되었습니다.", HttpStatus.NO_CONTENT);
    }
}
  • @ApiResponses : @ApiResponse의 한 덩어리
  • @ApiResponse : 결과 상태코드에 대한 문서 설명을 추가할 수 있습니다.
  • @ApiOperation : 각 엔드포인트마다 value(엔드포인트 바로 옆 위치한 설명), notes(상세 설명), response(반환 타입 클래스)를 추가 가능합니다.
  • @ApiParam : Request의 데이터 중, 파라미터의 값을 설정법에 대한 정보를 표현합니다.
    value = 값의 의미, example = 예제 값, required = 필수여부
  • @ApiImplicitParam : @ApiParam과 유사하다. (사실 아직 큰 차이점을 모르겠다..)

- 엔드포인트 자세히 보기

@ApiOperation(value = "질문 등록", notes = "등록된 질문 데이터 반환", response = QuestionDto.Response.class)
    @PostMapping
    public ResponseEntity write(@RequestBody QuestionDto.Post post) {

       Question writed = questionService.write_Service(mapper.questionPostToQuestion(post), post.getMember_id());

       return new ResponseEntity<>(mapper.questionToQuestionResponse(writed), HttpStatus.CREATED);
    }
  • 질문 등록인 write() 메서드는 QuestionDto.Post 객체를 Request Body로 받고 QuestionDto.Response 객체로 결과 데이터를 전송하므로, @ApiOperation의 response 속성 값도 그에 맞춰주었습니다.

- Request 데이터 설명

@Getter
public class QuestionDto {
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @Getter
    public static class Post {
        @ApiModelProperty(value = "질문 식별번호", required = false, example = "1")
        private Long questionId;
        @ApiModelProperty(value = "질문 등록한 회원 식별번호", required = true, example = "2")
        private Long member_id;
        @ApiModelProperty(value = "제목", required = true, example = "제목1")
        private String title;
        @ApiModelProperty(value = "내용", required = true, example = "내용1")
        private String contents;
    }
}
  • @ApiModelProperty : 엔드포인트가 모델 데이터를 사용 시, Swagger UI에서 각 property의 예제 값을 주고 싶을 때 사용한다.

- Response 데이터 설명

@Getter
public class QuestionDto {

    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @Getter
    public static class Response {
        @ApiModelProperty(notes = "질문 식별 번호", example = "1")
        private Long questionId;

        @ApiModelProperty(notes = "제목", example = "제목1")
        private String title;

        @ApiModelProperty(notes = "내용", example = "내용1")
        private String contents;

        @ApiModelProperty(notes = "질문 투표 수", example = "0")
        private int vote;
        @ApiModelProperty(value = "질문 조회 수", example = "0")
        private int view;
    }
}
  • Response 데이터도 마찬가지로 @ApiModelProperty를 사용하여 예제 데이터를 표시하였습니다.

Comments