Programming/Spring Boot

Swagger 사용하여 RESTful API 문서 자동화하기 (SpringBoot)

Jan92 2021. 7. 17. 01:23

 

처음에는 회사에 들어갔을 때는 Swagger를 잘 만들어야 한다는 이야기가 크게 와닿지 않았는데, 프로젝트를 진행하며 협업에 있어서 내가 개발한 것을 다른 사람들도 쉽게 알아보고, 사용할 수 있도록 문서화하는 것이 중요하구나를 많이 느끼고 있습니다.

그래서 Web API 문서화 도구 중 많이 쓰이는, 그리고 사용하고 있는 Swagger의 사용법에 대해 정리해보려고 합니다.

(Swagger 외에는 많이 사용되는 문서화 도구는 SpringRestDocs가 있습니다.)

 

 

Swagger란 무엇일까?

백엔드 개발에 있어서 Web API를 문서화하기 위한 도구이며 쉽게는 제품의 설명서라고도 생각할 수 있습니다.

간단한 설정으로 프로젝트의 API 목록을 웹에서 확인 및 테스트 가능하게 하는 라이브러리이며, 특히 RESTful API를 문서화시키고 관리하는 것에 많이 쓰입니다.

API 문서를 일반 문서로 작성하게 되면 API가 변경될 때마다 문서를 함께 수정해줘야 하는 번거로움이 있는데 SpringBoot에서는 Swagger를 사용하면 문서 수정을 자동화할 수 있습니다.

 

(본인이 생각하기에 RESTful API 를 테스트할 수 있다는 것이 큰 장점인 것 같습니다.)

 

 


 

그렇다면 SpringBoot에서 Swagger의 사용법은 어떻게 될까요?

 

- 가장 먼저 의존성을 추가해줘야 합니다.

// Swagger2 gradle
implementation (group: 'io.springfox', name: 'springfox-swagger2', version: '2.9.2'){
    exclude module: 'swagger-annotations' exclude module: 'swagger-models'
}
implementation "io.swagger:swagger-annotations:1.5.21"
implementation "io.swagger:swagger-models:1.5.21"
implementation group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2'

< Gradle 의존성 추가 >

 

    <!-- springfox-swagger2 -->
    <dependency>
      <groupId>io.springfox</groupId>
      <artifactId>springfox-swagger2</artifactId>
      <version>2.9.2</version>
      <exclusions>
        <exclusion>
          <groupId>io.swagger</groupId>
          <artifactId>swagger-annotations</artifactId>
        </exclusion>
        <exclusion>
          <groupId>io.swagger</groupId>
          <artifactId>swagger-models</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
    <!-- springfox-swagger-ui -->
    <dependency>
      <groupId>io.springfox</groupId>
      <artifactId>springfox-swagger-ui</artifactId>
      <version>2.9.2</version>
    </dependency>
    <dependency>
      <groupId>io.swagger</groupId>
      <artifactId>swagger-annotations</artifactId>
      <version>1.5.21</version>
    </dependency>
    <dependency>
      <groupId>io.swagger</groupId>
      <artifactId>swagger-models</artifactId>
      <version>1.5.21</version>
    </dependency>

< Maven 의존성 추가 >

 

 

 

Swagger 2.9.2 버전을 추가했습니다.

주의 깊게 봐야 할 점은 gradle, maven 모두 해당 버전의 swagger-annotations, swagger-models를 제거하고 1.5.21 버전의 annotaions, models를 추가했다는 점인데요.

 

이유는 2.9.2 버전에서 Long 타입의 필수 파라미터에 example이 없는 경우 "" 공백이 Long 타입 파라미터에 들어가기 때문에 아래와 같이 NumberFormatException이 발생하기 때문입니다.

NumberFormatException

 

 

- 다음은 Docket의 Bean 등록을 위한 클래스를 생성합니다.

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 SwaggerConfiguration {

    private final String version = "v1";

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("Example API")
                .description("Swagger 소개를 위한 example")
                .build();
    }

    @Bean
    public Docket commonApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .groupName(version)
                .apiInfo(this.apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.story.example"))
                .paths(PathSelectors.any())
                .build();
    }
}

Swagger2는 @EnableSwagger2 Annotation 설정으로 사용 가능하고, Docket는 Swagger 설정의 핵심이 되는 문서화 객체입니다.

Docket의 select() method는 ApiSelectorBuilder를 통해 객체를 생성합니다.

 

apiInfo는 api 정보를 담고 있습니다. apis는 api를 탐색할 위치를 설정하고, paths는 path 조건에 해당하는 API를 찾아서 문서화합니다.

