에러, 예외처리

seokseungmin·2024년 10월 14일

Today I Learned

목록 보기
1/20

에러(Error)와 예외(Exception)의 차이

  • 에러(Error): 에러는 애플리케이션 코드에서 복구할 수 없는 심각한 문제를 나타냅니다. 예를 들어, JVM이 실행을 계속할 수 없을 정도의 메모리 부족 오류(OutOfMemoryError) 같은 시스템 수준의 문제입니다. 에러는 프로그램이 복구할 수 없는 상황을 나타내며, 일반적으로 개발자가 처리하지 않습니다.

    • 예시: StackOverflowError, OutOfMemoryError
  • 예외(Exception): 예외는 프로그램에서 발생할 수 있는 일반적인 오류 상황입니다. 예외는 개발자가 처리하고 복구할 수 있는 상황을 나타냅니다. 예외는 두 가지로 나뉩니다: 체크 예외(Checked Exception)언체크 예외(Unchecked Exception).


체크 예외(Checked Exception)

  • 설명: 체크 예외는 컴파일 타임에 강제로 처리해야 하는 예외입니다. 예외를 처리하지 않으면 컴파일되지 않으며, 반드시 try-catch로 처리하거나 메서드 시그니처에 throws를 명시하여 호출하는 쪽으로 예외를 던져야 합니다.
  • 예시: IOException, SQLException, FileNotFoundException 등이 있습니다. 이런 예외는 코드에서 예측 가능한 외부 리소스나 환경 문제에서 발생하며, 반드시 예외 처리가 필요합니다.

예시 코드 (체크 예외):

public void readFile(String path) throws IOException {
    FileInputStream file = new FileInputStream(path);  // FileNotFoundException 가능성 있음
    // 파일 처리 로직
}

언체크 예외(Unchecked Exception)

  • 설명: 언체크 예외는 런타임에 발생하는 예외로, 컴파일 시에 강제적으로 처리할 필요는 없습니다. 이러한 예외는 주로 프로그래밍 오류나 논리적 문제에 의해 발생하며, 개발자가 선택적으로 처리할 수 있습니다.
  • 예시: 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);
}

스프링 부트에서의 예외 처리

스프링 부트에서는 예외를 처리하기 위한 다양한 방법을 제공합니다. 체크 예외와 언체크 예외를 모두 다룰 수 있는 방식이 있으며, 공통된 예외 처리 로직을 쉽게 구현할 수 있습니다.

1. 전역 예외 처리 (@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과 같은 체크 예외도 동일하게 처리할 수 있습니다.

2. 커스텀 예외 처리

비즈니스 로직에서 자주 발생하는 특정 예외를 처리하기 위해 커스텀 예외를 정의하고 이를 처리할 수 있습니다.

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());
    }
}

3. 체크 예외와 언체크 예외 처리 전략

  • 체크 예외: 스프링에서는 체크 예외를 처리할 때 throws를 사용하여 호출하는 메서드 쪽에서 처리할 수 있게 던질 수 있습니다. 하지만 일반적으로 스프링 애플리케이션에서는 체크 예외를 많이 사용하지 않고 언체크 예외를 주로 사용합니다.

    체크 예외는 코드에서 예외를 처리하는데 복잡성을 증가시키기 때문에, 스프링에서는 런타임 예외로 전환해서 사용하는 경우가 많습니다.

  • 언체크 예외: 스프링 부트에서는 언체크 예외를 적극적으로 활용하여 전역 예외 처리기(@ControllerAdvice)를 통해 처리하는 방식이 주로 사용됩니다. 비즈니스 로직에서 발생하는 예외를 RuntimeException을 상속받은 커스텀 예외로 처리하는 것이 일반적입니다.


스프링 부트에서의 예외 처리 흐름 요약

  1. 언체크 예외는 코드에서 발생하면 @RestControllerAdvice를 통해 전역적으로 처리하거나, 개별적으로 try-catch로 처리할 수 있습니다.
  2. 체크 예외는 명시적으로 throws를 통해 상위로 던져서 처리해야 하며, 일반적으로 처리하기보다는 언체크 예외로 변환하여 사용하는 경우가 많습니다.
  3. 전역 예외 처리: @ExceptionHandler, @RestControllerAdvice를 활용해 중앙집중식 예외 처리 로직을 작성할 수 있습니다.
profile

0개의 댓글