예외 처리에 대한 고찰
안녕하세요 🐸
오늘은 제가 일하면서 고민하고 생각했던 부분에 대해 기록을 남겨보고자 합니다.
미래에 더 나은 해답을 찾은 제가 과거의 저를 기억할 수 있도록 하고 싶습니다.
오늘은 예외 처리에 대해 발생한 문제에 대한 생각을 기록해 놨기 때문에 예외의 구조 및 예외 처리 전략 등에 대해 알고 있는 것이 좋습니다.
기억이 안나거나 알고있더라도 기억이 잘 안난다면
자바의 예외 구조와 예외 처리
를 읽고 간단하게 알고 가는 것이 좋겠습니다.
문제
- Throwable을 catch 해도 괜찮은가?
- 컨트롤러에서 throw 하는 것이 옳은가?
Throwable을 catch 해도 괜찮은가?
반대
아니다. 분명히 문제가 있을 것이다. 여기서 먼저 알아야 할 것은 Throwable 객체의 구조를 알아야 한다.
Exception은 상관 없지만 Error는 서버에 심각한 문제를 발생 시킬 수 있는 문제이기 때문에 Error는 catch 하면 안된다.
공식 문서에서도 Error에 대해서 다음과 같이 설명하고 있다.
An
Error
is a subclass ofThrowable
that indicates serious problems that a reasonable application should not try to catch.
catch 하려하면 안된다고 명확하게 적혀있다.
찬성
현재 상황에서 Throwable을 catch하여 클라이언트에게는 적절한 메세지를 보여주고 서버에는 어떠한 요청이 왔는지, 무엇을 목적으로 하는지에 대해 로그를 남기고 있다.
Error 발생 시 어차피 서버는 죽는다. 이 경우 Throwable을 catch하지 않는다면 서버가 죽었을 때 남는 로그는 어떤 Error 인지에 대해서만 남게된다. 결국 무엇을 목적으로 어떠한 요청이 왔을 때 이러한 Error 가 발생하는지를 추적하기 어렵다.
그리고 Error 발생 시 고객에게 오류 정보, 서버 정보가 노출될 우려가 있다.
지금 까지 서비스 운영하면서 Error로 인해 서버가 다운되었을 때 실무자는 전부 이를 복구하기 위해 투입된다. 이 때 이러한 정보라도 없으면 원인을 추적하는데 매우 힘들다.
Error에는 서버를 중단시킬 수 있는 큰 문제들이 있다고 하지만 실제로는 그렇게 심각하지 않은 문제도 Error에 있는 경우가 존재한다. 이런 케이스는 추적하기 매우 힘들어진다
문제 제기
Error 발생 원인 추적을 위한 로깅이 목적이라면 예외 핸들러를 통해 로그를 남기면 안되는 건가?
현재 서비스는 SimpleMappingExceptionResolver
를 상속받아 resolveException()
를 오버라이드하여 구현했다. 그리고 resolveException()
에는 HttpServletRequest, HttpServletResponse, Object, Exception 이 파라미터로 사용되고 있기 때문에 Exception 에 대해서만 처리가 가능하다. 결과적으로 이를 처리하기 위해서 예외 핸들러 자체를 작업하고 서비스 전반에 걸쳐 이를 테스트하기에는 리소스가 너무 많이 필요하다.
결과
현재 서비스에서 과도한 리소스가 투입되는 작업을 할 여유가 부족하기 때문에 서비스 전반적인 테스트를 필요로 하는 작업을 할 수 없다.
그렇기 때문에 현재의 서비스 상태에서 Error 에 대한 로깅 처리를 전역으로 하는 작업을 할 수 없고 개발자가 직접 코드를 작성하며 이를 처리해야한다.
그렇기 때문에 현재 상황에서는 Throwable을 catch 하는 수밖에 없다.