Swagger를 이용한 API 문서 자동화
API 문서 자동화 프레임워크인 Swagger를 학습하고 활용해보자.
1. Swagger란?
처음 개발하거나 혹은 유지보수를 진행할 때, API 서버가 어떤 Spec을 가진 데이터를 주고받는지에 대한 문서작업이 꼭 필요하다. 하지만 이런 문서작업은 굉장히 시간이 많이들고, API가 수정될 때마다 문서도 같이 수정해줘야 하는 번거로움을 동반한다.
스웨거(Swagger)는 Open Api Specification(OAS)를 위한 프레임워크로 API들이 가지고 있는 스펙(spec)을 명세, 관리할 수 있는 프로젝트이다.
1. Swagger
아래의 사진은 Swagger가 적용된 화면이다.
위 사진처럼 URL 리스트들의 목록을 바로 확인을 할 수가 있다.
2. Swagger 설정
1. 의존성 추가
- SpringBoot & Gradle 기반 의존성을 추가해준다.
compile group: 'io.springfox', name: 'springfox-swagger2', version: '2.9.2'
compile group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2'
2. Project에 Swagger Bean 추가
- SwaggerConfig.java 파일을 생성한다.
그 후, 다음과 같은 코드를 추가한다.
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket api(){
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("your Package Path"))
.paths(PathSelectors.any()) // basePackage로부터 Mapping된 resource를 문서화 시킴
.build();
}
private ApiInfo apiInfo(){
return new ApiInfoBuilder()
.title("Chatbot API Documentation")
.description("This documents describes about Kakao Chatbot RestAPI ")
.version("1.0.0")
.build();
}
}
3. Swagger-ui 접속해서 확인하기
- 브라우저에서 서버 주소:포트/swagger-ui.html로 접속해본다.
ex) localhost:8080/swagger-ui.html
2. Swagger 기능
1. Request
- 필수 파라미터를 파악 할 수 있다. ( *Required로 표시)
- Model Schema를 통해 어떤 Data를 전달받는지 확인할 수 있다.
2. Response
- 응답 형식을 쉽게 파악할 수 있다.
3. Swagger-ui API Test
Swagger는 이러한 문서화 기능뿐만아니라 Postman과 같은 API 메소드 테스트 기능을 제공한다.
1. Post API 메소드 → Parameters → Try it out 버튼 클릭
2. 필수 파라미터인 appUserId value 입력란이 활성화된다.
필수 파라미터를 입력해야만 API 테스트를 진행할 수 있다.
또한, Example Value에 Model Schema가 자동으로 입력된다.
이를 조작하여 테스트를 진행할 수도 있다.
3. 필수 파라미터 값을 채우고 Execute 버튼 클릭
4. 밑에 Response를 확인해보면 API 응답 값을 확인할 수 있다.
4. Swagger Annotation으로 Swagger-ui 보강하기
1. @ApiOperation Annotation
- API 메소드에 대한 설명을 추가할 수 있다.
@PostMapping("/userProfile")
@ApiOperation(value = "인증 요청 처리", notes = "OTP_URL을 처리하고 사용자 정보를 가져오는 API입니다.")
public MessageDTO profile(@RequestBody ActionDTO actionDTO) throws Exception{
......
......
}
2. @ApilmplicitParams Annotation
DTO 상세 파라미터의 설명을 추가하거나 필수 파라미터, Data Type, 파라미터 Type을 설정한다.
@PostMapping("/checkAppId")
@ApiOperation(value = "사용자별 인증 정보 CHECK", notes = "인증된 사용자인지 판단하는 API입니다.")
@ApiImplicitParams({
@ApiImplicitParam(name = "appUserId", value = "사용자 식별 ID", required = true)
})
public MessageDTO checkAppId(@RequestBody UserRequestDTO userRequestDTO){
......
......
}
- Data Type이나 파라미터 Type은 자동으로 설정되기 때문에 생략 가능하다.
- required = true 값으로 필수 파라미터를 설정할 수 있다.
3. @ApiModelProperty Annotation
- 파라미터의 Example value를 설정할 수 있다.
public static class MemberProfile {
@JsonProperty("origin")
@ApiModelProperty(example = "https://talk-plugin.kakao.com/otp/xxxxxx/profile?rest_api_key=yyyyyyyy")
private String origin;
public String getOrigin() {
return origin;
}
public void setOrigin(String origin) {
this.origin = origin;
}
}
DTO에 추가해준다.
- origin이라는 필드에 example 값이 설정된 것을 확인할 수 있다.
Issue
Mapping 되는 Json Data에 'properties' 라는 필드가 존재하면
Swagger에서 'properties'라는 필드가 Mapping 되지 않고 Model Schema에 표현되지 않는 이슈가 발생한다. Swagger에서 이미 'properties' 라는 이름을 사용하고 있기 때문이다.
properties: → Swagger properties
properties: → Request properties
이러한 형식으로 Mapping되서 resource를 읽어오지 못한다.
1. 문제 해결 시도 방법
1. @JsonPropery Annotation을 이용해 Mapping 되는 필드명을 바꾼다.
@JsonProperty("properties") → @JsonProperty("property")
필드명을 바꿔서 시도해본 결과, Swagger에서는 정상적으로 Data가 Mapping 되지만
Java Object에는 필드명을 찾을 수 없어 NullPointerException이 발생한다.
2. @JsonGetter와 @JsonSetter의 필드명을 각각 준다.
public static class User {
private Properties properties;
@JsonGetter("property")
public Properties getProperty() {
return properties;
}
@JsonSetter("properties")
public void setProperty(Properties properties) {
this.properties = properties;
}
}
이 방법도 위와 같은 문제로 해결되지 않았다.
2. 해결 방법
@JsonAlias Annotation으로 해결할 수 있었다.
→ Jackson 2.9에서 추가된 Annotation이다. 하나 이상의 이름을 지정할 때 사용한다.
public static class User {
@JsonProperty("properties")
@JsonAlias({ "property", "properties" })
private Properties properties;
public Properties getProperty() {
return properties;
}
public void setProperty(Properties properties) {
this.properties = properties;
}
}
property & properties 두 개의 이름을 같은 이름으로 인식하기 때문에 필드명을 property로 바꾸어도 properties 필드에 값이 제대로 매핑된다.
즉, Swagger-ui에는 property로 매핑되고 DTO에서는 properties로 매핑된다.