Contents
see List작성일 2025. 11. 30.
Java 예외 처리 전략
효과적인 예외 처리는 안정적인 애플리케이션의 핵심입니다. 체크 예외와 언체크 예외를 적절히 사용하고, 의미 있는 예외 메시지와 로깅으로 디버깅을 쉽게 만들어야 합니다.
예외 계층 구조
Throwable
├── Error (시스템 오류, 처리 불가)
│ └── OutOfMemoryError, StackOverflowError
└── Exception
├── Checked Exception (컴파일러가 체크)
│ └── IOException, SQLException
└── RuntimeException (Unchecked, 런타임 체크)
└── NullPointerException, IllegalArgumentException체크 vs 언체크 예외 선택 기준
| 체크 예외 | 언체크 예외 |
|---|---|
| 호출자가 복구 가능할 때 | 프로그래밍 오류일 때 |
| 외부 리소스 접근 실패 | 잘못된 인자, null 참조 |
| 반드시 처리해야 할 때 | 개발자 실수 |
커스텀 예외 정의
// 비즈니스 예외 기본 클래스
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;
}
}
// 에러 코드 enum
public enum ErrorCode {
USER_NOT_FOUND("U001", "사용자를 찾을 수 없습니다"),
INVALID_PASSWORD("U002", "비밀번호가 일치하지 않습니다"),
DUPLICATE_EMAIL("U003", "이미 등록된 이메일입니다");
private final String code;
private final String message;
// constructor, getters
}
// 구체적인 예외
public class UserNotFoundException extends BusinessException {
public UserNotFoundException() {
super(ErrorCode.USER_NOT_FOUND);
}
}예외 처리 Best Practices
// 1. 구체적인 예외를 먼저 catch
try {
// 작업
} catch (FileNotFoundException e) {
// 파일 없음 처리
} catch (IOException e) {
// 기타 I/O 오류
}
// 2. 예외 체이닝 (원인 보존)
try {
parseData(input);
} catch (ParseException e) {
throw new BusinessException(ErrorCode.PARSE_ERROR, e);
}
// 3. try-with-resources 사용
try (InputStream is = new FileInputStream(file);
BufferedReader reader = new BufferedReader(
new InputStreamReader(is))) {
return reader.readLine();
}
// 4. 불필요한 catch 금지
// BAD
try {
doSomething();
} catch (Exception e) {
throw e; // 의미없는 재던지기
}
// 5. 로깅 후 던지기 (중복 로깅 주의)
try {
process();
} catch (Exception e) {
log.error("처리 실패: {}", e.getMessage());
throw new ProcessException(e);
}Spring 글로벌 예외 처리
@RestControllerAdvice
public class GlobalExceptionHandler {
private static final Logger log =
LoggerFactory.getLogger(GlobalExceptionHandler.class);
@ExceptionHandler(BusinessException.class)
public ResponseEntity<ErrorResponse> handleBusiness(
BusinessException e) {
log.warn("비즈니스 예외: {}", e.getMessage());
return ResponseEntity
.status(HttpStatus.BAD_REQUEST)
.body(new ErrorResponse(e.getErrorCode()));
}
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleUnexpected(
Exception e) {
log.error("예상치 못한 오류", e);
return ResponseEntity
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(ErrorResponse.of("서버 오류가 발생했습니다"));
}
}
// 에러 응답 DTO
@Getter
public class ErrorResponse {
private String code;
private String message;
private LocalDateTime timestamp;
public ErrorResponse(ErrorCode errorCode) {
this.code = errorCode.getCode();
this.message = errorCode.getMessage();
this.timestamp = LocalDateTime.now();
}
}Optional로 null 예외 방지
// Optional 활용
public User findUser(Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new UserNotFoundException());
}
// null 체크 대신 Optional
Optional.ofNullable(value)
.map(String::trim)
.filter(s -> !s.isEmpty())
.orElse("default");예외 처리 안티패턴
- 빈 catch 블록 (예외 삼키기)
- Exception으로 모든 것 catch
- 예외를 흐름 제어에 사용
- 필요 이상으로 넓은 범위의 try
java
| No | 작성일 | Title |
|---|---|---|
| 2874 | 2026. 05. 24. | Java 서비스 ThreadPoolExecutor 포화 방지: 큐 크기, 거절 정책, 백프레셔 실전 가이드 |
| 2799 | 2026. 05. 16. | Java 운영 장애 분석을 위한 JFR·jcmd 실전 가이드: 재시작 없이 CPU·메모리 증거 남기기 |
| 2603 | 2026. 04. 24. | Java 26 Pattern Matching 실전 가이드: Records · Sealed Classes · Primitive Patterns로 분기 없는 도메인 모델링 |
| 2518 | 2026. 04. 16. | Java 26 Virtual Threads & Structured Concurrency 실전 가이드: 가상 스레드로 고성능 서버 구축하기 |
| 2491 | 2026. 04. 14. | Java 21/25 Virtual Threads 완벽 가이드: 기존 스레드 모델과의 차이, 실전 활용법 |
| 2470 | 2026. 04. 13. | Java 25 Virtual Threads & Structured Concurrency 완벽 가이드 |
| 2450 | 2026. 04. 12. | Java 21 Virtual Threads 완벽 가이드: Project Loom으로 수백만 스레드 다루기 |
| 2426 | 2026. 04. 11. | Java 24 Primitive Type Pattern Matching 완벽 가이드 - switch와 instanceof 확장 |
| 2390 | 2026. 04. 09. | Java 26 신기능 완벽 가이드 - AOT 캐시, Compact Headers, 패턴 매칭 실전 활용 |
| 2369 | 2026. 04. 08. | Java 21/25 완벽 가이드: Virtual Threads, Record Patterns, Structured Concurrency 실전 적용 |