• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    미해결

예상치못한 예외가 throw 되었을 경우의 Response 처리에 관련하여 질문드립니다

19.02.28 23:05 작성 조회수 235

2

실제로 컨트롤러에서 처리를 하다보면, 예상치 못한 에러가 발생하는 경우가 있는 것 같습니다. 가령 강의의 예제에서는 JSON serialization, deserialization 과정에서 checked exception이 발생할수 있으며, Repository객체를 사용하는 경우에는 DataAccessException 런타임 예외가 발생할 수 있을 것 같습니다. 이러한 경우들에도 적절한 응답을 돌려주고 싶은데, 그 때의 베스트 프렉티스에 대해서 여쭤보고자 합니다.

  1. 결국 @ExeptionHandler 라는 어노테이션이 붙은 메소드를 최소한 글로벌하게 하나는 만들어서 인터널 서버 에러(500)에 매핑시키게 되는 꼭 필요한 부분이라고 생각하는데, 맞는 생각일까요? 잘못하면 에러 로그를 view로 보여주게 될 것 같아서 그것을 방지하고자 함입니다.
  2. @ExceptionHandler

    public void globalExecptionHandler(Exception e) {

    return ResponseEntity.internalServerError();

    }

  3. 컨트롤러 내부에서도 결국 적어도 Unchecked Runtime Exception을 잡기 위해서 @ExceptionHandler를 정의하면 컨트롤러별로 예상치 못한 예외를 적절히 핸들링해 필요한 처리를 할 수 있게 되기 때문에 정의하는 것이 좋을것 같다고 생각하는데요, 이렇게 정의 했을 때 제가 고민되는 부분이 있습니다. 예제에서 나오는 것처럼 로직으로 인해서 발생하는 에러는 ResponseEntity를 리턴하는 형태로 처리하고, 그 외의 에러는 @ExceptionHandler로 잡게되면, 에러를 2가지 서로 다른 방법으로 처리함으로서 코드의 가독성을 해치는게 아닐까라고 생각해 보았습니다.
  4. 그렇다고 ResponseEntity로 통일하고자하면, 컨트롤러 메소드 각각에서 반드시 return으로 예외를 처리해야 하기 때문에, 컨트롤러 메소드 마다 try catch로 감싸주고 catch(Exception e) 같은 블록에서 반복적으로 internalServerError를 리턴해야만 하는 문제가 있습니다.
  5. 그리고 @ExceptionHandler로 통일하고자하면, throw 문을 goto처럼 사용하는 것이되어, 코드의 가독성을 해칩니다. 하지만 동시에 컨트롤러 메소드 내부의 if else를 줄여 줘서 가독성을 증가시키고, 컨트롤러 / 기타 빈 객체의 책임을 나누는 효과도 있습니다. 가령 service레벨이나 레포지토리 레벨에서 여러 데이터를 종합하다보니(MSA설계에서 자주 있는것 같습니다) 상황에 따라 200대가 아닌 리스폰스를 돌려줘야 할 필요가 있는 경우, 이것을 controller에서 호출한 service.method()의 리턴값으로 돌려줘서 컨트롤러에서 if else로 처리하게 되겠죠. 하지만 적절한 예외를 정의하여 그것을 컨트롤러가 아닌 webmvc빈에서 throw를 하여 ExceptionHandler가 처리하도록 하면, 컨트롤러 메소드 코드를 간결하게 할 수 있을 것 같습니다. 하지만 역시 throw 를 goto처럼 써서 가독성을 떨어뜨리는게 아닐까 하는 부담감이 있기도 하네요.

이런 것들을 복합적으로 고민해서 어떻게 1) 예제처럼 간단하게 체크해서 발생시킬수 있는 에러 2) 복잡한 상황에서 컨트롤러 객체가 아닌 곳에서 확인할 수 있는 에러 3) 예상치못한 런타임 에러(Repository connection pool error, httpclient socket timeout ...)를 깔끔하게 처리하여 클라이언트에 돌려줄 수 있을지 고민입니다. 어떻게 하는게 베스트일까요?

답변 2

·

답변을 작성해보세요.

2

애플리케이션 전반에 대한 에러는 언급하신대로 @ExceptionHandler를 만들어서 @ControllerAdvice안에 두고 글로벌 예외 핸들러를 쓰게 하는 것도 좋은 방법입니다.

하지만 특정 컨트롤러 로직(입력값 바인딩, 검증, 로직적인 검증)에서 발생하는 에러는 글쎄요. 그것도 뭔가 일반화 시켜서 공통적인 에러 핸들러로 처리할 수 있으면 좋긴하겠지만 그 컨트롤러에 특화된 로직이라면 그 위치에서 처리하는게 명시적이지 않을까 싶네요.

딱히 정해진 답이 없으니 여러 방법으로 해보시고 경험을 공유해 주시면 좋겠습니다.

좋은 질문 감사합니다.

0

김수님의 프로필

김수

질문자

2019.03.01

빠른 답변 감사드립니다!