27. 예외 처리(Exception Handling)

박은서's avatar
Jan 04, 2026
27. 예외 처리(Exception Handling)

1. 예외(Exception)

1️⃣ 예외란?

프로그램 실행 중 발생하는 비정상적인 상황을 의미
int a = 10 /0; // 실행 중 오류 발생
➡️ 이런 실행 중(Runtime) 문제가 발생하면, 자바는 Exception 객체를 생성하고 프로그램에 알림
✔️ 예외를 처리하지 않으면 프로그램은 즉시 종료

2️⃣ 예외의 종류

1) Checked Exception

  • 통제는 불가능하지만 예상은 가능한 예외
  • 컴파일러가 예외 처리를 강제로 요구 → 처리하지 않으면 컴파일 오류 발생
  • Try/Catch문으로 예외를 잡거나 예외가 터진 메서드를 호출한 곳으로 throw할 수 있음
    • But, 예외가 JVM까지 넘어가기 전에는 처리해야 함
  • Object > Throwable > Exception 클래스 안에서
    • RuntimException을 제외한 모든 Exception 클래스는 Checked Exception(예상 가능한 예외)
  • 클래스명 extends Exception 으로 사용 가능

2) Unchecked Exception (Runtime Exception)

  • 예상이 불가능하며 실행 중 발생하는 예외
  • 처리 강제 없음
  • 한 번 예외가 터지고 나면 이제 예상 가능한 예외이기 때문에 조치해야 함
  • Object > Throwable > Exception 중
    • RuntimException 클래스는 Unchecked Exception(예상 불가능한 예외)
  • 클래스명 extends RuntimException 으로 사용 가능

3) Error (아직 안 배움)

  • 프로그램이 복구 불가능한 심각한 오류
    • → 일반적으로 예외 처리로 다루지 않음

3️⃣ 자바 예외 계층 구조

notion image
 

2. 예외 전파(Exception Propagation)

1️⃣ 예외 전파란?

예외가 발생하면 그 메서드 안에서 해결되지 않을 경우, 그 예외는 메서드를 호출한 곳으로 전달되면서 위로 올라감
예외는 catch로 잡히지 않으면 자동으로 메서드 밖으로 튀어나가서 그 메서드를 호출한 쪽으로 전달
※ 예외가 발생하면 JVM까지 전달되기 전에 잡아채서(catch) 제어해야 함

2️⃣ 예외 전파의 예시

A() → B() → C()
  • C() 안에서 예외가 발생
  • C() 안에 try-catch 없음
  • 그럼 예외는 C() 밖으로 나가서 B()에게 전달
  • B()에도 try-catch가 없음
  • 예외는 다시 B() 밖으로 나가서 A()로 전달
  • A()에도 try-catch가 없음
  • main에도 try-catch가 없으면 마지막으로 main을 호출한 JVM까지 전달됨 → 프로그램 종료(예외 메시지 출력)
 

3. 예외 처리(Exception Handling)

교재 p.351-358 / 8.10 예외 처리란?

1️⃣ 예외 처리란?

프로그램 실행 중 발생할 수 있는 오류(예외)를 미리 대비하고 처리하는 방법
오류 때문에 프로그램이 갑자기 종료되지 않도록 하고, 상황에 맞는 조치를 취하도록 도와줌

2️⃣ 예외 처리가 필요한 이유

프로그램에는 예측하기 어려운 상황이 많이 생김
  • 존재하지 않는 파일을 읽으려고 할 때
  • 0으로 나누기를 할 때
  • 네트워크 연결이 끊겼을 때
  • 사용자가 잘못된 입력을 했을 때
이런 상황이 발생하면 프로그램은 오류를 내고 멈추지만, 예외처리를 사용하면 멈추지 않고 다른 동작을 하도록 만들 수 있음

3️⃣ 예외 처리 문법

1) try–catch

