[Spring Boot] Swagger의 비즈니스 코드 개입 최소화하기

윤진원·2023년 5월 2일
8

Spring Boot

목록 보기
1/6
post-thumbnail

❗️ 문제 상황

필자는 현재 캡스톤 디자인(졸업 작품)을 제작중이고, 꾸준히 개발하고 리팩토링하는 중이다.

그러던 와중, 연구실 동료의 추천으로 Swagger 라는 것을 알게 되었고, 바로 프로젝트에 적용을 해보았다.


Swagger란?

애플리케이션의 Restful 문서를 자동으로 구성해주는 특수 도구

  • 쉽게 말하면 Swagger가 프로젝트의 API 명세를 자동으로 파악하고, 관리해준다.
  • Swagger를 사용하면 API를 추가, 삭제 및 변경할 때 용이하다.

현재 나는 Notion에 API 명세를 정리하고, 기록해왔다.
하지만 잦은 변경과 추가로 인해 빠뜨린 부분이 생겼고, 응답과 요청값 또한 매번 변경되기 쉽다.


하지만 Swagger를 사용하면 서버를 실행시키면 지정한 URI에서 API 명세를 쉽게 볼 수 있다!


하지만, 큰 단점이 하나 존재한다.

바로 컨트롤러에 너무 많은 개입이 된다는 것! 이게 무슨 말일까?

우선 Swagger의 사용법부터 알아보자.


Swagger 사용법

  1. build.gradle 에 해당 의존성을 추가해준다.
  • 버전이 변경되어서 꼭 이 의존성을 추가해야 한다!
  • 옛 버전의 의존성을 추가하면 동작이 되지 않는다.
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0'

  1. 우선, Swagger 설정 파일을 하나 생성한다.
  • 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);
    }
}

  1. 원하는 API에 Swagger 어노테이션을 붙여서 사용한다.
  • ex) 회원 가입 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);
    }
  • @Operationsummary 속성 :
  • @ApiResponseresponseCode 속성 :

Swagger의 문제점

위에서 봐서 알겠지만, API 각각 모두 Swagger 코드를 붙여줘야 한다!

  • 물론 모두 이름도 다르고, 응답값이나 에러코드가 다르기 때문에 중복될 수가 없다!
  • 그럼 이렇게 하나하나 다 다르게 붙여줘야 하나?..

이런 고민을 하던 도중, 커스텀 어노테이션이라는 것이 생각났다!

  • 지금부터 커스텀 어노테이션을 활용하여 Swagger 코드를 최소한으로 작성해보자.

💡 문제 해결

  1. 성공, 에러 코드등 상황에 맞는 커스텀 어노테이션을 생성해준다.
  • 참고로 필자는 성공(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 역시 마찬가지이다.

  • 이 부분에서 고민을 많이 하였다. 커스텀 어노테이션은 뭔지 알겠는데, 그럼 원래 있던 어노테이션의 속성을 어떻게 갖다쓰지? 라는 의문이 들었다😭.

  1. 결과적으로는, 비즈니스 코드에 10줄 이상으로 개입하던 Swagger 코드가, 단 두 줄로 줄어든 것을 볼 수 있다!
@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);
}

  1. Swagger ui를 통해 확인해봐도 동일하다.

👍🏻 결론

API 명세를 자동으로 관리해주고, ui로 확인할 수 있는 편리한 Swagger를 비즈니스 코드의 개입을 최소화하면서 사용해보자!

  • 다음엔 Spring RestDocs를 써보자.
profile
기억보단 기록을

2개의 댓글

comment-user-thumbnail
2023년 5월 11일

중복을 줄여야겠네요.

답글 달기
comment-user-thumbnail
2023년 5월 11일

졸업작품때 Swagger와 Custom annotation을 사용할려고 했는데 글보고 해결했습니다 ^^ 감사합니다

답글 달기