Swagger Operation Customizing

GEONNY·2024년 8월 13일

Building-API

목록 보기
22/28
post-thumbnail

📌OperationCustomizer

Swagger 는 OpeartionCustomizer interface 를 통해서 전체 Operation 에 대한 커스텀 기능을 제공합니다.
org.springdoc.core.customizers.OperationCustomizer

@FunctionalInterface
public interface OperationCustomizer {
	Operation customize(Operation operation, HandlerMethod handlerMethod);
}

OperationCustomizer 를 활용하여 공통적으로 발생할수 있는 Response 를 Swagger Responses 에 추가하는 방법을 알아보겠습니다.
config.swagger.SwaggerConfig 파일을 열어 OperationCustomizer 를 리턴하는 method를 Bean으로 등록 합니다. 그리고 해당 OperationCustomizer 를 v1 group 에만 추가해 줍니다.

@Bean
public GroupedOpenApi version1APi() {
        return GroupedOpenApi.builder()
                .group("v1.0")
                .pathsToMatch("/v1/**")
                .addOperationCustomizer(operationCustomizer()) //OperationCustomizer 추가
                .build();
}

/*중간 생략*/

@Bean
public OperationCustomizer operationCustomizer() {
    return (operation, handlerMethod) -> {
        return operation;
    };
}

디버깅 포인트를 걸어 operation과 handlerMethod의 내용을 확인해보겠습니다. 이전에 @Operation으로 정보를 등록했던 getMemberById method 를 기준으로 보겠습니다.

📌operaion, handlerMethod 확인

operation 객체에는 @Operation 의 속성으로 등록했던 내용들이 포함되어 있습니다.

handlerMethod 에는 해당 컨트롤러의 정보가 포함되어 있습니다.

유효성 체크에 대한 공통 Error Response를 추가하려면 operation 내 responses 에 추가해야 합니다. 우선 이전에 설정한 GlobalExceptionHandler 내에 @Valid 와 @Validated 에서 발생시키는 MethodArgumentNotValidException, ConstraintViolationException @ExceptionHandler 부분을 확인합니다.

    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public ResponseEntity<ErrorResponse> handleMethodArgumentInValid(
    		MethodArgumentNotValidException e) {
        StringJoiner stringJoiner = new StringJoiner(", ");
        e.getFieldErrors().forEach(fieldError -> {
            stringJoiner.add(fieldError.getField() + ": " + fieldError.getDefaultMessage());
        });
        return generateErrorResponse(ErrorCode.INVALID_PARAMETER, 
        	new InvalidParameterException(stringJoiner.toString()));
    }

    @ExceptionHandler(value = ConstraintViolationException.class)
    public ResponseEntity<ErrorResponse> handleConstraintViolation(
    		ConstraintViolationException e) {
        return generateErrorResponse(ErrorCode.INVALID_PARAMETER,
                new InvalidParameterException(e.getMessage()));
    }

모두 ErrorCode.INVALID_PARAMETER 를 전달하고 있습니다. common.code.ErrorCode 를 확인해보면 INVALID_PARAMETER 의 코드는 ERR_CE_01 이고 resources/messages/message.properties 설정된 메시지는 적합하지 않은 값이 전달되었습니다. 입니다. 해당 내용을 모든 Operation 에 추가하기 위해서 operationCustomizer method 를 수정합니다.

📌공통 Response 추가

@Configuration
@RequiredArgsConstructor
public class SwaggerConfig {

    private final MessageConfig messageConfig;
    
    // 중간생략
    
    @Bean
    public OperationCustomizer operationCustomizer() {
        return (operation, handlerMethod) -> {
            operation.getResponses().addApiResponse("ERR_CE_01", getInvalidParameterResponse());
            return operation;
        };
    }

    public ApiResponse getInvalidParameterResponse() {
        ApiResponse apiResponse = new ApiResponse();
        apiResponse.setDescription("유효하지 않은 인자가 전달됨");
        addContent(apiResponse, ErrorCode.INVALID_PARAMETER);
        return apiResponse;
    }

    private void addContent(ApiResponse apiResponse, ErrorCode errorCode) {
        Content content = new Content();
        MediaType mediaType = new MediaType();
        Schema<Object> schema = new Schema<>();
        schema.$ref("#/components/schemas/ErrorResponse");
        mediaType.schema(schema).example(ErrorResponse.builder()
                .status(messageConfig.getCode(errorCode))
                .message(messageConfig.getMessage(errorCode))
                .build());
        content.addMediaType("application/json", mediaType);
        apiResponse.setContent(content);
    }
}

다른 공통적인 Response도 추가해서 쓸 수 있도록 content 를 추가하는 addContent 를 별도의 method 로 분리합니다. 실행해서 확인해보면 모든 Operation 에 ERR_CE_01 에 대한 response 가 추가된 것을 확인할 수 있습니다.

📌Response 정보 수정

회원 ID로 회원 조회 Operation 의 경우에는 @ApiResponse 를 설정해 주었기 때문에 위와 같이 표출이 되지만 설정하지 않은 다른 Operation 들은 정상응답에 대한 코드가 200으로 설정되어 있습니다. 정상 응답에 대한 Operation Code를 200 에서 OK 로 변경하기 위해 OperationCustomizer를 수정합니다.

    @Bean
    public OperationCustomizer operationCustomizer() {
        return (operation, handlerMethod) -> {
            ApiResponses apiResponses = operation.getResponses();
            if (apiResponses.containsKey("200")) {
                ApiResponse normalResponse = operation.getResponses().get("200");
                normalResponse.description("정상 응답");
                apiResponses.put("OK", normalResponse);
                apiResponses.remove("200");
            }
            apiResponses.addApiResponse("ERR_CE_01", getInvalidParameterResponse());
            return operation;
        };
    }

다른 공통 Response 를 추가해야 될 경우에는 getInvalidParameterResponse method 와 같이 추가하고 apiResponses 에 add 해주면 됩니다.

profile
Back-end developer

0개의 댓글