Spring/API

Spring Boot OpenAPI 3.0 + Swagger version 3 적용 및 설정하기, Swagger에 JWT 기능 설정하기

JWonK 2023. 6. 21. 14:21
728x90
반응형

이번 프로젝트를 진행하면서 API 문서 정리가 요구되었고 Swagger 3.0 버전을 적용하여 개발한 API를 정리하고 테스트할 수 있도록 설정하였다. 그에 대한 과정을 정리해보고자 한다.

 

 

 

▶ build.gradle Swagger dependency 적용해주기

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

 

 

 

 

 

 

 

OpenAPI 3.0 + Swagger 3.0 Spring Boot에 설정하기 : @OpenAPIDefinition

  • info : 해당 Swagger 페이지가 무엇을 나타내는지 알려주기 위해 작성해준다.
@OpenAPIDefinition(
        info = @Info(title = "User-Service API 명세서",
                description = "사용자 어플 서비스 API 명세서",
                version = "v1"))
@Configuration
public class SwaggerConfig {

    ...
    
}

 

info 안에 

  • title : 어떤 API 명세서를 위한 Swagger 페이지인지 나타내어준다.
  • description : 설명을 작성해준다

위와 같이 작성해주면

이렇게 나타낼 수 있다.

 

또한, 설정 파일을 등록해주어야 하기 때문에 @Configuration으로 Component Scan 범위 영역 내에 존재하도록 설정해준다.

 

 

 

 

 

 

 

 

 

 

 

 

 

나는 해당 프로젝트의 인증 및 인가 기능을 Redis로 관리하는 JWT를 구현하여 관리하였다. Swagger에도 JWT를 적용하여 좀 더 쉽게 테스트하고 명세를 확인할 수 있게 해주어야 했다.

 

 

Swagger에 JWT 기능 가능하게 하기

JWT를 가능하게 하기 위해서는 Bean 등록으로 가능하게 해주면 된다.

@OpenAPIDefinition(
        info = @Info(title = "User-Service API 명세서",
                description = "사용자 어플 서비스 API 명세서",
                version = "v1"))
@Configuration
public class SwaggerConfig {

    @Bean
    public OpenAPI openAPI(){
        SecurityScheme securityScheme = new SecurityScheme()
                .type(SecurityScheme.Type.HTTP).scheme("bearer").bearerFormat("JWT")
                .in(SecurityScheme.In.HEADER).name("Authorization");
        SecurityRequirement securityRequirement = new SecurityRequirement().addList("bearerAuth");

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

위 코드를 SwaggerConfig 클래스 내에 Bean으로 등록해주면 된다.

 

 

해당 코드를 작성해준 후 다시 Swagger를 작동시키면 오른쪽에 있는 Authorize 버튼이 생긴다.

해당 버튼을 누르고 JWT를 입력하면 백엔드 코드에서 작성한 JWT 유효성 검증을 할 수 있고 유효성 여부에 따라 기능도 수행 여부를 결정할 수 있다.

 

 

 

 

 

 

 

 

 

 

 

Swagger JWT 인터셉터 또는 필터에 적용되지 않게 설정

프로젝트에서 JWT로 유효성 검증을 하기 때문에 Swagger Page는 JWT 유효성 검증이 필요 없도록 해줘야 한다. 안그러면 JWT 없이 Swagger 페이지에 접근할 수가 없다.

 

@RequiredArgsConstructor
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Value("${spring.url}")
    private static String URI;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(jwtTokenInterceptor())
                .excludePathPatterns(URI + "/swagger-resources/**", URI + "/swagger-ui/**", URI + "/v3/api-docs", URI + "/api-docs/**")
                .excludePathPatterns("/swagger-resources/**", "/swagger-ui/**", "/v3/api-docs", "/api-docs/**")
                .excludePathPatterns("/signUp", "/signIn", "/error/**", "/reissue")
                .addPathPatterns("/**");
    }

    @Bean
    public JwtTokenInterceptor jwtTokenInterceptor(){
        return new JwtTokenInterceptor(...);
    }
}

 

JWT 인터셉터를 WebMvcConfigurer를 상속받은 클래스에 설정해주고 동시에 swagger page는 해당 인터셉트에 종속되지 않도록 설정해주어야 모두가 Swagger 페이지에 접근하여 API 명세서를 확인하고 테스트 할 수 있다.

 

 

 

 

 

 

 

 

 

 

 

 

 

API 그룹 설정해주기 : @Tag

: API 그룹 설정은 각 Controller 클래스 상단에 작성해준다.

  • name : 작성한 Controller 클래스가 보여질 이름을 설정해준다.
  • description : 해당 API 그룹이 무엇을 나타내는지 알려준다.
@Tag(name = "QR 컨트롤러", description = "QR코드 API입니다.")
@RequiredArgsConstructor
@RestController
public class QRcontroller {
	...
}

이렇게 작성한 @Tag 코드는 아래와 같이 나타난다.

 

 

 

 

 

 

 

 

 

 

 

