체크 예외, 언체크 예외

throws Exception이라고 선언해도,

**언체크 예외(RuntimeException 계열)**는 컴파일러가 강제하지 않기 때문에 사실상 throws 선언 없이도 자동으로 밖으로 던져집니다.


🔍 설명

예외 종류

예시

throws 필요 여부

강제 여부

체크 예외 (Checked)

IOException, SQLException

✅ 필요

✅ 컴파일러가 강제

언체크 예외 (Unchecked)

NullPointerException, IllegalArgumentException, RuntimeException

❌ 필요 없음

❌ 컴파일러 강제 안 함


🔧 예시 코드

class Facade {
    void send() throws Exception {
        throw new IllegalArgumentException("잘못된 인자"); // 언체크 예외
    }
}
  • 이건 throws Exception이 있든 없든 컴파일 오류가 나지 않습니다.

  • 왜냐하면 IllegalArgumentExceptionRuntimeException의 하위 클래스, 즉 언체크 예외이기 때문입니다.


✅ 결론

  • throws Exception을 써도 언체크 예외까지 모두 반드시 던지겠다는 의미는 아님

  • **런타임 예외(RuntimeException 계열)**는 throws 없이도 자동으로 전달되고, 컴파일러는 신경 안 씀

  • 실제로 중요한 건 체크 예외(Checked Exception)일 때만 컴파일러가 throws를 요구한다는 점이에요.

왜 자바는 RuntimeException 계열 예외는 컴파일러가 체크하지 않도록 설계했는가? → 이건 자바 예외 설계 철학의 핵심 중 하나입니다.


✅ 먼저 정리: Checked vs Unchecked 예외

구분
Checked Exception
Unchecked Exception (Runtime)

강제 여부

try-catch 또는 throws 필수

처리 강제 없음

예시

IOException, SQLException

NullPointerException, IllegalArgumentException

목적

외부 환경/자원 문제 (복구 가능성 있음)

프로그래밍 오류 (복구 불가능, 논리 문제)


✅ 그럼 왜 RuntimeException은 체크하지 않을까?

📌 1. 프로그래머 실수(논리 오류)는 예외 처리로 해결할 수 없음

  • 예: null 객체에 접근하면 NullPointerException

  • 이런 실수는 정상적인 코드 흐름으로는 복구가 어렵다

  • try-catch로 억지로 막지 말고, 코드를 고치라는 의미

🔴 RuntimeException = 개발자가 잘못 짠 코드의 결과, 예외 처리로 복구하려 하지 말 것


📌 2. 코드가 너무 지저분해지는 걸 막기 위해

  • 모든 메서드가 throws RuntimeException을 붙이면, 수많은 메서드에 try-catch가 필요해져서 가독성, 생산성 모두 떨어짐

  • → 그래서 자바는 개발자에게 선택권을 줌: "복구 불가능한 예외는 굳이 체크하지 마라."


📌 3. 성능과 생산성의 균형

  • RuntimeException은 빠르게 전파되며 스택 트레이스로 추적 가능

  • 예외 상황을 일일이 처리하지 않아도 프로그램 디버깅 가능

  • 개발자 경험을 해치지 않도록 설계됨


📌 4. 실제로도 RuntimeException은 잡지 말라는 관례

try {
    int x = 10 / 0;
} catch (ArithmeticException e) {
    // 보통 이렇게 하지 말라고 함 → 코드 자체를 고쳐야 할 문제
}

✅ 결론

이유
설명

❌ 복구 불가능

RuntimeException은 프로그래머 실수의 결과 (로직 오류)

❌ try-catch 남용 방지

의미 없는 예외 처리 코드가 양산되지 않도록

✅ 선택권 부여

개발자가 진짜 필요한 경우에만 처리할 수 있도록 유연성 확보

Last updated