1인 개발이기 때문에 비교적 API 문서도구의 중요성이 떨어지지만, 장점이 있기 때문에 사용하기로 결정했다.
- API의 일관성 유지
- API를 개발하는 동안 API 프로토타입을 작성하고 빠른 테스트 가능
- 프론트엔드 서버까지 담당하고 있기 때문에 문서화 된 API 구조와 엔드포인트 정보는 개발에 큰 편의성을 제공한다.
이런 이유 등으로 문서화 도구를 사용하기로 했고 그 중 Spring Rest Docs와 Swagger를 고민했다.
장단점
Spring Rest Docs | Swagger | |
---|---|---|
장점 | 정확한 문서화가 가능하다. (테스트를 기반하기 때문) | 시각적으로 뛰어난 API 문서를 얻을 수 있다. |
Spring과 통합이 용이하다 | 다양한 언어 및 프레임워크에서 사용 가능하다. | |
정적인 문서를 생성해 서버가 작동하지 않아도 문서를 확인할 수 있다. | 애노테이션을 사용해 API를 문서화하므로 수동 작업이 필요하지 않다. | |
단점 | 초기 설정이 복잡하다. | Swagger 버전이 변경되면 이전 버전과의 호환성 문제가 생길 수 있다. |
테스트 코드에 기반해 문서가 생성되어 프로젝트에 따라 애매할 수 있다. | API 동작과 일치하지 않을 수 있다. | |
API가 동적으로 생성되는 경우 적합하지 않다. | 복잡한 API에 적합하지 않다. |
가장 큰 차이점은 Spring Rest Docs는 테스트 주도에 기반한 정확한 문서화가 장점이고, Swagger는 시각적으로 보기 편한 API 문서와 자동화된 문서 생성이 장점이다.
선택
우선 내 Recommtoon 프로젝트는 1인 개발인 만큼 서비스가 크지 않고, 시간적인 여유도 부족하기 때문에 Swagger를 사용하기로 했다.
API 문서화에 익숙하지 않기 때문에 우선 비교적 쉽게 구현할 수 있는 Swagger를 선택하게 되었고, 작은 프로젝트이기 때문에 비교적 부정확해도 수정과 관리가 용이하다고 생각했다.
설정
1
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0'
- 접속
- 설정 변경했을 경우
- http://(server):(port)/(context-path)/index.html
- 기본 설정
- http://localhost:8080/swagger-ui/index.html
- 설정 변경했을 경우
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Configuration
public class SwaggerConfig {
@Bean
public OpenAPI openAPI() {
return new OpenAPI()
.info(new Info().title("Recommtoon").version("1.0.0"))
.components(new Components()
.addSecuritySchemes("Access_Token", new SecurityScheme()
.type(Type.APIKEY)
.in(In.HEADER)
.name("Authorization")))
.addSecurityItem(new SecurityRequirement().addList("Access_Token"));
}
}
- 문서의 Title, Version등의 설정이 가능하다.
- 보안 스키마 (SecuritySchemes)
- API키를 사용하는 형태로 헤더의 Authrization 키를 통해 토큰을 전달받도록 정의.
- 보안 요구 사항 (SecurityRequirement)
- Access_Token 보안 스키마를 사용하도록 정의한다.
자세한 사항은 공식 사이트를 참조하자.
그리고 내 프로젝트는 SpringSecurity가 적용되어 있기 때문에 위의 설정만 한 후 접속을 시도하면 401 에러를 만날 수 있다.
따라서 설정을 해주어야 한다.
1
... "/swagger-ui/**", "/v3/api-docs/**").permitAll()
이렇게 하면 기본적인 Swagger 화면을 볼 수 있다.
구현 예시
이제 각 컨트롤러에 애노테이션을 이용해 구현을 해보자.
- Controller
1
2
3
4
5
@Tag(name = "인증 컨트롤러")
@RestController
@RequestMapping("/api/auth")
@RequiredArgsConstructor
public class AuthController {
- Method
1
2
3
4
5
6
7
@Operation(summary = "토큰 갱신", description = "Access 토큰 갱신")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "토큰 갱신 성공", content = @Content(schema = @Schema(implementation = Map.class))),
@ApiResponse(responseCode = "401", description = "기존 토큰 유효성 검증 실패", content = @Content(schema = @Schema(implementation = ApiError.class)))
})
@PostMapping("/refresh")
public ApiSuccess<?> refreshAccessToken(HttpServletRequest request) {
- DTO
1
2
3
4
5
6
7
8
9
@Data
public class LoginFormDto {
@Schema(description = "Id", example = "apple")
private String username;
@Schema(description = "Password", example = "password123")
private String password;
}
애노테이션으로 손쉽게 API 문서를 작성할 수 있다.
결과
이제 각 API에 대해 필요한 요소, 응답 등을 한 눈에 볼 수 있는 문서가 완성되었다.