에러(Error): 에러는 애플리케이션 코드에서 복구할 수 없는 심각한 문제를 나타냅니다. 예를 들어, JVM이 실행을 계속할 수 없을 정도의 메모리 부족 오류(OutOfMemoryError) 같은 시스템 수준의 문제입니다. 에러는 프로그램이 복구할 수 없는 상황을 나타내며, 일반적으로 개발자가 처리하지 않습니다.
StackOverflowError, OutOfMemoryError예외(Exception): 예외는 프로그램에서 발생할 수 있는 일반적인 오류 상황입니다. 예외는 개발자가 처리하고 복구할 수 있는 상황을 나타냅니다. 예외는 두 가지로 나뉩니다: 체크 예외(Checked Exception)와 언체크 예외(Unchecked Exception).
try-catch로 처리하거나 메서드 시그니처에 throws를 명시하여 호출하는 쪽으로 예외를 던져야 합니다.IOException, SQLException, FileNotFoundException 등이 있습니다. 이런 예외는 코드에서 예측 가능한 외부 리소스나 환경 문제에서 발생하며, 반드시 예외 처리가 필요합니다.예시 코드 (체크 예외):
public void readFile(String path) throws IOException {
FileInputStream file = new FileInputStream(path); // FileNotFoundException 가능성 있음
// 파일 처리 로직
}
NullPointerException, IllegalArgumentException, ArrayIndexOutOfBoundsException 등 런타임에서 발생하는 예외들이 여기에 속합니다.예시 코드 (언체크 예외):
public void divide(int a, int b) {
if (b == 0) {
throw new IllegalArgumentException("Division by zero is not allowed.");
}
System.out.println(a / b);
}
스프링 부트에서는 예외를 처리하기 위한 다양한 방법을 제공합니다. 체크 예외와 언체크 예외를 모두 다룰 수 있는 방식이 있으며, 공통된 예외 처리 로직을 쉽게 구현할 수 있습니다.
@RestControllerAdvice)스프링 부트에서는 전역 예외 처리를 위해 @ControllerAdvice나 @RestControllerAdvice 애너테이션을 사용합니다. 이를 통해 모든 컨트롤러에서 발생하는 예외를 한 곳에서 처리할 수 있습니다. 주로 언체크 예외에 대해 많이 사용되지만, 체크 예외도 처리할 수 있습니다.
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<?> handleIllegalArgumentException(IllegalArgumentException ex) {
// 언체크 예외 처리
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body("잘못된 요청입니다: " + ex.getMessage());
}
@ExceptionHandler(IOException.class)
public ResponseEntity<?> handleIOException(IOException ex) {
// 체크 예외 처리
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("입출력 오류가 발생했습니다.");
}
@ExceptionHandler(Exception.class)
public ResponseEntity<?> handleGeneralException(Exception ex) {
// 그 외 모든 예외 처리
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("서버에서 오류가 발생했습니다.");
}
}
IllegalArgumentException과 같은 런타임 예외는 @ExceptionHandler로 처리하여 적절한 응답을 반환할 수 있습니다.IOException과 같은 체크 예외도 동일하게 처리할 수 있습니다.비즈니스 로직에서 자주 발생하는 특정 예외를 처리하기 위해 커스텀 예외를 정의하고 이를 처리할 수 있습니다.
public class BizException extends RuntimeException {
private HttpStatus status;
public BizException(String message, HttpStatus status) {
super(message);
this.status = status;
}
public HttpStatus getStatus() {
return status;
}
}
@RestControllerAdvice
public class BizExceptionHandler {
@ExceptionHandler(BizException.class)
public ResponseEntity<?> handleBizException(BizException ex) {
return ResponseEntity.status(ex.getStatus())
.body(ex.getMessage());
}
}
체크 예외: 스프링에서는 체크 예외를 처리할 때 throws를 사용하여 호출하는 메서드 쪽에서 처리할 수 있게 던질 수 있습니다. 하지만 일반적으로 스프링 애플리케이션에서는 체크 예외를 많이 사용하지 않고 언체크 예외를 주로 사용합니다.
체크 예외는 코드에서 예외를 처리하는데 복잡성을 증가시키기 때문에, 스프링에서는 런타임 예외로 전환해서 사용하는 경우가 많습니다.
언체크 예외: 스프링 부트에서는 언체크 예외를 적극적으로 활용하여 전역 예외 처리기(@ControllerAdvice)를 통해 처리하는 방식이 주로 사용됩니다. 비즈니스 로직에서 발생하는 예외를 RuntimeException을 상속받은 커스텀 예외로 처리하는 것이 일반적입니다.
@RestControllerAdvice를 통해 전역적으로 처리하거나, 개별적으로 try-catch로 처리할 수 있습니다.throws를 통해 상위로 던져서 처리해야 하며, 일반적으로 처리하기보다는 언체크 예외로 변환하여 사용하는 경우가 많습니다.@ExceptionHandler, @RestControllerAdvice를 활용해 중앙집중식 예외 처리 로직을 작성할 수 있습니다.