[Swagger] Spring 3.X + Swagger 사용해보기

chrkb1569·2024년 2월 2일

이전에 진행했던 팀 프로젝트를 살펴보던 중, 협업 툴로 Swagger를 사용했던 프로젝트가 있었습니다.

그런데 Spring 버전이 3가 넘어가면서, 이전에 했던 설정으로는 Swagger를 사용할 수 없더라구요.

그래서 오늘은 Spring 3.x 버전에서 어떻게하면 Swagger를 사용할 수 있는지 살펴보도록 하겠습니다.

변경된 Swagger 설정 방식은 다음의 Swagger 공식 문서를 참고하였습니다.

https://www.bezkoder.com/spring-boot-swagger-3/

개발 환경

  • Spring Boot 3.1.2
  • Java 17
  • Spring Security 6.2
  • Gradle

추가 의존성

이전에 Swagger를 사용하기 위해서는

implementation 'io.springfox:springfox-boot-starter:3.0.0'

다음의 의존성을 사용했지만, 변경된 의존성은 다음과 같습니다.

implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2'

따라서, 기존에 springfox를 사용하시던 분들은 이전 의존성을 제거하시고, 새로운 의존성을 추가해주셔야 Spring 3.x 버전에서 Swagger를 사용하실 수 있습니다.

사실 의존성을 추가한 뒤, /swagger-ui/index.html에 접근하여 Swagger 문서를 사용할 수 있지만, 저는 프로젝트에서 인증 방식으로 Spring Security + JWT를 활용하고 있기 때문에 다음처럼 추가 설정을 해주었습니다.

추가 설정

SwaggerConfig

import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.info.Info;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.List;

@Configuration
@OpenAPIDefinition(
        info = @Info(
                title = "index 페이지에 들어갈 제목",
                description = "index 페이지에 들어갈 내용"
        )
)
public class SwaggerConfig {
    @Bean
    public OpenAPI openAPI() {
        SecurityScheme securityScheme = getSecurityScheme();
        SecurityRequirement securityRequirement = getSecurityRequireMent();

        return new OpenAPI()
                .components(new Components().addSecuritySchemes("bearerAuth", securityScheme))
                .security(List.of(securityRequirement));
    }

    private SecurityScheme getSecurityScheme() {
        return new SecurityScheme().type(SecurityScheme.Type.HTTP).scheme("bearer").bearerFormat("JWT")
                .in(SecurityScheme.In.HEADER).name("Authorization");
    }

    private SecurityRequirement getSecurityRequireMent() {
        return new SecurityRequirement().addList("bearerAuth");
    }
}

SecurityConfig

import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import umc.precending.config.jwt.*;

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
    private final JwtAuthenticationEntryPointHandler authenticationEntryPointHandler;
    private final JwtAccessDeniedHandler accessDeniedHandler;
    private final TokenProvider tokenProvider;
    private final String[] swaggerPath = {"/swagger-ui/**", "/v3/api-docs/**", "/swagger-resources/**", "/error"};
    private final String AUTH_PATH = "/api/auth/**";

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public SecurityFilterChain configure(HttpSecurity http) throws Exception {
        http.csrf(AbstractHttpConfigurer::disable)
                .formLogin(AbstractHttpConfigurer::disable)
                .exceptionHandling(
                        security -> security
                                .authenticationEntryPoint(authenticationEntryPointHandler)
                                .accessDeniedHandler(accessDeniedHandler))
                .sessionManagement(
                        security -> security
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .authorizeHttpRequests(
                        security -> security
                                .requestMatchers(HttpMethod.POST, AUTH_PATH).permitAll()
                                .requestMatchers(swaggerPath).permitAll()
                                .anyRequest().authenticated())
                .apply(new JwtSecurityConfig(tokenProvider));

        return http.build();
    }
}

Spring Security는 버전이 변경됨에 따라서 람다식을 권장하고 있기 때문에 다음처럼 람다식을 사용하였습니다.

그럼 다음처럼 이전에 사용했던 Swagger UI를 확인할 수 있습니다.

변경된 Annotation

의존성을 변경함에 따라, 이전에 사용했던 수많은 어노테이션들이 먹통이 되었을 것입니다.
저 또한 의존성을 변경하니까 자주 사용하던 @ApiOperation, @ApiImplicitParam, @ApiModelProperty와 같은 어노테이션들에서 빨간줄이 떴습니다.

이러한 어노테이션들은 다음으로 변경하여 사용할 수 있습니다.

@Tag -> Swagger에서 Controller에 대한 설명 추가 가능

  • option :
    - name : Controller 이름
    • description : Controller 설명
  • 사용 예시

@Operation -> 기존 @ApiOperation과 동일한 기능 수행

  • option :
    - method : 요청시 사용할 HTTP Method
    • summary : API 요약 설명
    • description : API 상세 설명
  • 사용 예시

@Schema -> 기존 @ApiModelProperty와 동일한 기능 수행

  • option :
    - description : 필드에 대한 설명
    - example : 입력값 예시

0개의 댓글