본문 바로가기
Backend/Spring

[Spring] 예외처리는 곧 유비무환

by Everyday Sustler 2023. 12. 26.
반응형

내가 코드를 작성할 때는 파일 시스템은 안정적이며 네트워크는 원활하게 연결되어 있으며 JVM이 차지하는 메모리는 여유있는 이상적인 상황을 가정한다.

 

이를 일컬어 Happy Path 라고 말하는 것 같은데, 소위 말하자면 머리가 꽃밭에 있어서 아무 걱정이 없는 상태다.

 

그러나 소프트웨어는 단지 현실의 문제를 가상화한 모델링 결과일 뿐이다. 

 

현실은 더욱 복잡하고 가차없으며 저렇게 작성했던 내 과거의 코드들은 무분별하게, 잔인하게, 야만적인 느낌이 들 만큼 Exception(예외)을 뿌려주었다.

 

연결된 네트워크 이상으로 전달이 지연되거나 실패하는 경우, 갑작스런 접속자 폭증으로 응답이 지연되는 경우 등은 기본.

 

사전에 공유된 내용도 없이 인터페이스 내용이 바뀐다거나 기준 정보가 변경되는 경우도 배제할 수 없다.

 

결국... 유비무환(有備無患)이다.

 

수많은 다이어그램들이 소프트웨어 설계의 결과라고 한다면, 예외 처리 코드는 운영자의 경험과 고민의 결과라고 생각한다.

 

감사합니다 @ControllerAdvice

@ControllerAdvice 어노테이션을 가진 클래스는 @Controller 클래스들에 공유되며,

@ExceptionHandler, @InitBinder, @ModelAttribute 를 구현하는 @Component 어노테이션의 구현체가 된다.

 

간단하게 얘기하자면 아래 코드는 이제 모든 컨트롤러 클래스들에 공유된다.

@ControllerAdvice
public class SampleExceptionController {
    @ExceptionHandler
    protected ResponseEntity<String> exceptionHandlerExample(RuntimeException e){
        return ResponseEntity.ok(e.getMessage());
    }
}

 

그렇기 때문에 어떤 컨트롤러에서든 RuntimeException 예외가 발생하면 이 @ExceptionHandler 위치한 메소드로 넘어와 하기 동작을 수행한다.

 

대표적인 예외 타입들을 묶어 표현해 놓으면 나름대로 안정적으로 동작하는 모습을 볼 수 있게 해준다.

 

물론! 여기에 만족하면 큰일난다.

 

@ControllerAdvice 사용할 때 놓치지 않아야 할 간단한 실험

만약 아래와 같이 RuntimeException 예외를 인자로 받는 핸들러를 하나 더 만들어 본다면 어떻게 될까?

@ControllerAdvice
public class SampleExceptionController {
    @ExceptionHandler
    protected ResponseEntity<String> exceptionHandlerExample(RuntimeException e){
        return ResponseEntity.ok(e.getMessage());
    }

    @ExceptionHandler
    protected ResponseEntity<String> exceptionHandlerExample2(RuntimeException e){
        return ResponseEntity.ok(e.getMessage());
    }
}

 

Ambiguous @ExceptionHandler method mapped for... 이란 메시지를 뱉어내며 빌드가 되지 않는다.

 

RuntimeException 관련 예외를 모두 한 번에 처리해주기 때문에 편리하지만, 만족하지 않고 조금 더 세분화하려는 노력이 필요하다.

 

한 개 클래스 내에서 같은 인자를 받는 경우를 실험해봤다면, 두 개 이상을 클래스에서 같은 인자를 받는 실험은 어떻게 동작할까?

 

만약 서로 동시에 2개 클래스에서 @ControllerAdvice 어노테이션을 가진 상태에서 RuntimeException 예외를 인자로 받는다면?

 

예상외로 이러한 유형의 중복 선언은 앞선 케이스와 달리 정상적으로 빌드된다.

 

와 그럼 그냥 써도 되겠다.

 

안 된다.

 

그치만 둘 중 어떤 것에서 에러를 처리하는지 알 수 없기 때문에 덕지덕지 예외를 바르다 보면 디버깅에 난항을 겪을 것이 분명해 보인다.

 

추천하는 글

 

이 링크에 상세한 내용들이 많이 정리되어 있다.

  • Throwable, Exception, Error, RuntimeException 등 모호했던 개념들을 예시와 함께 설명
  • 예외를 발생시키는 방법과 처리하는 방법
  • 예외 처리에서 피해야 할 패턴 (Anti-pattern)
반응형

'Backend > Spring' 카테고리의 다른 글

[Spring] Proxies in JPA  (0) 2023.05.30