본문 바로가기
Spring

Spring boot - 서버의 존재하지 않는 URL 접근 시 예외 처리

by khds 2022. 4. 9.

 

프로젝트를 진행하면서 서버의 존재하지 않는 URL로 접근 시, 아래와 같이 404 Status코드와 함께 에러메시지가 반환되는 것을 보았다.

 

이 페이지는 사용자가 보기에 매우 가독성 없는 페이지다. 

이제 Spring boot에서 간단한 설정을 통해 위 페이지를 사용자의 가독성을 향상하도록 수정해 보겠다. 

여기서 사용할 것은 예외 처리를 위한 @ExceptionHandler이다. 

@ExceptionHandler에 대해 궁금한 사항은 https://khdscor.tistory.com/29를 참고하길 바란다.

 

스프링 @ExceptionHandler 를 통한 예외 처리

스프링으로 프로젝트를 진행하다 보면 정해진 입력값이 잘못되거나 없거나 하는 등 다양한 예외들이 발생할 것이다. 아래와 같이 흔히 JPA로 데이터를 가져올 때도 findById를 사용할 때 잘못될 경

khdscor.tistory.com

 

 

아래는 구현한 ExceptionHandler이다. 

@ControllerAdvice
public class ControllerAdvice {

    @ExceptionHandler(NoHandlerFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public String handleNotFoundError(NoHandlerFoundException ex, Model model) {
        model.addAttribute("errorMessage", "죄송하지만, 해당하는 페이지는 존재하지 않습니다.");
        return "error/404"; // error/404.html 파일로 이동
    }
}

 

NoHandlerFoundException은 Spring Framework에 기본적으로 존재하는 예외이다. 이 예외는 Spring MVC에서 요청을 처리할 핸들러(컨트롤러)를 찾지 못했을 때 발생한다. 즉, 존재하지 않는 URL로 접근 시 NoHandlerFoundException 예외가 발생한다. 그렇기에, ExceptionHandler를 통해 NoHandlerFoundException 예외가 발생 시 이를 캐치하여, 원하는 페이지, 데이터가 반환되도록 설정한 것이다. 

하지만 여기서 추가로 설정해줘야하는 작업이 있다. 

 이 예외는 기본적으로 활성화되어 있지 않기 때문에, 이를 활성화하는 과정이 필요하다. 

 

application.properties을 기준으로 아래와 같이 두 줄을 추가하자.

spring.mvc.throw-exception-if-no-handler-found=true
spring.web.resources.add-mappings=false

 

첫 번째 설정은 스프링 MVC가 핸들러를 찾지 못했을 때 NoHandlerFoundException을 던지도록 만든다.

두 번째 설정은 기본 리소스 핸들러를 비활성화한다.

 

설정 후 존재하지 않는 url로 실행 시 아래와 같이 원하는 메시지를 포함한 페이지를 노출시킬 수 있다.

 

아래는 html 파일이다. 

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Page Not Found</title>
</head>
<body>
<h1>죄송하지만, 해당하는 페이지는 존재하지 않습니다.</h1>
<p>URL을 다시 한번 확인해주세요.</p>
</body>
</html>

 

 

참고로 아래와 같이 RestAPI로 설정 또한 가능하지만, 데이터를 반환하기보단 페이지를 반환하는 것이 더 가독성 있는 화면을 제공할 수 있기에, @ControllerAdvice로 주로 설정한다.

@RestControllerAdvice
public class ControllerAdvice {

    @ExceptionHandler(NoHandlerFoundException.class)
    public ResponseEntity<ErrorResponse> handleNotIncludedMapException(NoHandlerFoundException e) {

        return ResponseEntity.status(HttpStatus.NOT_FOUND)
            .body(new ErrorResponse("잘못된 URL입니다. 다시 한번 확인해 주세요 "));
    }
}