예외처리의 경우 try~catch~finally로 많이 처리하지만...
이 마저도 프로젝트 규모가 커지면 코드 중복에 리소스 낭비로 이어진다고 한다😭
항상 찾아볼 때마다 나오던 전역 예외처리에 대해서 정리해보려고 한다!
보통은 에러가 터지면 이와 같이 기록된다.
하지만, 프론트 입장에서는 어떤 에러가 명확히 발생했는지 모르게된다🤔
따라서 커스텀 예외처리를 통해 명확한 에러 상황을 전달하거나, 공통된 예외의 경우 메세지를 설정하여 전달할 수가 있다.
Spring은 전역적으로 ExceptionHandler를 적용할 수 있는 @ControllerAdvic와 @RestControllerAdvice를 제공한다고 한다.
따라서 핸들링 클래스를 만들어 어노테이션을 적용함으로 예외 처리를 위임할 수 있게 된다.
🤔그럼 Rest가 붙고 안 붙고 차이는 뭘까...??
일반적으로 @Controller와 @RestController의 차이라고 보면 된다.
@RestController에는 @Controller + @ResponseBody인 것처럼,
@RestControllerAdvice도 그 차이인 것이다!
응답을 Json 형태로 내려주기에 Restful API를 할 때는 @RestControllerAdvice를 사용하면 된다.
1. Controller에서 예외를 직접 처리하지 않아도 된다.
@ControllerAdvice나 @RestControllerAdvice가 선언된 클래스에서 예외를 캐치해 응답을 반환한다.2. 예외에 따라 다른 처리 로직을 적용할 수 있다.
@ExceptionHandler를 사용하여 예외에 대한 핸들러 메서드를 직접 정의할 수 있다.3. 공통적인 예외 처리 로직을 재사용할 수 있다.
@ControlerAdvice나 @RestControllerAdvice가 선언된 클래스는 모든 컨트롤러에 적용이 되므로, 어디서나 동일한 예외 처리를 진행할 수 있다.예를 들어, 404 Not_Found의 경우 어떤 정보를 찾지 못했는지 명확히 전달해주면 더 처리가 쉬울 수 있다.
학생인지, 선생님인지, 혹은 학생의 성적인지 구분을 해서 설정하기 위해 custom을 사용할 것이다.

위와 같이 원래의 상태와 내가 설정한 코드번호, 전달할 메세지로 구성할 수 있다. 이렇게 내가 원하는 예외들을 별도로 구성해주면 된다.

응답으로 전달할 내용을 DTO 형태로 꾸렸다.
설정한 code와 설정한 메세지, 그리고 현재 에러가 발생한 시간을 담고자 했다.
생성자의 경우 @ExceptionHandler를 처리하면서 필요한 형태에 맞춰 생성해두었다.

해당 객체가 이제 나만의 예외가 된다.
RuntimeException을 상속받고, 위에서 예외로 처리하고자 구성해 둔 ErrorCode를 가져온다.
(우리가 일반적으로 사용할 예외는 전부 Runtime에 발생하기 때문에 RuntimeException을 상속받았다!)
이후 생성자를 만들어 ErrorCode를 받을 경우 RuntimeException의 메세지는 직접 구성한 ErrorCode의 메세지로 설정해주고,
현재 필드의 errorCode에 파라미터 errorCode를 설정해준다!
마지막 핸들러를 생성해주면 된다!

기존에 흔히 발생하는 커스텀하지 않은 예외의 경우 ErrorResponseDTO로 만들어 둔 생성자를 이용해,
코드와 그에 맞는 메세지를 설정해주었다.

Custom Exception의 경우 해당 예외를 그대로 받아 적용할 수 있게 했다.
위에서 ErrorResponseDTO의 생성자를 2가지로 구성한 이유가 여기에 있다.
🚨그리고 가장 중요한 것은 클래스명 상단에 @RestControllerAdvice!!
이제 controller에서 예외가 발생하면 해당 기능이 작동하여 설정한 메세지가 전달되는 것이다.
그럼 Custom Exception은 어떻게 처리하느냐!?!?!
Restful API를 작업중이기도 하고, controller는 문 역할로만 쓰고 전부 service에서 처리해주려고 했다.

이와 같이 사용했다. 현재는 보안까지 들어가지 않고 비밀번호 일치여부만 간단히 확인하는 작업이기에 간단히 구성해보았다.
일단 로그인 객체(ParentLoginDTO)를 받아와서 해당 아이디와 일치하는 객체가 DB에 있는지 확인해보았다.
해당 객체가 없으면 404에 해당하는 not_found를 전달하고자 ErrorCode에서 설정한 TEACHER_NOT_FOUND를 가져왔다.
👉 출력 결과

객체가 있다면, 비밀번호 일치여부를 확인했다.
일치하지 않는 경우, 권한이 없는 것이기에 401에 해당하며 "비밀번호 불일치"로 메세지를 설정한 INVALID_PASSWORD를 가져와 사용했다.
👉 출력 결과

커스텀 예외를 이렇다 치고.. 그럼 아까 같이 설정한 일반적인 다른 예외의 경우는??
👉 출력 결과

이와 같이 설정한 코드 번호와 문구가 출력되게 된다!
이와 같이 예외를 전역으로 두고 공통적으로 사용함으로
코드도 줄이고 원하는 내용을 전달하여 작업을 진행할 수 있다!