우당탕탕
Java 예외 처리, Checked와 Unchecked를 실제로 언제 써야 할까 본문
저도 처음 Java 예외 처리할 때 Checked 예외와 Unchecked 예외 구분이 너무 헷갈렸어요. "이거 도대체 언제 쓰는 게 맞는 거야?" 하면서 코드 작성하다가 삽질을 많이 했거든요.
이 글에서는 제가 겪었던 실제 고민과 문제 상황, 그리고 타사례와 비교해서 어떤 상황에 Checked 예외를 쓰고 언제 Unchecked 예외를 써야 하는지 완전히 정리해봤습니다. 코드 예시와 함께 보시면 훨씬 이해가 쉬울 거예요.
개발 환경 / 버전 정보
제가 테스트하던 환경은 Java 17에
실제 운영은 Spring Boot 3.1 기반이었어요. 이 글의 설명은 Java 표준 예외 처리 기준이며,
스프링의 AOP나 트랜잭션 처리와도 연동해서 생각하면 더 좋습니다.
Java 예외 처리 checked vs unchecked 언제 쓸까 관련 정보
Checked 예외, Unchecked 예외 기본 개념부터 다시
사실 이 부분이 가장 많이 헷갈리고 혼동되는 부분인데요, 간단히 정리하면 이렇습니다.
- Checked 예외는 컴파일 시점에 예외 처리를 강제하는 예외입니다. 메서드 선언부에 반드시
throws를 명시해야 하고, 호출하는 쪽에서 예외 처리를 강제당해요. - Unchecked 예외는 런타임 예외로, 컴파일러가 예외 처리를 강제하지 않습니다. 주로
RuntimeException과 그 하위 예외들이 여기에 해당하죠.
그래서 Checked 예외는 "예외 상황을 반드시 신경 써야 하는 경우"에 쓰고, Unchecked 예외는 "프로그램의 논리적 오류나 개발자가 수정해야 할 버그"에 주로 쓰는 게 권장돼요.
제가 만난 사례: Checked 예외로 파일 읽기 처리할 때
한번은 사용자 입력 받은 파일을 읽는 기능을 만들면서 IOException 처리를 고민했었어요. 컴파일러가 IOException을 Checked 예외로 강제하기 때문에 메서드 선언에 throws IOException을 써야 했고, 호출하는 쪽에서도 예외를 처리해야 했죠.
public void readFile(String filePath) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
}
여기서는 파일이 없거나 읽기 실패하면 당장 복구가 불가능하니 호출자가 예외를 반드시 처리하도록 만드는 게 맞다고 판단했어요. 그래서 Checked 예외를 쓴 거죠.
다른 사람들의 사례: Unchecked 예외를 선호하는 경우
그런데 최근 몇몇 개발자들이나 오픈소스 프로젝트를 보면, Checked 예외 대신 Unchecked 예외를 선호하는 사례가 많더라고요. 예를 들어, 데이터베이스 작업 중에 발생하는 예외를 런타임 예외로 바꿔서 처리하는 경우가 많았어요.
예를 들어 Spring의 DataAccessException은 RuntimeException을 상속받아서, 컴파일러가 예외 처리를 강제하지 않게 설계됐죠. 그래서 코드가 깔끔해지고 예외처리에 따른 중복 코드가 줄어드는 장점이 있어요.
public void saveData(Entity entity) {
try {
repository.save(entity);
} catch (DataAccessException e) {
// 예외 처리 로직 (주로 로그 기록 및 재시도)
}
}
여기서는 예외가 발생해도, 장애 대응 로직을 한 곳에 집중하거나 트랜잭션 롤백 등을 위임하는 식으로 처리하는 경우가 많더라고요.
Java 예외 처리 checked vs unchecked 언제 쓸까 관련 정보
Checked vs Unchecked 쉽게 비교하는 표
| 항목 | Checked 예외 | Unchecked 예외 |
|---|---|---|
| 컴파일러 처리 | 예외 처리를 강제함 (throws 필수) | 처리 강제하지 않음 |
| 예외 대상 | 복구 가능한 외부 문제 (파일, DB 연결 등) | 개발자의 논리적 오류, 프로그래밍 버그 |
| 예외 처리 방식 | 메서드 시그니처에 명시, 호출자 처리 강제 | 필요 시 처리, 선택적 |
| API 설계 영향 | 사용자에게 예외 상황을 명확히 알림 | API가 깔끔하나 예외가 숨겨질 위험 |
| 단점 | 코드가 복잡해질 수 있음 | 예외 관리 소홀 위험 |
제가 직접 해보면서 정리한 기준
제가 프로젝트를 진행하면서 일단 아래 기준으로 예외를 나눠서 처리하고 있어요.
- 외부 자원 문제 같은 회복 가능한 상황 (파일 읽기 실패, 네트워크 문제 등)은 Checked 예외를 써서 호출자에게 꼭 예외 처리를 강제
- 개발자 실수, 잘못된 API 사용 같은 논리적 문제는 Unchecked 예외로 던져서 RuntimeException에 맡김
- 비즈니스 정책 위반 등 검증 실패는 보통 Unchecked 예외로 처리하고, 필요한 곳에서 예외를 잡아서 메시지를 사용자에게 보여줌
이렇게 쓰면 실제로 예외 복구 로직이 깔끔하게 모이고, 불필요한 throws 선언과 try-catch 블록이 줄어들더라고요.
실제 코드 예시: Checked와 Unchecked 예외 함께 쓰기
예를 들어 다음과 같은 파일 업로드 서비스를 생각해볼게요.
public class FileUploadService {
// Checked 예외 - 외부 파일 처리 문제
public void uploadFile(String filePath) throws IOException {
// 파일 존재 여부 체크, IOException 발생 가능
if (!new File(filePath).exists()) {
throw new IOException("File not found: " + filePath);
}
// 업로드 처리 로직
}
// Unchecked 예외 - 비즈니스 룰 위반
public void validateFileExtension(String fileName) {
if (!fileName.endsWith(".jpg")) {
throw new IllegalArgumentException("지원하지 않는 파일 형식입니다.");
}
}
}
이렇게 외부 상황 문제는 Checked 예외로 던지고, 내부 검증 실패는 Unchecked 예외로 던져요.
Java 예외 처리 checked vs unchecked 언제 쓸까 관련 정보
여기서 삽질했던 부분들
사실 처음엔 무조건 Checked 예외를 쓰려고 했는데, 이러다 보니 호출하는 쪽에서 너무 많은 try-catch가 나와서 코드가 지저분해지고 유지보수가 힘들었어요. 특히 예외를 단순히 래핑(wrapping)만 하는 경우도 많았고요.
try {
service.uploadFile("test.png");
} catch (IOException e) {
throw new RuntimeException(e); // 불필요한 예외 래핑
}
이 부분에서 다른 개발자들 코드와 비교하며 "굳이 이렇게까지 해야 하나?" 싶어서 권장 패턴을 찾아봤죠.
심화: Unchecked 예외를 커스텀해서 상태 관리하기
제가 많이 쓴 방법이 커스텀 Unchecked 예외를 만들어서 비즈니스 상태를 포함시키는 거였어요. 예를 들어, 오류 코드와 메시지를 갖는 예외 클래스를 정의해서 한 번에 처리하는 패턴이죠.
public class BusinessException extends RuntimeException {
private final String errorCode;
public BusinessException(String errorCode, String message) {
super(message);
this.errorCode = errorCode;
}
public String getErrorCode() {
return errorCode;
}
}
이렇게 하면 호출하는 쪽에서 예외를 catch 해서 공통 에러 핸들러에 넘기거나, 클라이언트에 통일된 메시지를 전달할 때 편리해요.
자주 물어보시는 것들
Q. Checked 예외를 왜 아예 쓰지 말라는 사람들도 있나요?
A. 네, 특히 대규모 프로젝트에서는 Checked 예외가 많으면 오히려 유지보수가 복잡해져서 아예 런타임 예외로 통일하는 사례가 많아요. 하지만 저는 중요한 외부 자원 접근 예외는 반드시 Checked로 관리하는 편입니다.
Q. Unchecked 예외를 남발하면 안 좋은 점은 뭔가요?
A. 예외 처리를 깜빡하거나 너무 늦게 발견하면 장애로 연결되기 쉽습니다. 그래서 커스텀 Unchecked 예외를 잘 설계하고, 예외 발생 위치나 로그 기록을 신경 써야 합니다.
Q. Spring 프레임워크는 Checked 예외를 어떻게 권장하나요?
A. Spring은 JDBC 관련 예외들을 Unchecked 예외로 감싸서 제공하는 편입니다. 그래서 많이들 Spring 환경에서는 Unchecked 예외를 선호하는 편이죠.
제가 직접 경험하며 느낀 건, "언제든 예외가 발생하면 호출자가 반드시 어떻게든 처리해야 한다면 Checked 예외"를, "그렇지 않고 예외가 프로그램 흐름을 방해하면 안 된다면 Unchecked 예외를 써야 한다"는 거였어요. 물론 프로젝트 특성에 따라 달라지겠지만, 이 기준을 갖고 나니 코드 유지보수가 훨씬 편해졌답니다.
'언어 > Java' 카테고리의 다른 글
| Java 17에서 실무에 바로 써먹는 새로운 기능들 체크리스트 (0) | 2026.08.27 |
|---|---|
| Java Optional 제대로 쓰는 법과 흔한 안티패턴 사례 비교 (0) | 2026.08.07 |
| Java 예외 처리에서 Checked와 Unchecked, 비용 차이로 이해하기 (0) | 2026.07.30 |
| Java 17 새로운 기능, 실무에 바로 적용하는 절차 중심 가이드 (0) | 2026.07.23 |
| Java 동시성 컬렉션 ConcurrentHashMap 실제 사용하며 겪은 문제들 (0) | 2026.07.23 |
