예외처리에 대한 고찰 - 1편
수 많은 우문은 현답을 만든다
개발자에게 예외처리란 경험의 영역입니다.
서비스를 개발하고 유지보수를 하면서 각종 버그와 마주치게 되는데요,
디버깅을 하면서 가장 와닿는 기술이 바로 예외처리입니다.
서비스의 비즈니스 로직 구현에만 신경쓰다보면 예외처리에는 신경쓰지 못하는 경우가 많은데요
예외처리를 위해 필요한 체크리스트 몇가지를 적어보려고 합니다.
로깅에 예외발생에 대한 정보를 포함시켰는가?
예외가 어떠한 원인으로 발생했는지에 대한 정보가 필요합니다.
보통 예외 처리의 경우 try catch에서 catch에 로그나 e.printStackTrace()를 통해 발생한 exception을 나열하고 끝내는 경우가 많습니다.
하지만 해당 예외를 해결하기 위해서는 원인을 파악해야 하고,
원인을 제대로 파악하기 위해서는 문제 상황을 재현해야 합니다.
이때 재현에 필요한 정보들을 예외처리 내의 로깅에 포함시켜야 합니다.
어떤 유저의, 어떤 정보를, 어떻게 처리할때 발생하였는가?
필요없다고 생각되는 데이터들을 로그에 포함시키지 않는게 좋다고 생각할수 있지만
서비스는 릴리즈 되었다고 개발이 끝난것이 아닙니다.
지속적인 관리가 필요하고 고도화를 통한 개발이 계속되기 때문에 유지보수에 필요한 데이터들을 모두 포함해야합니다.
로깅은 단순히 어떤 예외가 발생했는지를 확인하는 용도가 아니라 예외를 확인하고 재발 방지 처리를 위해 필요한 작업을 동반합니다.
테스트를 통해 충분히 예외에 대해 검토하였는가?
최근에는 TDD 등의 트랜드로 단위테스트를 진행하는 경우가 많아졌습니다.
비즈니스 로직뿐 아니라 예외처리에도 테스트가 필수적이며, 가능한 예외상황에 대해 충분히 검토하고 처리하는 습관이 필요합니다.
테스트를 통해 예외에 대한 커버리지를 높일수록 시스템은 견고해집니다.
또한 해당 시스템을 만든 개발자 자신에게도 예외에 대한 경험이 쌓이게 되어 전문성있는 개발자로 성장하게 됩니다.
발생 가능한 예외를 어떻게 처리할 것인가?
예외는 크게 3가지 방법으로 처리합니다.
예외 복구, 예외처리 회피, 예외전환.
예외복구는 예외가 발생했을때, 정상적인 흐름으로 서비스가 진행되도록 예외를 발생시키는 것 입니다.
예를 들어 통신환경이 좋지않아 로그인이 되지 않을경우 정해진 만큼 retry를 하고, 정해진 이상으로 로그인이 되지 않을 경우 임의의 exception을 throw 하여 처리하는 것입니다.
예외처리 회피는 메서드에서 예외가 발생하였을때, 호출 부로 예외를 떠넘기는 것 입니다.
예측 가능한 예외의 경우 if 문 등을 통해 예외상황을 처리할수 있는데요,
이런 예외처리가 많아질수록 코드가 복잡해질수 있습니다.
따라서 예외를 별도로 처리하지 않고 throw 함으로써 코드의 간결성을 지킬수 있습니다.
하지만 예외를 던지는 것이 최선이 방법이라는 확신이 있을 때만 사용해야 합니다.
예외전환은 발생한 예외에 대한 처리로서 다른 예외를 발생시키는 것을 말합니다.
예를 들어 , 숫자만이 필요한 패스워드를 입력받는 로직에서 입력값에 문자가 들어있어 NumberFormatException 이 발생하면 try - catch 문의 catch 문에서,
임의로 만든 PasswordShouldOnlyNumberException으로 throw new PasswordShouldOnlyNumberException()을 실행합니다.
이렇게 사용자 정의 exception으로 예외를 전환하면 로그 확인시에 NumberFormatException 보다 직관적으로 예외 상황을 확인할수 있게 됩니다.
가독성에 대한 고찰
예외를 처리하는데에는 try catch문을 이용한 방법과 throw 를 이용한 방법이 있습니다.
try-catch 문의 경우.
예외처리를 학습할때 가장 흔하게 학습하는 방법입니다.
try 문 안에 실행될 메소드를 넣고 try 문 내에서 발생할수 있는 예외를 catch 문 내에서 처리하는 방법입니다.
이 경우는 코드를 보게 되었을 때 메서드 내의 예외처리에 대한 부분을 한눈에 파악할수 있는 장점이 있지만
코드 블럭이 길기 때문에 전체적인 코드의 줄이 늘어지며 메서드 하나하나 try catch 문을 사용할 경우 가독성이 떨어질수 있습니다.
throw 의 경우.
메서드 실행시 throw new exception을 통해 예외를 처리하는 방법입니다.
사실 throw로 예외를 던지는 것은 try-catch 문이 없다면 아무의미가 없습니다.
예외는 checked exception(컴파일에서 걸러지는 예외)와 unchecked exception(runtime exception을 상속받고, 컴파일 단계에서 걸러지지 않은 예외)로 나뉩니다.
throw는 checked exception 일 경우 컴파일 단계에서 걸러지는 강제적인 예외이기 때문에 try-catch, throw 둘다 적절한 예외처리 방법입니다.
unchecked exception의 경우 throw로 처리한 예외는 try-catch문이 없을 경우 별도의 처리가 되지 않고 jvm 기본 exception이 발생하게됩니다.
따라서 unchecked exception의 경우 throw를 사용할때는 try - catch 문을 필수적으로 사용해야 예외처리의 의미가 생깁니다.
spring 어노테이션을 이용한 예외처리 방법.
별도의 exception handler를 구현하여 사용하는 방법이 있습니다.
spring의 경우 @ControllerAdvise, @ExceptionHandler 어노테이션을 통해 @Controller 어노테이션이 적용된 bean의 예외를 일괄적으로 처리할수 있습니다.
해당 어노테이션을 이용하여 컨트롤러 전역적으로 예외를 처리할수있는 핸들러를 구현하면
try catch 문의 반복으로 가독성이 떨어지는 일을 막을수 있습니다.
예시 : aidenshin 님 - [Spring]컨트롤러 예외처리를 자동으로
https://velog.io/@aidenshin/Spring-Boot-Exception-Controller
참고 링크:
조영호님 - 예외처리에 대한 고찰 1
https://dodghek.tistory.com/27
넥스트리 - 예외처리에 대한 작은 생각
https://www.nextree.co.kr/p3239/
중중모리님 - 예외처리(Exception)에 대한 고찰
https://morit.tistory.com/10
wookim 님 -예외처리 고찰
https://wookim789.tistory.com/21
임도형님 -예외처리 처리 가이드
https://www.slideshare.net/dhrim/ss-2804901
스윗동현님 -예외의 회피
https://dololak.tistory.com/58
사바라다님 - exception 처리하기 - throws에 관하여
https://sabarada.tistory.com/77
aidenshin 님 - [Spring]컨트롤러 예외처리를 자동으로
https://velog.io/@aidenshin/Spring-Boot-Exception-Controller
다음 내용이 궁금하다면?
이미 회원이신가요?
2023년 11월 30일 오전 2:02
집
... 더 보기금
... 더 보기A회사는 일에 비해 근로자의 수가 적었다. 매일 2시간 이상 야근이다. 회사는 신규 인력을 채용하기 보다는 야근 수당을 주는 것이 더 효율적이라고 생각했다. 회사는 야근 수당을 지급하면서 다른 한편으로는 사무 자동화 추진과 일하는 방식의 개선을 교육하였다.
... 더 보기🔹앞서 나가는 비결은 시작하는 것이다.
... 더 보기