에러핸들링 (1)

예외 처리/에러 핸들링 잘하기

안녕하세요, 오늘은 예외 처리(에러 핸들링)에 대해서 얘기를 해볼까 합니다.

책에 나오는 또는 인터넷 상에서 간략하게 설명하는 try-catch 예외처리에 대한 내용은 아니고 직접 개발을 진행하면서 경험한 내용을 토대로 이렇게 하면 좋겠다 싶은 내용들을 공유하는 차원에서 작성하는 글입니다. 혹여나 더 좋은 방법이나 공유해주시고 싶은 내용이 있다면 댓글도 환영합니다.

 

우선 자바 서적이나 구글링을 해서 찾는 에러 핸들링에 대한 내용들은 대부분 try-catch 문을 사용하면 된다에서 끝납니다.

하지만 단순히 그렇게 작업하면 에러 핸들링을 잘한다고 할 수 없습니다.

복잡한 비즈니스 로직을 구현하다보면 여러 클래스들을 넘나들면서 여러 메서드들을 거치게 됩니다.

비즈니스 로직의 메서드 콜 체인

위 메서드 콜 체인은 하나의 프로세스(기능)이 처리될 때의 과정의 일부입니다. 예를들면 controller -> service -> dao 뭐 이런 건데요, 아무리 복잡한 서비스라 하더라도 결국 요청에서부터 응답을 주기까지의 과정은 결국 위 그림처럼 한 줄로 연결이 가능하죠.

 

따라서 어느 시점에 try-catch 로 예외를 잡아야 할지 그리고 예외를 잡았다면 어떤 처리를 해야할지에 대해 많은 고민이 필요합니다. 하지만 실상 그런 고민을 별로 하지 않고 대충 에러로그 찍어놓는 개발자들이 많은 것이 사실이죠. 심지어 catch로 잡아서 로그만 남기고 다시 throw를 하기도 합니다. 무슨 폭탄돌리기 하는 것도 아니고 말이죠 -_-;; 최악입니다. 그렇게 개발된 서비스는 하나의 에러에 대해서 중복적으로 여러개의 로그를 남기는 것을 확인할 수 있고 디버깅도 비효율적으로 만들어 버립니다. 그럼 어떻게 하는 것이 좋은 것일까요?

 

첫 번째는 요청을 받아서 응답을 주기까지 하나의 체인에서 특정 예외에 대한 처리는 한 곳에서만 하도록 하는 것이 좋습니다. 즉, 위 체인 그림에서 메서드 1, 2, 3, 4 중 하나의 메서드에서만 A라는 예외에 대한 처리를 한다는거죠. 컨트롤러 부분에서 ExceptionHandler를 이용해서 처리할 수도 있고 서비스 레이어에서 try-catch 문을 이용해서 처리해도 됩니다. 메서드3에서 예외처리를 해놓았는데 불필요하게 메서드2에서 또 하고 있다거나 한다면 둘 중 하나를 제거하는게 유지보수하는데 큰 도움이 됩니다.

 

두 번째는 catch를 했으면 적절한 처리를 해줘야 한다는 겁니다. 여기서 "적절한" 이라는 말이 애매할 수 있는데요, 단순히 로그만 찍고 catch한 예외를 다시 throw 하고있다면 해당 try-catch문은 쓸모없는 것일 가능성이 99.9%입니다. 그런 경우라면 callee에서만 catch해서 로그를 남기고 적절한 처리를 하는게 더 깔끔합니다. 굳이 두 군데서 나누어 catch할 필요가 없다는 거죠. 또, 어떤 예외는 잡아서 로그만 남기고 무시할 수도 있고 (옵셔널 값이 없다거나 하는 경우), 어떤 예외는 디버깅용 로그를 남기고 비즈니스 로직을 롤백하는 처리를 해야할 수도 있습니다. 해당 프로세스를 진행함에 있어서 어떻게 처리해야 할 지는 API스펙 또는 정책에 따라 달라질 겁니다.

 

마지막으로, 예외가 발생했을 경우 디버깅용 로그를 남기기로 했다면 정말 필요한 정보만 가독성 있게 로그를 남기는 것입니다. 한 줄의 로그만 잘 남겨도 디버깅하기 쉽도록 작성하면 유지보수 효율성 뿐만 아니라 로깅 시스템에 부하도 줄일 수 있게 됩니다.

 

제 경험을 토대로 신입 또는 주니어 개발자 분들께서 이렇게 해보시면 좋겠다는 생각으로 끄적여 보았습니다.

 

혹시 이 글을 읽으시다가 멋진 노하우가 있으신 분들은 댓글로 공유 부탁드려요 ^-^