J-S-14 자바 예외 처리

글 정보
카테고리
Programming/Java/Starter
태그
JavaLevel1

1. 에러와 예외의 정의

오류(Error)와 예외(Exception)는 프로그램 실행을 막는 상황을 뜻합니다.

정상적인 연산이나 실행이 불가능한 상태를 말합니다.

보통 아래 세 가지 시점에 발생합니다.

예외 처리(Exception Handling)는 이러한 비정상적인 상황을 대비하는 기법입니다.

예외 상황을 별도로 처리함으로써 프로그램이 강제 종료되지 않고, 흐름을 계속 이어갈 수 있게(Fail-safe) 만드는 것이 핵심입니다.

자바에서는 java.lang.Exception 클래스를 기반으로 이를 관리합니다.

성공하는 상황(Happy Path)을 가정하고 코드를 작성하되, 예외 처리를 따로 분리하면 코드의 가독성이 크게 높아집니다.

(참고) Short Circuit의 원리란?

'Short Circuit'은 논리 연산(&&, ||) 외에도 예외 처리 흐름에서 사용되는 개념입니다.
- 예외가 발생하는 즉시 나머지 로직 실행을 중단(단락)하고,
- 바로 catch 블록으로 점프하는 동작 방식을 의미합니다.
- 불필요한 연산을 막고 즉시 대응 체계로 넘어가는 효율적인 구조입니다.

2. 자바의 예외 계층 구조 (Error vs Exception)

자바는 발생 원인과 대응 가능성에 따라 크게 두 가지로 구분합니다. 이 둘을 나누는 기준은 "애플리케이션단에서 복구할 수 있는가?"입니다.

Error (에러)

시스템 레벨에서 발생하는 심각한 문제입니다.

Exception (예외)

개발자가 구현한 로직 내에서 발생하는 문제입니다.

(Q&A) Error와 Exception을 굳이 나눈 이유는?

JVM 실행 환경 자체의 문제(Error)와 프로그램 논리의 문제(Exception)를 분리하여,
개발자가 "통제할 수 있는 영역"에만 집중하게 하기 위함입니다.

3. 두 가지 예외 종류 (Checked vs Unchecked)

대응 관점과 컴파일러의 개입 여부에 따라 나뉩니다.

Checked Exception

Unchecked Exception

4. 대표적인 예외 사례

런타임 예외 (Unchecked)

주로 개발자의 실수로 발생합니다.

String emptyBox = null;

// 내용물이 없는데(null) 길이를 재려고 해서 에러가 펑!
int length = emptyBox.length();
int[] numbers = {1, 2, 3}; // 인덱스는 0, 1, 2 까지 있음

// 5번째 칸은 존재하지 않으므로 에러 발생
System.out.println(numbers[5]);
String text = "이천이십오";

// "이천이십오"는 아라비아 숫자가 아니라서 변환 실패
int year = Integer.parseInt(text);
Object box = "나는 문자열입니다";

// 문자열이 들어있는 박스를 갑자기 숫자(Integer)라고 우기면 에러 발생
Integer number = (Integer) box;

보편적 예외 (I/O 관련)

외부 시스템과의 연동 시 주로 발생하며, 통제하기 어려운 요소가 많습니다.

// "secret.txt" 파일이 실제 경로에 없으면 에러 발생
FileInputStream file = new FileInputStream("C:/secret.txt");
// 해당 IP나 포트(8080)가 닫혀있거나 방화벽에 막히면 연결 거부 에러 발생
Socket socket = new Socket("192.168.0.99", 8080);
// 'members'라는 테이블이 없거나 컬럼명이 틀리면 에러 발생
stmt.executeQuery("SELECT * FROM 없는테이블 WHERE id = 'test'");

5. 예외 처리 방법 (Handling)

try - catch - finally

가장 기본적인 직접 처리 방식입니다.

try {
    System.out.println("1. 연산을 시작합니다.");
    int result = 10 / 0;  // 여기서 에러 발생! (ArithmeticException)
    System.out.println("2. 이 코드는 실행되지 않습니다."); // 실행 건너뜀

} catch (ArithmeticException e) {
    // 에러가 발생하면 즉시 이곳으로 넘어옵니다.
    System.out.println("3. 0으로 나눌 수 없어 에러를 잡았습니다.");

} finally {
    // 에러 발생 여부와 상관없이 무조건 실행됩니다. (리소스 정리 등)
    System.out.println("4. 계산기를 종료합니다.");
}

throws

예외 처리를 위임(Delegation)하는 방식입니다.

// 1. (Callee) 에러를 직접 처리하지 않고 throws로 던지는 메서드
public void findFile() throws FileNotFoundException {
    // 파일이 없으면 에러가 나는데, 여기서 try-catch를 안 씀
    FileReader fr = new FileReader("없는파일.txt"); 
}

// 2. (Caller) 위 메서드를 호출한 쪽에서 억지로라도 처리를 해야 함
public void mainLogic() {
    try {
        findFile(); // 여기서 에러가 넘어옴
    } catch (FileNotFoundException e) {
        System.out.println("넘겨받은 에러를 여기서 처리합니다.");
    }
}