IT/JAVA

Java 예외: RuntimeException

iamhyeon 2025. 12. 6. 19:02

 

RuntimeException

Java에서는 프로그램 실행 중 나타나는 오류(exception or error)를 처리하기 위해 예외(Exception) 클래스를 제공한다.

그중 RuntimeException은 “런타임 예외(Runtime Exception)”로 불리며,

보통 예측 불가능한 프로그래밍 오류를 나타낼 때 사용된다.

 

RuntimeException을 직접 사용하거나, 그 하위 클래스를 사용하는 것 

=>  이게 바로 흔히 말하는 “Unchecked Exception”이다.

 

반대로 RuntimeException을 상속하지 않는 예외들은 Checked Exception으로 분류된다.

 

 

Checked Exception vs Unchecked Exception 차이

 

검사 시점 컴파일 시점 — 예외 처리를 강제 런타임 시점 — 컴파일러가 검사하지 않음 
선언 및 처리 필요 여부 try-catch 또는 throws 키워드로 처리하거나 선언해야 한다 선언이나 처리 없이도 됨
개발자 선택에 따라 catch 가능 
주로 발생하는 상황 파일 I/O, 네트워크, DB 접근 등
외부 리소스와의 상호작용 중 발생 가능한 예외
프로그래밍 실수나 논리 버그
(예: null 참조, 배열 인덱스 벗어남, 잘못된 연산)
예시 IOException,
SQLException,
ClassNotFoundException 등 
NullPointerException,
ArrayIndexOutOfBoundsException,
IllegalArgumentException,
ArithmeticException 등 

 

  • Checked Exception은 예측 가능한 실패 상황(예: 파일이 없어서 읽을 수 없음)에 대비하도록 설계
    → 호출자는 반드시 “예외가 발생할 수 있음”을 인지하고 처리하거나 상위로 던져야 한다.
  • Unchecked Exception은 프로그래밍 오류나 개발자 실수를 나타내며,
    → 컴파일 시점에서는 알 수 없고, 런타임 시점에만 드러나므로, 개발자에게 필요할 때만 책임지고 처리할 수 있게 한다. 

“회복 가능한 예외인가?” vs “코드 논리·버그인가?”라는 관점에서 선택이 달라진다.

 

RuntimeException (Unchecked Exception) 의 특징과 주의점

✔️ 특징

  • 메서드 시그니처에 throws 선언이 필요 없다.
  • 호출 측에서는 예외를 강제적으로 처리할 필요가 없다.
  • 예외 처리에 얽매이지 않아 코드가 간결해질 수 있다.
  • 주로 논리적 오류나 프로그래머 실수에 의해 발생하는 예외가 많다
  • String s = null; s.length(); // NullPointerException 등

✔️ 주의할 점

Unchecked 예외는 “무시”하기 쉽다. 예외 처리를 생략할 수 있기 때문이다.
따라서 다음과 같은 문제가 생길 수 있다:

  • 예외 발생 시 전체 애플리케이션이 예상치 못하게 종료될 수 있다.
  • 예외 상황을 엉뚱하게 무시하거나 숨기면서, 버그가 조용히 누적될 수 있다.
  • 예외가 발생할 수 있는 지점을 명확히 예측하기 어렵다 — 특히 외부 자원 접근이 섞인 코드에서는 더욱 그렇다.

Unchecked Exception을 남발하면, “누가 어디서 왜 에러가 났는지” 추적이 어려워진다.

 

언제 Checked Exception, 언제 RuntimeException (Unchecked) 을 써야 할까?

 

  • 회복 가능한 실패가 예상되는 상황 → Checked Exception
    예: 파일이 없어서 읽지 못했다면, 이걸 호출자에게 알려주고 “대체 행동”을 하게 할 수 있음
  • 프로그래머 실수 / 논리 오류 / 예측 불가 내부 버그 → Unchecked Exception (RuntimeException)
    예: null 참조, 잘못된 인자 전달, 배열 인덱스 벗어남 등 — 이런 건 코드 수정으로 해결해야 함
  • API 설계 시
    • 만약 호출자가 “예외에 대비해야 한다”고 강제하고 싶다면 → Checked Exception
    • 예외가 발생하면 호출자가 속성적으로 복구할 수 없고, 단순히 호출이 잘못된 것이라면 → Unchecked Exception



예시 코드

// Checked Exception 예시
public void readFile(String path) throws IOException {
    FileInputStream in = new FileInputStream(path);
    // ...
}

// 호출 쪽: 반드시 try-catch 또는 throws 선언
try {
    readFile("somefile.txt");
} catch (IOException e) {
    // 파일을 읽을 수 없을 때 대체 동작
    // e.g. 사용자에게 알림, 기본값 사용 등
}

// Unchecked Exception 예시
public int divide(int a, int b) {
    return a / b;  // b가 0이면 ArithmeticException (Unchecked)
}

public void process(String input) {
    if (input == null) {
        throw new IllegalArgumentException("input must not be null");
    }
    // ...
}

 

Unchecked 예외는 선언이나 처리 없이도 던질 수 있다.
하지만 이런 경우엔 반드시 예외 발생 가능성을 코드 주석이나 문서로 남겨야 한다 

 

 

RuntimeException을 포함한 예외 설계의 팁

  • RuntimeException 계열(언체크드 예외)은 프로그래밍 오류나 불가능한 상황을 나타낼 때 사용
  • 예측 가능한 실패 (외부 리소스, 사용자 입력 오류 등)은 Checked Exception으로
  • API 설계 시 호출자에게 “예외 처리 책임을 누가 지는가?”를 명확히 고려
  • 무작정 모든 예외를 RuntimeException으로 바꾸면 코드가 간결해질 수 있지만, 예외의 의미와 책임 구조가 흐트러질 수 있다.

 

Java에서 RuntimeException은 “불완전한 코드 / 예측 불가능한 상황”을 나타내는 강력한 도구이다.
하지만 그만큼 책임감 있게 사용해야 한다.

어떤 예외를 던질지, 어떤 예외를 반드시 처리해야 할지.

그 설계가 코드의 안정성과 유지보수성을 좌른다.

 

반응형