Spring

예외처리 - Exception Handle

chadongmin 2023. 10. 28. 22:08

1.  예외처리를 해야하는 이유

스프링을 활용한 프로젝트를 할 때 가장 신경써야 하는 것 중에 하나가 바로 예외처리이다. 예외란 사용자의 잘못된 조작이나 개발자의 코딩 로직의 실수로 인해 발생하는 프로그램 오류를 뜻한다. 예외가 발생해서 프로그램이 종료되면 실제 상용화되어 운영중인 서비스라면 이는 엄청한 피해를 야기할 수도 있다. 적절한 예외처리를 통해서 어떠한 상황에서도 프로그램이 중단되는 일 없이 서비스 되도록 해야한다.

2. 예외를 처리해야 하는 상황

위의 코드를 보면 TripId를 통해 여행 Entity의 내용을 수정하는 서비스 로직이다. 파라미터로 TripId와 수정요청DTO를 받는다.

로직의 첫번째는 파라미터로 전달받은 수정요청DTO를 validation 한다.

그 이후에는 Spring Data JPA의 findById 메서드를 통해 해당 TripId로 여행이 DB에 존재하는지 확인하고 존재한다면 수정 로직이 계속 진행되고, 존재하지 않는다면 예외를 발생시킨다. 예외는 Runtime Exception을 상속받는 Custom 예외 클래스를 정의 했다. 

 

그러면 직접 정의한 NO_TRIP Exception이 발생했을 때 어떻게 예외를 처리할까?

 

 Exception Hanlder

위와 같이 ExceptionHandler 어노테이션을 붙이고 어떤 클래스의 예외를 처리할지를 명시하면 된다. 

특정 예외클래스의 예외가 ExcepitonHandler 어노테이션이 붙은 메서드를 통해 처리된다.

이 메서드는 보통 Controller에 작성한다.

하지만 한가지 단점이 있는데 서비스가 많아질수록 Controller가 많아지는 경우가 생기는데, 그럴 때 마다 Controller 소스코드에 Exception Handler 메서드를 정의하기에는 효율적이지 못하다.

글로벌한 예외처리가 필요하다.

Global Exception Handler

 

위와 같이 예외처리를 위한 클래스를 정의하고 클래스에 @ControllerAdvice를 붙이면 글로벌한 예외처리가 가능하다.

예외가 발생하면 @ControllerAdvice가 붙은 클래스에서 @Exception Handler가 붙은 메서드를 통해 예외가 처리된다. 

이 코드에는 REST API를 만드는 프로젝트이기 때문에 Json형식의 요청과 응답만 사용되어진다. 그래서 @RestControllerAdvice 어노테이션을 사용했다. 그리고 HTTP 응답의 상태코드와 Response Body를 제어할 수 있도록 하기 위해서 Exception Handler 메서드의 반환타입을 Response Entity로 하였다. 

 

그리고 각각 발생할 수 있는 예외를 클래스로 정의하였는데, 생각지 못한 예외가 발생할 수 있기 때문에, Exception.class를 Internal Server Error로 처리하는 메서드도 정의해야 한다. 그래야 예외가 절대 빠져나가지 못한다.

 

가장 중요한 것은 예외를 어떻게 처리해야 할 것인지도 중요하지만 어떠한 예외도 빠져나가지 못하도록 모든 구멍을 막는 것 또한 중요하다는 것을 느꼈다.