이 게시물은 2025-2026 성공회대학교 GDGoC Backend 스터디 세션을 위해 작성되었습니다.
자바에서 발생하는 문제는 크게 두 가지로 나눌 수 있다.
프로그램을 실행하기 전, 컴파일 과정에서 발생하는 오류이다.
자바 컴파일러가 소스코드를 바이트코드로 번역하려고 할 때 문법이나 규칙이 어긋나면 발생한다.
ex) 세미콜론(;) 빠짐, 잘못된 자료형 사용 등
컴파일 에러가 있으면 프로그램을 실행조차 할 수 없기 때문에 디버깅이 용이하다. → 상대적으로 좋은 오류이다.
프로그램이 컴파일에는 성공했지만, 실행 도중 발생하는 오류이다.
코드 문법상 문제는 없지만 실행 환경에서 문제가 생기는 경우 발생한다.
런타임 에러는 실행 도중에야 문제가 드러나기 때문에 재현하기 까다롭고 디버깅이 어렵다.
런타임에 생기는 오류는 에러(Error), 예외(Exception) 2가지로 분류할 수 있다.

try-catch 또는 throws로 처리할 수 있다.public class Scanner1 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("문자열을 입력하세요 :");
String str = scanner.nextLine();
System.out.println("입력한 문자열: " + str);
System.out.print("정수를 입력하세요 :");
int intValue = scanner.nextInt();
System.out.println("입력한 정수: " + intValue);
System.out.print("실수를 입력하세요 :");
double doubleValue = scanner.nextDouble();
System.out.println("입력한 실수: " + doubleValue);
}
}
문자열을 입력하세요 : hello
입력한 문자열 : hello
정수를 입력하세요 : 오백
Exception in thread "main" java.util.InputMismatchException
at java.base/java.util.Scanner.throwFor(Scanner.java:939)
…
사용자가 정수를 입력해야 하는데 문자열을 입력해 InputMismatchException이 발생했다.
try-catch 문을 이용해 코드를 리팩토링해 보자
public class Scanner1 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
try {
System.out.print("문자열을 입력하세요: ");
String str = scanner.nextLine();
System.out.println("입력한 문자열: " + str);
System.out.print("정수를 입력하세요: ");
int intValue = scanner.nextInt();
System.out.println("입력한 정수: " + intValue);
System.out.print("실수를 입력하세요: ");
double doubleValue = scanner.nextDouble();
System.out.println("입력한 실수: " + doubleValue);
} catch (Exception e) {
System.out.println("잘못된 입력입니다. 다시 입력해주세요.");
}
}
}
문자열을 입력하세요 : 안녕하세요
입력한 문자열 : 안녕하세요
정수를 입력하세요 : 이백
잘못된 입력입니다. 다시 입력해주세요.
상단의 try-catch 문에서 Exception 타입 변수 e를 사용한 것을 보았다.
자바에서 다루는 모든 예외는 Exception 혹은 그 하위 클래스에서 처리한다.
Exception 클래스는 다시 RuntimeException 과 그 외의 자식 클래스 그룹으로 나뉘게 된다.
| Checked Exception | Unchecked Exception | |
|---|---|---|
| 처리 여부 | 반드시 예외를 처리해야 함 | 명시적인 처리를 하지 않아도 됨 |
| 확인 시점 | 컴파일 단계(실행 불가능) | 런타임 단계(실행은 가능) |
| 예외 종류 | FileNotFoundException, DataFormatException 등 | IndexOutOfBoundsException, NullPointerException 등 |
두 예외의 핵심적인 차이는 “반드시 예외 처리를 해야 하는가?” 이다.
Checked Exception은 컴파일 단계에서 체크하기 때문에 예외 처리를 하지 않는다면 컴파일이 되지 않는다.
try-catch 문을 직역하면, “시도해보고-잡는다” 라는 뜻이다.
잡는 놈이 있으면 던지는 놈도 있지 않을까?
그렇다. 자바는 메서드 안에서 발생한 예외를 나를 호출한 바깥의 메서드에게 던질 수 있다.
public class ThrowExample {
public static void main(String[] args) {
try {
int result = divide(10, 0);
System.out.println("결과: " + result);
} catch (ArithmeticException e) {
System.out.println("예외가 발생했습니다. 원인: " + e.getMessage());
}
}
public static int divide(int a, int b) throws ArithmeticException {
if (b == 0) {
throw new ArithmeticException("0으로 나눌 수 없습니다!");
}
return a / b;
}
}
이와 같이 throw를 이용해 나를 호출한 메서드에게 예외를 던져 호출부에서 예외를 처리하도록 할 수 있다.
이렇게 예외를 다른 곳으로 던지는 것은 코드 가독성, 재사용등, 책임 분배 등의 측면에서 추후에 중요해 진다.