try { // 예외가 발생할 수 있는 코드 } catch (예외타입 e) { // 해당 예외가 발생했을 때 실행되는 코드 }
① 0으로 나누기
try { int result = 10 / 0; } catch (ArithmeticException e) { System.out.println("0으로 나눌 수 없습니다."); }
② 여러 예외 처리
try { int[] arr = {1, 2}; System.out.println(arr[3]); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("배열 인덱스가 잘못되었습니다."); } catch (Exception e) { System.out.println("알 수 없는 오류 발생"); }

3) throws 키워드

메서드에서 예외를 직접 처리하지 않고 호출한 곳으로 예외를 떠넘기는 것
public void readFile() throws IOException { FileReader fr = new FileReader("test.txt"); }
호출하는 쪽에서 다시 try-catch 해야 함.

4️⃣ 교재 예제

예제 8-2. 배열 인덱스 예외 처리 (p.355)

package ex08; public class ArrayError { public static void main(String[] args) { int[] array = { 1, 2, 3, 4, 5 }; int i = 0; for (i = 0; i <= array.length; i++) { System.out.println(array[i] + " "); } } }
notion image
package ex08; public class ArrayError { public static void main(String[] args) { int[] array = { 1, 2, 3, 4, 5 }; int i = 0; try { for (i = 0; i <= array.length; i++) { System.out.println(array[i] + " "); } } catch (Exception e) { System.out.println("인덱스 " + i + "는 사용할 수 없네요!"); } } }
notion image

예제 8-3. 입력 예외 처리 (p.356)

package ex08; public class ExceptionTest3 { public static void main(String[] args) { int num = Integer.parseInt("ABC"); System.out.println(num); } }|
notion image
package ex08; public class ExceptionTest3 { public static void main(String[] args) { try { int num = Integer.parseInt("ABC"); System.out.println(num); } catch (NumberFormatException e) { System.out.println("NumberFormat 예외 발생"); } } }
notion image
 

4. 실습

package ex08; public class Try01 { public static void main(String[] args) { throw new RuntimeException("강제로 예외를 터트림"); } }
notion image
package ex08; public class Try02 { static void start(){ throw new RuntimeException("예외가 발생함"); } public static void main(String[] args) { try { start(); } catch (RuntimeException e){ System.out.println("괜찮아"); } } }
notion image
package ex08; class Service{ static void loginProcess(String username, String password){ if (username.length() < 5){ throw new RuntimeException("username의 길이가 짧아요"); } if (!password.equals("1234")){ throw new RuntimeException("password가 틀렸어요"); } } } // SRP 잘못된 처리를 하는 곳 class Controller{ static void login(String username, String password){ try { Service.loginProcess(username, password); } catch (RuntimeException e) { System.out.println(e.getMessage()); } } } public class Try03 { public static void main(String[] args) { Controller.login("ssar","1234"); } }
notion image
package ex08.ch01; /** * checked exception * unChecked exception */ public class CheckTry { static void m1() throws Exception { throw new Exception("강제로 던진 Checked Exception"); } static void m2(){ throw new RuntimeException("강제로 던진 Unchecked Exception"); } public static void main(String[] args) { try { m1(); } catch (Exception e) { System.out.println(e.getMessage()); } m2(); } }
notion image
package ex08.ch01; import java.io.FileInputStream; import java.io.FileNotFoundException; public class CheckTry02 { // 예상 불가능한 익셉션 코드 (RuntimeException 관련 자식들) static void m1(int n) { try { int result = 10 / n; System.out.println(result); } catch (RuntimeException e) { System.out.println("0"); } } // 예상 가능한 익셉션 코드 (RuntimeException이 아닌 모든 것 / Exception) static void m2() { try { FileInputStream fis = new FileInputStream("파일명"); } catch (FileNotFoundException e) { System.out.println("파일명 못찾았어!! 다시 시도해!!"); } } public static void main(String[] args) { m1(0); m2(); } }
notion image
 

필기 정리

notion image

※ if vs RuntimeException?

notion image
Share article