필자는 현재 캡스톤 디자인(졸업 작품)을 제작중이고, 꾸준히 개발하고 리팩토링하는 중이다.
그러던 와중, 연구실 동료의 추천으로 Swagger 라는 것을 알게 되었고, 바로 프로젝트에 적용을 해보았다.
애플리케이션의 Restful 문서를 자동으로 구성해주는 특수 도구
현재 나는 Notion에 API 명세를 정리하고, 기록해왔다.
하지만 잦은 변경과 추가로 인해 빠뜨린 부분이 생겼고, 응답과 요청값 또한 매번 변경되기 쉽다.
하지만 Swagger를 사용하면 서버를 실행시키면 지정한 URI에서 API 명세를 쉽게 볼 수 있다!
하지만, 큰 단점이 하나 존재한다.
바로 컨트롤러에 너무 많은 개입이 된다는 것! 이게 무슨 말일까?
우선 Swagger의 사용법부터 알아보자.
build.gradle
에 해당 의존성을 추가해준다.implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0'
SwaggerConfig.java
@Configuration
public class SwaggerConfig {
@Bean
public OpenAPI openAPI() {
Info info = new Info()
.version("v1.0.0")
.title("Santa Clothes API")
.description("Santa Clothes API 명세입니다.");
return new OpenAPI()
.info(info);
}
}
회원 가입 API
@Operation(summary = "회원 가입")
@ApiResponses(value = {
@ApiResponse(
responseCode = "200",
content = @Content(schema = @Schema(implementation = CreateUserResponse.class))),
@ApiResponse(
responseCode = "404",
content = @Content(schema = @Schema(implementation = Error.class))),
@ApiResponse(
responseCode = "409",
content = @Content(schema = @Schema(implementation = Error.class)))
})
@PostMapping("/api/auth/signup")
public CreateUserResponse saveUser(@RequestBody @Valid final CreateUserRequest request) {
Long id = userService.join(request);
return new CreateUserResponse(id);
}
@Operation
의 summary
속성 : @ApiResponse
의 responseCode
속성 : 위에서 봐서 알겠지만, API 각각 모두 Swagger 코드를 붙여줘야 한다!
이런 고민을 하던 도중, 커스텀 어노테이션이라는 것이 생각났다!
200
)은 API마다 공통적임으로 하나로 만들고, 나머지는 중복되고 상황에 맞는 에러 코드에 맞추어 생성해주었다.@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Operation()
@ApiResponses(value = {
@ApiResponse(responseCode = "200")
})
public @interface SwaggerApiSuccess {
String summary() default "";
Class<?> implementation();
}
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Operation()
@ApiResponses(value = {
@ApiResponse(
responseCode = "404",
content = @Content(schema = @Schema(implementation = Error.class)))
})
public @interface SwaggerApiNotFoundError {
}
위 코드와 동일하게 작성하면,
summary
속성은 사용자 입맛대로 API에 맞추어 설정할 수 있고,implementation
역시 마찬가지이다.
- 이 부분에서 고민을 많이 하였다. 커스텀 어노테이션은 뭔지 알겠는데, 그럼
원래 있던 어노테이션의 속성을 어떻게 갖다쓰지?라는 의문이 들었다😭.
@SwaggerApiSuccess(summary = "회원 가입", implementation = CreateUserResponse.class)
@SwaggerApiConflictError
@PostMapping("/api/auth/signup")
public CreateUserResponse saveUser(@RequestBody @Valid final CreateUserRequest request) {
Long id = userService.join(request);
return new CreateUserResponse(id);
}
API 명세를 자동으로 관리해주고, ui로 확인할 수 있는 편리한 Swagger를 비즈니스 코드의 개입을 최소화하면서 사용해보자!
중복을 줄여야겠네요.