예외처리
프로그래밍에서 예외처리는 매우 중요하다.
사실 우테코에 들어오기 전에는 예외처리와 관련된 코드를 매우 세세하게 짜는 편은 아니었다. 그냥 돌아가면 되는 거지! 정도의 코드였다. 다만, 상세하고 다양한 예외를 갖출 수 있게 된다면 더 안정적인 프로그램이 만들어질 수 있다.
그렇지만 try-catch나 if문으로 예외를 잡거나 상위메서드로 예외처리를 위임하는 등의 작업을 진행하더라도 코드는 쉽게 복잡해질 수 있고, 이는 비즈니스 로직보다 예외처리를 위한 코드에 더 힘쓰게 되는 결과를 초래한다.
나 역시 해당 부분에 있어서 잘 모르는 부분이 존재했고, 또한 기존 Spark 구현 코드를 Spring으로 이식하는 과정에서 예외처리와 관련된 문제들을 해결하기 위해 @ExceptionHandler와 @ControllerAdvice라는 키워드를 조언받았기에, 이에 대해서 간단하게 정리해보고자 한다.
@ExceptionHandler
@ExceptionHandler의 경우는 @Controller, @RestController가 적용된 Bean 내에서 발생하는 예외를 잡아 하나의 메서드에서 처리하는 기능을 제공한다.
@RestController
public class RestController {
//......
// 하나만 지정할 경우
@ExceptionHandler(NullPointerException.class)
public ResponseEntity<String> myException(Exception e) {
//...
}
// 여러개 지정도 OK
@ExceptionHandler({FileSytemException.class, RemoteException.class})
public ResponseEntity<String> myException2(Exception e) {
//...
}
}
주의사항/알아 둘 것
- Controller, RestController에만 적용 가능하다. (@Service 같은 빈에서는 적용되지 않는다.)
- 리턴 타입은 자유롭게 해도 된다. (Controller내부에 있는 메서드들은 여러 타입의 response를 할 것이다. 해당 타입과 전혀 다른 리턴 타입이어도 상관없다.) 공식문서에 나와있는 반환 값 링크
- 메서드의 파라미터로 Exception을 받아왔는데 이것 또한 자유롭게 받아와도 된다. 공식문서의 메서드 인수 링크
- @ExceptionHandler를 등록한 Controller에만 적용된다. 다른 Controller에서 NullPointerException이 발생하더라도 예외를 처리할 수 없다.
여기서 마지막 사항을 눈여겨보자. @ExceptionHandler만 존재할 경우, 해당 Controller에서만 적용된다는 단점이 존재한다. 즉, 비슷한 에러를 처리하기 위한 비슷한 코드가 중복으로 구성될 수 있다는 것이다. 이를 해결할 수 있는 방법이 바로 @ControllerAdvice다.
@ControllerAdvice와 @RestControllerAdvice
Spring은 앞서 말한 @ExceptionHandler의 한계를 극복하는 일환으로 전역적으로 예외를 처리하는 @ControllerAdvice와 @RestControllerAdvice를 각각 Spring3.2, Spring4.3부터 제공하고 있다.
각각의 차이는 앞에 Rest가 붙었다는 점에서 눈치챌 수 있듯, @Controller와 @RestController의 차이와 유사하다. (관련 글 - [Spring] @Controller와 @RestController)
즉, @RestControllerAdvice는 @ResponseBody가 붙어있는 형식으로, 응답 형식이 Json이라고 보면 된다.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ControllerAdvice
@ResponseBody // 틀린그림찾기처럼 쳐다보다보면 이부분이 추가된 것을 볼 수 있다.
public @interface RestControllerAdvice { ...
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ControllerAdvice { ...
}
ControllerAdvice는 여러 컨트롤러에 대해 전역적으로 ExceptionHandler를 동일하게 적용해준다.
ControllerAdvice의 장점
- 하나의 클래스로 모든 컨트롤러에 대해 전역적으로 예외 처리가 가능함
- 직접 정의한 에러 응답을 일관성 있게 클라이언트에게 내려줄 수 있음
- 별도의 try-catch문이 없어 코드의 가독성이 높아짐
ControllerAdvice의 주의점
- 한 프로젝트당 하나의 ControllerAdvice만 관리하는 것이 좋다.
- 만약 여러 ControllerAdvice가 필요하다면 basePackages나 annotations 등을 지정해야 한다.
- 직접 구현한 Exception 클래스들은 한 공간에서 관리한다.
참고자료
https://tecoble.techcourse.co.kr/post/2021-05-10-controller_advice_exception_handler/
'프로그래밍 공부 > Spring' 카테고리의 다른 글
[Spring] Controller에서 데이터 받기 (0) | 2022.04.28 |
---|---|
[Spring] Java Bean vs Spring Bean (1) | 2022.04.26 |
[Spring] DI(Dependency Injection, 의존성 주입)이란? (0) | 2022.04.25 |
[Spring] @Controller와 @RestController (0) | 2022.04.22 |
[Spring] @RequestMapping (8) | 2022.04.20 |