티스토리 뷰

Spring Boot WebFlux - Thymeleaf 환경에서 에러 핸들링 하는 방법을 소개한다.

아래는 참고한 가이드

 

https://www.baeldung.com/spring-webflux-errors

 

Handling Errors in Spring WebFlux | Baeldung

Have a look at different methods to gracefully handle errors in Spring Webflux.

www.baeldung.com

하지만 위 예제는 error status에 따른 json return만 구현되어있기 때문에,

우리가 통상적으로 생각하는 404/500에 대한 error 처리를 하기 위해서는 추가적인 작업이 필요하다.

 

완성된 코드는 아래와 같다.

 

@Component
@Order(-2)
public class ExceptionHandlerConfiguration extends AbstractErrorWebExceptionHandler {
    
    
    public ExceptionHandlerConfiguration(ErrorAttributes errorAttributes,
                                         ResourceProperties resourceProperties,
                                         ApplicationContext applicationContext,
                                         ObjectProvider<List<ViewResolver>> viewResolversProvider,
                                         ServerCodecConfigurer configurer) {
        super(errorAttributes, resourceProperties, applicationContext);
        this.setMessageWriters(configurer.getWriters());
        this.setViewResolvers(viewResolversProvider.getIfAvailable());
    }
    
    @Override
    protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
        return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
    }
    
    private Mono<ServerResponse> renderErrorResponse(ServerRequest request) {
        Map<String, Object> errorPropertiesMap = getErrorAttributes(request, false);
        
        /*int status = (int) errorPropertiesMap.get("status");
        
        // status에 따른 분기처리 (html view)
        if(status >= 500){
            return ok().render("error/500");
        }else{
            return ok().render("error/404");
        }*/
    
        // json return
        return ServerResponse.status(HttpStatus.BAD_REQUEST)
            .contentType(MediaType.APPLICATION_JSON_UTF8)
            .body(BodyInserters.fromObject(errorPropertiesMap));
        
    }
    
}

 

 

 

@Component
@Order(-2)
public class ExceptionHandlerConfiguration extends AbstractErrorWebExceptionHandler {
	...
}

configure의 순서를 정렬한다.

Spring Boot에서 DefaultErrorWebExceptionHandler가 -1, ResponseStatusExceptionHandler가 0으로 설정되어 있기 때문에

-2로 내려야 위 요소들보다 먼저 배치되게 된다.

 

 

 

public ExceptionHandlerConfiguration(ErrorAttributes errorAttributes,
                                         ResourceProperties resourceProperties,
                                         ApplicationContext applicationContext,
                                         ObjectProvider<List<ViewResolver>> viewResolversProvider,
                                         ServerCodecConfigurer configurer) {
        super(errorAttributes, resourceProperties, applicationContext);
        this.setMessageWriters(configurer.getWriters());
        this.setViewResolvers(viewResolversProvider.getIfAvailable());
}

생성자에서 AbstractErrorWebExceptionHandler의 생성자를 호출하고,

그 아래에 MessageWriter와 ViewResolver를 정의한다. (이게 가장 핵심)

인자로 List<ViewResolver>를 받아오는데, 이때 사용중인 템플릿 엔진이 Thymeleaf라면 ThymeleafResolver가

다른 템플릿 엔진이라면 다른 리졸버가 들어올것이다.

 

해당 부분을 정의하지 않으면 DefaultRenderingResponseBuilder.writeToInternal에서 ViewResolver를 찾지 못하기 때문에

500에러가 발생하게 된다.

 

 

 

@Override
protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
	return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
}

라우팅 부분이다.

모든 요청에 대해 받되, ErrorAttributes 인자가 있을 경우 renderErrorResponse 함수가 실행되게 된다.

 

 

private Mono<ServerResponse> renderErrorResponse(ServerRequest request) {
        Map<String, Object> errorPropertiesMap = getErrorAttributes(request, false);
        
        /*int status = (int) errorPropertiesMap.get("status");
        
        // status에 따른 분기처리 (html view)
        if(status >= 500){
            return ok().render("error/500");
        }else{
            return ok().render("error/404");
        }*/
    
        // json return
        return ServerResponse.status(HttpStatus.BAD_REQUEST)
            .contentType(MediaType.APPLICATION_JSON_UTF8)
            .body(BodyInserters.fromObject(errorPropertiesMap));
        
}

해당 부분에서 실질적인 에러 처리를 진행한다.

주석처리 된 부분은 템플릿 엔진을 사용중일 경우 해당 html view가 노출되도록 return하는 부분이며,

최하단의 return은 JSON형식으로 에러정보가 return된다.

(필자의 경우에는 Thymeleaf를 사용중이기 때문에, error/404를 호출시 실제로는 reousrces/templates/error/404를 바라보게 된다.)

 

에러코드에 대한 정의와 어떤 템플릿을 보여줄것인지, 어떤 요청이 들어왔을때 어떻게 리턴해줄것인지는

각 사용자가 입맛에 맞게끔 구현 해 사용하면 될것이다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함