반응형
목차
- 1. Java Exception의 기본 개념
- 2. Exception vs Error
- 3. Checked Exception vs Unchecked Exception
- 4. Exception 처리 전략
- 5. Best Practices
- 6. 실전 예제
- 7. 면접 대비 Q&A
1. Java Exception의 기본 개념
Java에서 예외는 프로그램 실행 중 발생할 수 있는 예상치 못한 상황을 처리하기 위한 메커니즘입니다. 모든 예외는 Throwable
클래스를 상속받으며, 크게 Error
와 Exception
으로 나뉩니다.
// Exception 계층도
Throwable
├── Error
│ ├── OutOfMemoryError
│ ├── StackOverflowError
│ └── ...
└── Exception
├── IOException (Checked)
├── SQLException (Checked)
└── RuntimeException (Unchecked)
├── NullPointerException
├── IllegalArgumentException
└── ...
2. Exception vs Error
Error
- 시스템 레벨에서 발생하는 심각한 문제
- 애플리케이션에서 복구가 불가능한 상황
- 예외 처리(try-catch)를 권장하지 않음
public class ErrorExample {
public static void main(String[] args) {
// StackOverflowError 예시
recursiveMethod(1);
}
public static void recursiveMethod(int i) {
recursiveMethod(i + 1); // 무한 재귀 호출
}
}
Exception
- 애플리케이션 레벨에서 발생하는 문제
- 프로그램에서 처리 가능한 상황
- 예외 처리를 통한 복구 가능
3. Checked Exception vs Unchecked Exception
Checked Exception
- 컴파일 시점에 확인
- 반드시 예외 처리 필요 (try-catch 또는 throws)
- 주로 외부 리소스와의 상호작용에서 발생
public class CheckedExceptionExample {
public void readFile() throws IOException {
File file = new File("nonexistent.txt");
FileInputStream fis = new FileInputStream(file); // IOException 발생 가능
}
public void handleFile() {
try {
readFile();
} catch (IOException e) {
// 예외 처리 로직
logger.error("파일 읽기 실패", e);
}
}
}
Unchecked Exception
- 런타임 시점에 확인
- 명시적인 예외 처리가 강제되지 않음
- 프로그래머의 실수로 인한 로직 오류에서 발생
public class UnCheckedExceptionExample {
public void divideNumbers(int a, int b) {
if (b == 0) {
throw new IllegalArgumentException("0으로 나눌 수 없습니다.");
}
int result = a / b;
}
// throws 선언이 필요하지 않음
public void processNumbers() {
try {
divideNumbers(10, 0);
} catch (IllegalArgumentException e) {
// 예외 처리 로직
logger.error("잘못된 입력값", e);
}
}
}
4. Exception 처리 전략
예외 처리 원칙
- 예외는 가능한 한 발생한 지점과 가까운 곳에서 처리
- 예외 처리와 비즈니스 로직은 분리
- 예외는 충분한 정보를 포함해야 함
public class ExceptionHandlingStrategy {
public void processBusinessLogic() {
try {
// 비즈니스 로직
performOperation();
} catch (SQLException e) {
// 구체적인 예외를 래핑하여 상위 레이어로 전달
throw new BusinessException("데이터 처리 중 오류 발생", e);
} catch (Exception e) {
// 예상치 못한 예외 처리
throw new SystemException("시스템 오류 발생", e);
} finally {
// 리소스 정리
cleanup();
}
}
}
5. Best Practices
Custom Exception 정의
public class BusinessException extends RuntimeException {
private final ErrorCode errorCode;
public BusinessException(String message, ErrorCode errorCode) {
super(message);
this.errorCode = errorCode;
}
public BusinessException(String message, ErrorCode errorCode, Throwable cause) {
super(message, cause);
this.errorCode = errorCode;
}
}
예외 처리 템플릿
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(BusinessException.class)
public ResponseEntity<ErrorResponse> handleBusinessException(BusinessException e) {
return new ResponseEntity<>(
new ErrorResponse(e.getErrorCode(), e.getMessage()),
HttpStatus.BAD_REQUEST
);
}
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleException(Exception e) {
return new ResponseEntity<>(
new ErrorResponse(ErrorCode.INTERNAL_SERVER_ERROR, "서버 오류가 발생했습니다."),
HttpStatus.INTERNAL_SERVER_ERROR
);
}
}
6. 실전 예제
트랜잭션 처리와 예외
@Service
@Transactional
public class OrderService {
public Order createOrder(OrderRequest request) {
try {
validateOrder(request);
Order order = orderRepository.save(new Order(request));
paymentService.process(order);
return order;
} catch (InvalidOrderException e) {
throw new BusinessException("주문 생성 실패", ErrorCode.INVALID_ORDER, e);
} catch (PaymentException e) {
throw new BusinessException("결제 처리 실패", ErrorCode.PAYMENT_FAILED, e);
}
}
}
7. 면접 대비 Q&A
Q1: Checked Exception과 Unchecked Exception의 주요 차이점은?
A:
- Checked Exception은 컴파일 시점에 확인되며, 반드시 예외 처리가 필요합니다.
- Unchecked Exception은 런타임에 확인되며, 명시적인 예외 처리가 강제되지 않습니다.
- Checked Exception은 메서드 시그니처에 throws 선언이 필요하지만, Unchecked Exception은 불필요합니다.
Q2: 어떤 경우에 Custom Exception을 만들어야 하나요?
A:
- 비즈니스 로직에 특화된 예외 처리가 필요할 때
- 예외에 추가적인 정보(에러 코드, 상태 등)를 포함해야 할 때
- 예외 처리를 통일화하고 표준화해야 할 때
Q3: Exception 처리 시 주의할 점은?
A:
- 예외를 무시하지 않고 적절히 처리하거나 전파
- 예외 처리 시 충분한 컨텍스트 정보 포함
- 예외 처리 계층을 명확히 구분
- 너무 상위 레벨의 예외를 잡지 않기
- 로깅과 모니터링을 통한 예외 추적
Q4: try-with-resources와 일반 try-catch의 차이는?
A: try-with-resources는 AutoCloseable을 구현한 리소스의 자동 해제를 보장합니다.
// try-with-resources
try (FileInputStream fis = new FileInputStream("file.txt")) {
// 리소스 사용
} catch (IOException e) {
// 예외 처리
}
// 일반 try-catch
FileInputStream fis = null;
try {
fis = new FileInputStream("file.txt");
// 리소스 사용
} catch (IOException e) {
// 예외 처리
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
// close 실패 처리
}
}
}
Q5: 예외 처리 시 성능 고려사항은?
A:
- 예외는 실제 예외 상황에서만 사용 (제어 흐름용으로 사용 금지)
- 예외 스택 트레이스 생성은 비용이 큼
- try-catch 블록 내부는 최소화
- 예외 처리는 최대한 구체적으로 (Exception보다는 구체적인 예외 사용)
반응형
'JAVA' 카테고리의 다른 글
일급 컬렉션(First-Class Collection)을 사용해야 하는 이유 (0) | 2024.11.22 |
---|---|
클래스와 메소드 이해하기 (0) | 2024.06.13 |