Bank App 만들기 - Exception Handler 처리(HTTP 상태 코드?)
학습 목표
1. @ControllerAdvice, @RestControllerAdvice 는 뭘까?
2. @ControllerAdivce 와 @RestControllerAdivce 에 차이점을 이해 하자.
3. 사용자 정의 예외 클래스를 만들기
4. @ControllerAdvice 구현해 보기
5. 에러 페이지 코드 수정 (errorPage.jsp)
6. 직업 예외 발생해보기
1. @ControllerAdvice, @RestControllerAdvice 는 뭘까?
HTTP 통신을 통해 예외 상황을 클라이언트에게 알려주는 방법은 여러 가지가 있으며, 이들을 적절히 사용하는 것이 중요합니다.
@ControllerAdvice와 @RestControllerAdvice는 Spring Framework에서 제공하는 어노테이션들로, 애플리케이션 전역에 걸쳐 발생하는 예외를 효과적으로 관리하고 처리하는 데 사용됩니다. 이들은 일종의 "예외 처리의 중앙 집중화"를 가능하게 해주며, 애플리케이션 내 여러 컨트롤러나 서비스에서 공통적으로 발생할 수 있는 예외를 한 곳에서 관리할 수 있게 해줍니다.
2. @ControllerAdivce 와 @RestControllerAdivce 에 차이점을 이해 하자.
@ControllerAdvice와 @RestControllerAdvice 차이점
- @ControllerAdvice: 이 어노테이션은 주로 @Controller 또는 @RequestMapping 어노테이션이 적용된 클래스(즉, MVC 컨트롤러)에서 발생하는 예외를 처리하기 위해 사용됩니다. HTML 뷰를 반환하는 전통적인 웹 애플리케이션에서 주로 사용됩니다.
- @RestControllerAdvice: @ControllerAdvice와 유사한 기능을 제공하지만, @RestController에서 발생하는 예외를 처리하는 데 특화되어 있습니다. 즉, RESTful 웹 서비스에서 JSON이나 XML 같은 응답을 반환할 때 사용됩니다. 사실상, @RestControllerAdvice는 @ControllerAdvice에 @ResponseBody를 추가한 것과 동일한 효과를 제공하여, 응답 본문에 직접 데이터를 매핑할 수 있습니다.
@ControllerAdvice와 @RestControllerAdvice 차이점
- @ControllerAdvice: 이 어노테이션은 주로 @Controller 또는 @RequestMapping 어노테이션이 적용된 클래스(즉, MVC 컨트롤러)에서 발생하는 예외를 처리하기 위해 사용됩니다. HTML 뷰를 반환하는 전통적인 웹 애플리케이션에서 주로 사용됩니다.
- @RestControllerAdvice: @ControllerAdvice와 유사한 기능을 제공하지만, @RestController에서 발생하는 예외를 처리하는 데 특화되어 있습니다. 즉, RESTful 웹 서비스에서 JSON이나 XML 같은 응답을 반환할 때 사용됩니다. 사실상, @RestControllerAdvice는 @ControllerAdvice에 @ResponseBody를 추가한 것과 동일한 효과를 제공하여, 응답 본문에 직접 데이터를 매핑할 수 있습니다.
예시 코드 확인 - 1
ControllerAdvice 에서 데이터를 반환하는 예시 코드
GlobalControllerAdvice.java
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = ResourceNotFoundException.class)
@ResponseBody
public ResponseEntity<Object> handleResourceNotFoundException(ResourceNotFoundException ex) {
// 에러 메시지와 함께 404 상태 코드를 반환
return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND);
}
}
예시 코드 확인 - 2
RestControllerAdvice 에서 반환
GlobalControllerAdvice.java
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = ResourceNotFoundException.class)
// @ResponseBody 사용 안해도 됨(데이터를 반환 처리 함)
public ResponseEntity<Object> handleResourceNotFoundException(ResourceNotFoundException ex) {
// 에러 메시지와 함께 404 상태 코드를 반환
return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND);
}
}
3. 사용자 정의 예외 클래스를 만들기
RuntimeException은 프로그램의 실행 도중 발생하는 예외를 나타냅니다.
컴파일 시 예외가 아닌 실행 시 예외로 분류되며, 따로 try-catch 블록으로 처리하지 않아도 컴파일러가 오류로 인식하지 않습니다. 예시로는 NullPointerException, ArrayIndexOutOfBoundsException, IllegalArgumentException 등이 있습니다.
여기서는 RuntimeException 확장해서 사용자 정의 예외 클래스를 만들어 봅니다.
위 그림처럼 패키지와 자바 파일을 만들어 주세요 (handler/GlobalControllerAdivce.java 파일 생성)
- handler/GlobalControllerAdivce.java 파일 생성
- handler/exception 패키지 생성
- handler/exception/UnAuthorizedException 자바 파일 생성
: UnAuthorizedException 클래스는 인증이 안된 사용자가 인증이 필요하 서비스에 접근 요청을 할 때 예외를 발생 시킬 사용자 정의 예외 클래스를 설계 합니다.
test1controller.java
package com.tenco.bank.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.tenco.bank.repository.model.User;
// Controller -> String (뷰리졸버 동작 --> JSP 파일 찾아서 렌더링 처리 한다.)
// RestController --> 데이터를 반환 처리
@RestController // Controller + REST API
public class Test1Controller {
// localhost:8080/test1
@GetMapping("/test1")
public User test1() {
// Gson --> JSON 형식으로 반환 --> String 응답 처리
return User.builder().username("길동").password("asd123").build();
}
}
test1controller.java
package com.tenco.bank.controller;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.mysql.cj.exceptions.UnableToConnectException;
import com.tenco.bank.handler.exception.UnAuthorizedException;
import com.tenco.bank.repository.model.User;
// Controller -> String (뷰리졸버 동작 --> JSP 파일 찾아서 렌더링 처리 한다.)
// RestController --> 데이터를 반환 처리
@RestController // Controller + @ResponseBody
public class Test1Controller {
// localhost:8080/test1
@GetMapping("/test1")
public User test1() {
// Gson --> JSON 형식으로 반환 --> String 응답 처리
try {
int result = 10 / 0;
} catch (Exception e) {
throw new UnAuthorizedException("인증이 안된 사용자 입니다.", HttpStatus.UNAUTHORIZED);
}
return User.builder().username("길동").password("asd123").build();
}
}