Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- Swagger
- 백엔드
- 개발자
- 엔티티 설계
- ORM
- auditing
- 인텔리제이
- 스프링 부트 핵심 가이드
- 백엔드스쿨
- 제로베이스 #백엔드 #Java #Spring #개발자 #백엔드공부 #백엔드 스쿨
- spring
- JPA
- 제로베이스
- DAO 설계
- 프로젝트 생성
- 유효성검사
- DAO 연동 컨트롤러 서비스 설계
- 데이터베이스 연동
- validated
- Java
- #devops #terraform #state
- 백엔드공부
- MariaDB
- 스프링부트실전가이드
- 리포지토리 인터페이스
Archives
- Today
- Total
JeongJin's Blog
10. 유효성 검사와 예외처리(3) 본문
10.4 예외처리
10.4.1 예외 처리
- 프로그래밍에서 예외(exception)란 입력 값의 처리가 불가능하거나 참조된 값이 잘못된 경우 등 애플리케이션이 정상적으로 동작하지 못하는 상황을 의미한다.
- 예외는 개발자가 직접 처리 할 수 있는 것이므로 미리 코드 설계를 통해 처리할 수 있다.
- 에러 vs 예외
- 에러는 주로 자바의 가상머신에서 발생시키는 것으로서 예외와 달리 애플리케이션 코드에서 처리할 수 있는 것이 거의 없다.
- 대표적인 예로 메모리 부족(OutOfMemory), 스택 오버플로우(StackOverFlow) 등이 있음
- 이러한 에러는 발생 시점에 처리하는 것이 아니라 미리 애플리케이션의 코드를 살펴보면서 문제가 발생하지 않도록 예방해서 원천적으로 차단해야 한다.
10.4.2 예외 클래스
- 모든 예외는 Throwable 클래스를 상속받습니다. 그리고 가장 익숙하게 볼 수 있는 Exception 클래스는 다양한 자식 클래스를 가지고 있습니다. 해당 클래스는 크게 Checked Exception과 Unchecked Exception으로 구분할 수 있다.
- Checked Exception은 컴파일 단계에서 확인 가능한 예외 상황으로 IDE에서 캐치해서 반드시 예외 처리를 할 수 있게 표시해준다.
- Unchecked Exception은 런타임 단계에서 확인되는 예외 상황을 나타냅니다. 문법상 문제는 없지만 프로그램이 동작하는 도중 예기치 않은 상황이 생겨 발생하는 예외를 의미한다.
10.4.3 예외 처리 방법
예외가 발생했을 때 처리하는 방법은 크게 세 가지가 존재한다.
- 예외 복구
- 예외 상황을 파악해서 문제를 해결하는 방식
- 대표적인 방법 try/catch 구문
- 예외 처리 회피
- 예외가 발생한 시점에서 바로 처리하는 것이 아니라 예외가 발생한 메서드를 호출한 곳에서 예외 처리를 할 수 있게 전가하는 방식
- throw 키워드를 사용해 어떤 예외가 발생했는지 호출부에서 내용을 전달 할 수 있다.
int a = 1;
String b = "a";
try {
System.out.println(a + Integer.parseInt(b));
} catch (NumberFormatException e) {
throw new NumberFormatException("숫자가 아닙니다");
}
- 예외 전환
- 앞의 두 방식을 적절하게 섞은 방식
10.4.4 스프링 부트의 예외 처리 방식
- 예외가 발생했을 때 클라이언트에 오류 메세지를 전달할려면 각 레이어에서 발생한 예외를 엔드포인트 레벨인 컨트롤러로 전달해야 한다. 이렇게 전달받은 예외를 스프링 부트에서 처리하는 방식으로 크게 두 가지가 있다.
- @(Rest)ControllerAdvice 와 @ExceptionHandler를 통해 모든 컨트롤러의 예외를 처리
- @ControllerAdvice 대신 @RestControllerAdvice 를 사용하면 결과값을 JSON 형태로 반환할 수 있다.
- @ExceptionHandler를 통해 특정 컨트롤러의 예외를 처리
- @(Rest)ControllerAdvice 와 @ExceptionHandler를 통해 모든 컨트롤러의 예외를 처리
@RestControllerAdvice
public class GlobalException {
@ExceptionHandler(value = RuntimeException.class)
public ResponseEntity<Map<String, String>> handlerException(RuntimeException e,
HttpServletRequest request) {
HttpHeaders responseHeaders = new HttpHeaders();
...
}
}
- @(Rest)ControllerAdvice 는 스프링에서 제공하는 어노테이션으로 @(Rest)Controller 에서 발생하는 예외를 한 곳에서 관리하고 처리할 수 있게 하는 기능을 수행한다.
- Service 소스에서 throw new 호출해도 Controlle에서는 null로 출력므로 해당 어노테이션을 사용한다.
- @ExceptionHandler는 @(Rest)Controller 가 적용된 Bean 에서 발생하는 예외를 잡아 처리하는 메서드를 정의할 때 사용
- 어떤 예외 클래스를 처리할지는 value 속성으로 등록한다.
- value 속성은 배열의 형식으로도 전달받을 수 있어 예러 예외 클래스를 등록할 수 있다.
- 해당 설정을 통해 예외를 관제하는 범위를 지정할 수 있다.
- basePackages 에 정의된 package만 예외를 관제한다.
@RestControllerAdvice(basePackages="com.springboot.valid_exception")
10.4.5 커스텀 예외
- 표준 예외에서 제공하는 클래스는 해당 예외 타입의 이름만으로 이해하기 어려운 경우가 있으므로, 표준 예외를 사용할 때는 예외 메세지를 상세히 작성해야 하는 번거로움이 있다.
- 애플리케이션에서 발생하는 예외를 개발자가 직접 관리하기가 수월하다.
10.4.6 커스텀 예외 클래스 생성하기
- 커스텀 예외는 예외가 발생하는 상황에 해당하는 상위 예외 클래스를 상속받는다. 그래서 커스텀 예외는 상위 예외 클래스보다 좀 더 구체적인 이름을 사용하기도 한다.
// AccountException.java
public class AccountException extends RuntimeException {
private final ErrorCode errorCode;
private final String errorMessage;
public AccountException(ErrorCode errorCode) {
this.errorCode = errorCode;
this.errorMessage = errorCode.getDescription();
}
}
// ErrorCode.java
@Getter
@AllArgsConstructor
public enum ErrorCode {
INVALID_SERVER_ERROR("내부 서버 오류가 발생하였습니다."),
INVALID_REQUEST("잘못된 요청입니다."),
USER_NOT_FOUND("사용자가 없습니다."),
ACCOUNT_NOT_FOUND("계좌가 없습니다."),
ACCOUNT_TRANSACTION_LOCK("해당 계좌는 사용 중입니다."),
TRANSACTION_NOT_FOUND("해당 거래가 없습니다."),
AMOUNT_EXCEED_BALANCE("거래 금액이 계좌 잔액보다 큽니다."),
TRANSACTION_ACCOUNT_UN_MATCH("이 거래는 해당 계좌에서 발생한 거래가 아닙니다."),
CANCEL_MUST_FULLY("부분 취소는 허용되지 않습니다."),
TOO_OLD_ORDER_TO_CANCEL("1년이 지난 거래는 취소가 불가능합니다."),
USER_ACCOUNT_UNMATCH("사용자와 계좌의 소유주가 다릅니다."),
ACCOUNT_ALREADY_UNREGISTERED("계좌가 이미 해지되었습니다."),
BALANCE_NOT_EMPTY("잔액이 있는 계좌는 해지할 수 없습니다."),
MAX_COUNT_PER_USER_10("사용자 최대 계좌는 10개입니다.")
;
private String description;
}
// 응답 메세지
{
"errorCode": "ACCOUNT_NOT_FOUND",
"errorMessage": "계좌가 없습니다."
}
'Book Study > 스프링 부트 핵심 가이드' 카테고리의 다른 글
12. 서버 간 통신 (1) (0) | 2023.12.04 |
---|---|
11. 액추에이터 활용하기 (0) | 2023.12.04 |
10. 유효성 검사와 예외 처리 (2) (2) | 2023.11.21 |
10. 유효성 검사와 예외 처리 (1) (0) | 2023.11.20 |
09. 연관관계 매핑 (0) | 2023.11.15 |