Lab_01 : Spring에서의 예외 처리란 ?
예외 처리의 경우가 필요한 예시를 들면,
- 클라이언트 요청 데이터에 대한 유효성 검증에서 발생하는 에외
- 서비스 계층의 비즈니스 로직에서 던져지는 의도된 예외
- 웹 애플리케이션 실행 중에 발생하는 예외
위 세가지의 유형으로 실습을 진행하려고 한다.
Lab_02 : 예외처리 실습
@ExceptionHandler를 이용한 예외 처리

[그림1] MemberController 코드

[그림2] MemberService 코드

[그림3] MemberEntity 코드

[그림4] MemberPostDTO
실습에 필요한 코드들은 위와 같다.
Post 방식의 postMember 을 PostMan을 통해 진행하려고 할 때,
위 그림 처럼 응답을 보내려고 한다. 이때, 수신된 응답은 에러가 발생함을 알 수 있다.
이때 MemberPostDTO 의 @valid 에서 name,email이 유효성을 만족하지 못해 에러가 발생하게 되어 위 그림과 같은 응답을 수신하게 된다.
위와 같은 에러들을 예외처리를 하고자 하려면 @ExceptionHandler을 이용할 수 있다.
Controller에 아래의 코드를 추가한다. 
위 코드를 추가하고 난 후에 다시 Postman으로 응답을 보내면 수신되는 응답은 아래와 같다.

수신되는 응답의 형태는 그 전에 본 에러의 형태가 아님을 알 수 있다.
RequestBody의 유효성 검증에 실패했을 때 예외 처리 과정을 살펴보면
- 클라이언트 쪽에서 회원 등록을 위해 MemberController의 postMember() 핸들러 메서드에 요청을 전송한다.
- RequestBody에 유효하지 않은 요청 데이터가 포함되어 있어 유효성 검증에 실패하고, MethodArguemntNotValidException이 발생한다.
- MemberController에는 @ExceptionHandler 애너테이션이 추가된 예외 처리 메서드인 handlerException() 이 있기 때문에 유효성 검증 과정에서 내부적으로 던져진 MethodArgumentNotValidException을 handlerException() 메서드가 전달받는다.
- MethodArgumentNotValidException 객체에서 getBindingResult().getFieldErrors()를 통해 발생한 에러 정보를 확인
- 얻어진 에러 정보를 ResponseEntity를 통해 ReponseBody로 전달
@ExceptionHandler의 단점
@ExceptionHandler 애너테이션으로 에러 처리를 하게 되면 다음과 같은 문제점이 발생할 수 있다.
- 각각의 Controller 클래스에서 @ExceptionHandler 애너테이션을 사용하여 Request Body에 대한 유효성 검증 실패에 대한 에러 처리를 해야 되므로 각 Controller 클래스마다 코드 중복이 발생한다.
- Controller에서 처리해야 되는 예외가 유효성 검증 실패에 대한 예외만 있는 것이 아니기 때문에 하나의 Controller 클래스 내에서 @ExceptionHandler를 추가한 에러 처리 핸들러 메서드가 늘어난다.
@RestControllerAdvice를 이용한 예외처리
특정 클래스에 @RestControllerAdvice 애너테이션을 추가하면 여러 개의 Controller 클래스에서 @ExceptionHandler,@InitBinder 또는 @ModelAtrribute가 추가된 메서드를 공유해서 사용할 수 있다.
@RestControllerAdvice 애너테이션을 추가한 클래스를 이용하면 예외 처리를 공통화할 수 있다는 것이다.
- @InitBinder와 @ModelAtrribute 애너테이션은 JSP,Thymeleaf 같은 서버 사이드 렌더링 방식에서 주로 사용되는 방식이다.

[그림] @RestControllerAdvice 애너테이션의 이용 예시
- 애너테이션을 붙이면 Controller에서 발생하는 예외를 도맡아서 처리하게 된다.
해당 클래스의 내용에는 @ExceptionHandler에서 구현한 내용으로 채워 넣어 실행한다.
변경 후 응답을 수신해보면,
해당 에러에 대한 예외를 @RestControllerAdvice가 도맡아서 예외를 처리함으로써, 정상적으로 동작함을 알 수 있다.