API Data Schema 적용해주기 : @Schema

  • description : 해당 data가 어떤 Data Schema를 나타내고자 하는 것을 명시
  • nullable : null이 가능한지 아닌지 설정
  • example : 해당 Data Schema 예시 값 설정
@Data
public class RequestUser {

    @NotNull(message = "Email cannot be null")
    @Size(min = 2, message = "Email not be less than two characters")
    @Email
    @Schema(description = "사용자 이메일", nullable = false, example = "k12@gmail.com")
    private String email;

    @NotNull(message = "Name cannot be null")
    @Size(min = 2, message = "Name not be less than two characters")
    @Schema(description = "사용자 이름", nullable = false, example = "김재한")
    private String name;

    @NotNull(message = "Password cannot be null")
    @Size(min = 8, message = "Password not be less than two characters")
    @Schema(description = "사용자 비밀번호", nullable = false, example = "pwd")
    private String password;

    @NotNull(message = "PhoneNumber cannot be null")
    @Schema(description = "사용자 핸드폰 번호", nullable = false, example = "010-12-31")
    private String phoneNumber;

}

나는 위와 같이 Data Schema를 설정하였고 추가로

  • @Notnull(message : _)를 통해 null일 경우 메세지를 출력해주는 validation과
  • @Size(min = _, message = _)로 최소 길이 설정과 출력 메세지 validation
  • @Email로 mail 형태의 값 입력을 요구하는 것을 작성하였다.

위와 같이 작성하면 Swagger 페에지 하단에 Data Schema에서

 

위와 같이 나타난다.

 

 

 

 

 

 

 

 

 

 

 

API 상세 정보 설정 : @Operation

  • summary : 해당 API가 무엇을 위한건지 간단하게 작성
  • description : 해당 API가 무엇을 위한건지 상세하게 작성

해당 @Operation은 Controller Class 내부 Method 위에 작성하게 된다. 예를 들어 아래와 같이 작성할 수 있다.

@Tag(name = "QR 컨트롤러", description = "QR코드 API입니다.")
@RequiredArgsConstructor
@RestController
public class QRcontroller {

    @Operation(summary = "QR 스캔", description = "사용자가 배송된 물품의 QR코드를 스캔합니다.")
    @PostMapping("/scan")
    public ResponseEntity<ResponseData> scanQR(HttpServletRequest request, @RequestBody RequestQRcode qrCode){
        ...
    }
}

 

해당 메서드가 무엇을 위한 건지 summary를 통해 간단하게 작성하고 description을 통해 정확이 어떤 것인지 작성해준다. 이렇게 작성하면 아래와 같이 Swagger 페이지에서 나타낼 수 있게 된다.

 

 

 

 

 

 

 

 

 

 

 

 

API Response 설정 : @ApiResponses

작성한 메서드가 반환하는 API Response를 작성하여 사용자가 쉽게 알아볼 수 있도록 해주는 기능이다. @ApiResponses는 여러 개의 @ApiResponse를 반영할 수 있고 하나의 @ApiResponse는

  • ResponseCode : 반환되는 Response의 상태 코드를 나타내어준다.
  • description : 반환되는 상태에 따라 어떤 상태인지 결과인지를 설명해준다.
  • content : 반환되는 데이터가 무엇인지 반환해준다. 
@Tag(name = "QR 컨트롤러", description = "QR코드 API입니다.")
@RequiredArgsConstructor
@RestController
public class QRcontroller {

    @Operation(summary = "QR 스캔", description = "사용자가 배송된 물품의 QR코드를 스캔합니다.")
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "스캔 성공", content = @Content(schema = @Schema(implementation = ResponseData.class))),
            @ApiResponse(responseCode = "401", description = "인가 기능이 확인되지 않은 접근", content = @Content(schema = @Schema(implementation = ResponseError.class))),
            @ApiResponse(responseCode = "404", description = "존재하지 않는 리소스 접근", content = @Content(schema = @Schema(implementation = ResponseError.class))),
            @ApiResponse(responseCode = "500", description = "서버 오류 발생", content = @Content(schema = @Schema(implementation = ResponseError.class)))
    })
    @PostMapping("/scan")
    public ResponseEntity<ResponseData> scanQR(HttpServletRequest request, @RequestBody RequestQRcode qrCode){
        ...
    }
}

위와 같이 작성할 수 있고 content 내부에는 또 다른 형태의 어노테이션이 붙은 @Content를 반환해준다. 안에는 직접 설정한 클래스를 명시하여 반환 꼴을 명시해준다.

 

 

@Data
@AllArgsConstructor
public class ResponseData<T> {

    @Schema(description = "상태 코드", nullable = false, example = "200")
    private String status;

    @Schema(description = "상태 메세지", nullable = false, example = "성공하였습니다.")
    private String message;

    @Schema(description = "데이터", nullable = false)
    private T data;

    @Schema(description = "Access Token", nullable = false)
    private String accessToken;
}

 

설명한 대로 작성하면 이러한 형태로 Swagger에 보여지게 된다.

728x90
반응형