(이 외에도 다양한 생성 방법과 옵션이 있는데 해당 글에서는 기본적인 Swagger의 세팅만 진행하겠습니다.)

 

 

 

세부 설정 전 Swagger

여기까지 진행하고 {host 주소}/swagger-ui.html#으로 접속을 하게 되면 기본적인 Swagger가 동작하게 됩니다.

(본인 기준 http://localhost:8080/swagger-ui.html#) 

 

Swagger가 동작하게 되면 여기서부터는 세부적인 설명서 작성에 들어가는 단계입니다.

 

 

- 먼저 MainController 설정부터 보겠습니다.

import com.story.example.lib.Response;
import com.story.example.main.dto.RegisterRequest;
import com.story.example.main.dto.RegisterResponse;
import io.swagger.annotations.*;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@ApiResponses({
        @ApiResponse(code = 200, message = "Success"),
        @ApiResponse(code = 400, message = "Bad Request"),
        @ApiResponse(code = 500, message = "Internal Server Error")
})
@RestController
@RequestMapping("/v1")
public class MainController {

    private final Response response;

    public MainController(Response response) {
        this.response = response;
    }

    @ApiOperation(value = "회원 정보", notes = "회원에 대한 정보 출력")
    @GetMapping("/member/{idx}")
    public ResponseEntity<?> getMember(@PathVariable String idx) {
        return response.success();
    }

    @ApiOperation(value = "회원 등록", notes = "신규 회원 등록", response = RegisterResponse.class)
    @PostMapping("/member")
    public ResponseEntity<?> registerMember(RegisterRequest registerRequest) {
        return response.success();
    }
}

(각 엔드 포인트는 예시를 위한 것으로 내부 동작되는 부분의 코드는 없고 틀만 있습니다.)

 

@ApiResponses 안에 @ApiResponse Annotaion을 통해 결과 코드에 대한 문서를 추가합니다.

각 엔드 포인트에서는 @ApiOperation Annotaion으로 각 포인트의 value, notes, response 정보를 추가할 수 있습니다.

 

 

Controller 설정 된 Swagger

Controller가 설정된 Swagger의 모습입니다.

 

- 다음으로는 엔드 포인트 세부적인 내용을 추가해 볼 텐데요. 회원 등록을 예시로 보겠습니다.

 

@ApiOperation(value = "회원 등록", notes = "신규 회원 등록", response = RegisterResponse.class)
@PostMapping("/member")
public ResponseEntity<?> registerMember(RegisterRequest registerRequest) {
    return response.success();
}

회원 등록인 registerMember 메서드는 RegisterRequest 객체를 파라미터로 받고, RegisterResponse 객체로 요청 결과를 나타냅니다.

 

import io.swagger.annotations.ApiParam;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class RegisterRequest {

    @ApiParam(value = "회원 아이디", required = true, example = "1")
    private String id;

    @ApiParam(value = "회원 비밀번호", required = true, example = "e")
    private String password;

    @ApiParam(value = "회원 전화번호", example = "01033335555")
    private Long phone;

    @ApiParam(value = "회원 이메일", example = "example@example.com")
    private String email;
}

RegisterRequest Class입니다.

 

@ApiParam이라는 Annotaion의 value, example을 통해 값을 설정할 수 있고, required 여부도 설정할 수 있습니다.

 

Parameters

@ApiParam이 설정된 결과입니다.

 

 

import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class RegisterResponse {

    @ApiModelProperty(notes = "회원 고유 번호", example = "1")
    private Long idx;

    @ApiModelProperty(notes = "회원 아이디", example = "id")
    private String id;

    @ApiModelProperty(notes = "회원 이름", example = "name")
    private String name;

    @ApiModelProperty(notes = "회원 전화번호", example = "01038499269")
    private Long phone;

    @ApiModelProperty(notes = "회원 이메일", example = "example@example.com")
    private String email;
}

RegisterResponse Class입니다.

 

@ApiModelProperty Annotaion을 통해 notes, example을 설정할 수 있습니다.

 

 

Example Value

 

Model

@ApiModelProperty 설정된 결과입니다.

 

 

여기까지 기본적인 Swagger를 설정하는 방법을 알아봤습니다.

 

내가 개발을 한 것을 문서화하여 다른 사람들이 쉽게 알아볼 수 있도록 한다는 점에서 Swagger 외 문서화 도구는 개발에 있어서 기본이 되고 또 꼭 필요한 것 같습니다. 계속 쓰이게 될 것이니 만큼 잘 익혀두고 사용하면 좋을 것 같습니다.

 

 

잘못된 부분은 말씀해주시면 확인하고 공부하여 수정하겠습니다. 감사합니다.