[Java] Checked vs Unchecked Exception

슈퍼대디·2024년 12월 23일

CS면접대비

목록 보기
2/13

Java Exception의 이해 - Checked vs Unchecked Exception

목차

  1. Exception 계층구조
  2. Checked vs Unchecked Exception
  3. Exception 사용 가이드라인
  4. 실무에서의 Exception 처리 전략
  5. Spring에서의 Exception 처리
  6. 면접 예상 질문

1. Exception 계층구조

Java의 예외 계층구조는 다음과 같습니다:

Throwable
├── Error
│   ├── OutOfMemoryError
│   ├── StackOverflowError
│   └── ...
└── Exception
    ├── IOException (Checked)
    ├── SQLException (Checked)
    └── RuntimeException (Unchecked)
        ├── NullPointerException
        ├── IllegalArgumentException
        └── ...

주요 구성요소 설명

  • Throwable: 모든 예외의 최상위 클래스
  • Error: 시스템 레벨의 심각한 문제
  • Exception: 애플리케이션 레벨의 문제
  • RuntimeException: Unchecked Exception의 최상위 클래스

2. Checked vs Unchecked Exception

Checked Exception

  • 컴파일 시점에 처리 여부를 확인
  • 반드시 try-catch로 처리하거나 throws로 선언해야 함
  • 주로 복구 가능한 예외에 사용
  • 대표적인 예: IOException, SQLException
public class CheckedExceptionExample {
    public void readFile(String path) throws IOException {
        Files.readAllLines(Paths.get(path)); // IOException 발생 가능
    }
    
    public void handleFile(String path) {
        try {
            readFile(path);
        } catch (IOException e) {
            // 복구 가능한 예외 처리
            logger.error("파일 읽기 실패", e);
            // 대체 로직 수행
        }
    }
}

Unchecked Exception

  • 컴파일 시점에 처리 여부를 확인하지 않음
  • 명시적인 예외 처리가 필요 없음
  • 주로 프로그래밍 오류나 예측할 수 없는 예외에 사용
  • RuntimeException과 그 하위 클래스들
public class UnCheckedExceptionExample {
    public void divide(int a, int b) {
        if (b == 0) {
            throw new IllegalArgumentException("0으로 나눌 수 없습니다.");
        }
        return a / b;
    }
    
    // throws 선언이 필요없음
    public void processNumber(int num) {
        if (num < 0) {
            throw new IllegalArgumentException("음수는 처리할 수 없습니다.");
        }
    }
}

주요 차이점 정리

특징Checked ExceptionUnchecked Exception
처리 여부컴파일러가 체크컴파일러가 체크하지 않음
처리 방법try-catch 또는 throws 필수선택적 처리
트랜잭션 처리롤백되지 않음롤백됨
사용 시점비즈니스 로직상 예외 상황프로그래밍 오류

3. Exception 사용 가이드라인

Checked Exception 사용 시기

  • 호출자가 예외 상황을 복구할 수 있는 경우
  • 외부 시스템과의 통신에서 발생하는 예외
  • 비즈니스 로직에서 중요한 예외 상황
public class BusinessService {
    public void processOrder(Order order) throws InsufficientStockException {
        if (order.getQuantity() > stockRepository.getAvailableStock()) {
            throw new InsufficientStockException("재고가 부족합니다.");
        }
        // 주문 처리 로직
    }
}

Unchecked Exception 사용 시기

  • 프로그래밍 오류를 나타내는 경우
  • 예외 복구가 불가능한 경우
  • 예외 처리가 비즈니스 로직을 복잡하게 만드는 경우
public class ValidationService {
    public void validateUser(User user) {
        if (user == null) {
            throw new IllegalArgumentException("사용자 정보가 null입니다.");
        }
        if (user.getName() == null || user.getName().isEmpty()) {
            throw new IllegalArgumentException("사용자 이름은 필수입니다.");
        }
    }
}

4. 실무에서의 Exception 처리 전략

계층별 Exception 처리

@Service
public class UserService {
    public User findUser(Long id) {
        try {
            return userRepository.findById(id);
        } catch (SQLException e) {
            // SQL 예외를 비즈니스 예외로 변환
            throw new UserNotFoundException("사용자를 찾을 수 없습니다.", e);
        }
    }
}

커스텀 Exception 설계

public class BusinessException extends RuntimeException {
    private final ErrorCode errorCode;
    
    public BusinessException(ErrorCode errorCode) {
        super(errorCode.getMessage());
        this.errorCode = errorCode;
    }
    
    public BusinessException(ErrorCode errorCode, Throwable cause) {
        super(errorCode.getMessage(), cause);
        this.errorCode = errorCode;
    }
    
    public ErrorCode getErrorCode() {
        return errorCode;
    }
}

5. Spring에서의 Exception 처리

@ExceptionHandler 활용

@RestControllerAdvice
public class GlobalExceptionHandler {
    
    @ExceptionHandler(BusinessException.class)
    public ResponseEntity<ErrorResponse> handleBusinessException(BusinessException e) {
        ErrorResponse response = ErrorResponse.of(e.getErrorCode());
        return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
    }
    
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> handleException(Exception e) {
        ErrorResponse response = ErrorResponse.of(ErrorCode.INTERNAL_SERVER_ERROR);
        return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

예외 처리 전략 예시

@Service
@Transactional
public class OrderService {
    public Order createOrder(OrderRequest request) {
        validateOrder(request); // Unchecked Exception
        
        try {
            // 외부 결제 시스템 호출
            paymentClient.processPayment(request.getPaymentInfo()); // Checked Exception
        } catch (PaymentException e) {
            throw new OrderException("주문 처리 중 결제 오류 발생", e);
        }
        
        return orderRepository.save(new Order(request));
    }
    
    private void validateOrder(OrderRequest request) {
        if (request == null) {
            throw new IllegalArgumentException("주문 정보가 없습니다.");
        }
        // 기타 검증 로직
    }
}

6. 면접 예상 질문

Q: Checked Exception과 Unchecked Exception의 차이점을 설명해주세요.
A: Checked Exception과 Unchecked Exception의 주요 차이점:

  1. 컴파일 시점 처리 여부

    • Checked Exception: 컴파일러가 예외 처리를 강제 (try-catch 또는 throws 필수)
    • Unchecked Exception: 컴파일러가 예외 처리를 강제하지 않음
  2. 사용 목적

    • Checked Exception: 복구 가능한 비즈니스 예외 상황
    • Unchecked Exception: 프로그래밍 오류나 예측 불가능한 예외
  3. 트랜잭션 처리

    • Checked Exception: 트랜잭션이 롤백되지 않음
    • Unchecked Exception: 트랜잭션이 롤백됨

Q: Exception 처리 시 Runtime Exception을 사용하는 것이 좋을까요, Checked Exception을 사용하는 것이 좋을까요?
A: 각 Exception 유형의 적절한 사용 상황:

  1. Runtime Exception 사용이 적절한 경우

    • 프로그래밍 오류 발생 시
    • 예외 복구가 불가능한 경우
    • 비즈니스 로직의 명확성이 중요한 경우
  2. Checked Exception 사용이 적절한 경우

    • 호출자의 예외 복구가 필요한 경우
    • 외부 시스템 연동 시
    • 명시적인 예외 처리가 필요한 비즈니스 로직

Q: 커스텀 예외를 만들 때 고려해야 할 점은 무엇인가요?
A: 커스텀 예외 설계 시 고려사항:

  1. 계층 구조

    • 적절한 상위 예외 클래스 선택
    • 예외의 성격에 따른 계층화
  2. 명명 규칙

    • 구체적이고 명확한 클래스명 사용
    • Exception 접미사 포함
  3. 정보 제공

    • 에러 코드 정의
    • 상세 메시지 포함
    • 추가적인 컨텍스트 정보 제공
  4. 구현 세부사항

    • cause 전달을 위한 생성자 구현
    • 직렬화 고려
    • 불변 객체로 구현

참고 자료

profile
성장하고싶은 Backend 개발자

0개의 댓글