[Java 개념노트 44] 예외 처리란 무엇인가?
안녕하세요. Java 개념노트 시리즈 마흔네 번째 글입니다.
지난 글에서는 LocalDate, LocalTime, LocalDateTime을 사용해서 날짜와 시간을 다루는 방법을 정리했습니다. 이번 글에서는 프로그램 실행 중 발생할 수 있는 문제를 안전하게 처리하는 예외 처리에 대해 알아보겠습니다.
프로그램은 항상 우리가 예상한 대로만 실행되지 않습니다. 0으로 나누거나, 배열 범위를 벗어나거나, 없는 값을 사용하려고 하면 실행 중 오류가 발생할 수 있습니다. 이런 상황을 그냥 두면 프로그램이 갑자기 종료될 수 있습니다. 예외 처리는 이런 문제 상황을 안전하게 다루기 위한 문법입니다.
1. 예외란?
예외는 프로그램 실행 중 발생하는 예상하지 못한 문제 상황입니다.
예를 들어 숫자를 0으로 나누거나, 배열에 없는 인덱스에 접근하거나, null 값으로 메서드를 호출하면 예외가 발생할 수 있습니다.
쉽게 말하면
예외는 프로그램이 실행되는 도중에 발생하는 문제 상황이고, 예외 처리는 그 문제로 프로그램이 바로 멈추지 않도록 안전하게 처리하는 방법입니다.
2. 오류와 예외의 차이
처음에는 오류와 예외가 비슷하게 느껴질 수 있습니다. 간단히 구분하면 다음과 같습니다.
| 구분 | 의미 | 예시 |
| 컴파일 오류 | 코드 문법이 잘못되어 실행 전부터 막히는 오류입니다. | 세미콜론 누락, 변수 이름 오타 |
| 예외 | 프로그램 실행 중 발생하는 문제 상황입니다. | 0으로 나누기, 배열 범위 초과 |
| 에러 | 프로그램에서 직접 처리하기 어려운 심각한 문제입니다. | 메모리 부족 같은 시스템 문제 |
이번 글에서는 실행 중 발생하는 예외를 중심으로 정리하겠습니다.
3. 예외가 발생하는 코드
먼저 예외가 발생하는 간단한 코드를 보겠습니다.
public class Main {
public static void main(String[] args) {
int result = 10 / 0;
System.out.println(result);
}
}
위 코드는 실행 중 오류가 발생합니다. 정수를 0으로 나눌 수 없기 때문입니다.
Exception in thread "main" java.lang.ArithmeticException: / by zero
ArithmeticException은 산술 연산 중 문제가 발생했을 때 나타나는 예외입니다.
4. 예외가 발생하면 프로그램 흐름은 어떻게 될까?
예외가 처리되지 않으면 프로그램은 예외가 발생한 지점에서 멈춥니다.
public class Main {
public static void main(String[] args) {
System.out.println("프로그램 시작");
int result = 10 / 0;
System.out.println("결과: " + result);
System.out.println("프로그램 종료");
}
}
실행 결과는 다음과 비슷합니다.
프로그램 시작
Exception in thread "main" java.lang.ArithmeticException: / by zero
10 / 0에서 예외가 발생했기 때문에 그 아래의 출력문은 실행되지 않습니다.
주의
예외를 처리하지 않으면 프로그램이 중간에 종료될 수 있습니다. 그래서 문제가 생길 수 있는 코드는 예외 처리를 고려해야 합니다.
5. 예외 처리란?
예외 처리는 실행 중 발생할 수 있는 예외를 잡아서 프로그램이 갑자기 종료되지 않도록 처리하는 것입니다.
자바에서는 주로 try-catch 문을 사용해서 예외를 처리합니다.
try {
예외가 발생할 수 있는 코드;
} catch (예외타입 변수명) {
예외가 발생했을 때 실행할 코드;
}
| 구성 | 역할 |
try |
예외가 발생할 수 있는 코드를 작성합니다. |
catch |
예외가 발생했을 때 처리할 코드를 작성합니다. |
6. try-catch 기본 예제
try-catch를 사용해서 0으로 나누는 예외를 처리해보겠습니다.
public class Main {
public static void main(String[] args) {
System.out.println("프로그램 시작");
try {
int result = 10 / 0;
System.out.println("결과: " + result);
} catch (ArithmeticException e) {
System.out.println("0으로 나눌 수 없습니다.");
}
System.out.println("프로그램 종료");
}
}
실행 결과는 다음과 같습니다.
프로그램 시작
0으로 나눌 수 없습니다.
프로그램 종료
예외가 발생했지만 catch에서 처리했기 때문에 프로그램이 바로 종료되지 않고 마지막 출력문까지 실행되었습니다.
핵심 포인트try 안에서 예외가 발생하면, 해당 예외를 처리할 수 있는 catch 블록으로 이동합니다.
7. try 블록 안의 실행 흐름
try 블록 안에서 예외가 발생하면, 예외가 발생한 줄 아래의 코드는 실행되지 않고 catch로 이동합니다.
public class Main {
public static void main(String[] args) {
try {
System.out.println("try 시작");
int result = 10 / 0;
System.out.println("이 문장은 실행되지 않습니다.");
} catch (ArithmeticException e) {
System.out.println("catch 실행");
}
System.out.println("try-catch 이후 실행");
}
}
실행 결과는 다음과 같습니다.
try 시작
catch 실행
try-catch 이후 실행
int result = 10 / 0;에서 예외가 발생했기 때문에 그 아래 문장은 실행되지 않습니다.
8. 예외 객체 e
catch (ArithmeticException e)에서 e는 발생한 예외 정보를 담고 있는 객체입니다.
이 객체를 사용하면 예외 메시지를 확인할 수 있습니다.
public class Main {
public static void main(String[] args) {
try {
int result = 10 / 0;
} catch (ArithmeticException e) {
System.out.println(e.getMessage());
}
}
}
실행 결과는 다음과 같습니다.
/ by zero
getMessage()는 예외에 담긴 간단한 메시지를 반환합니다.
9. printStackTrace()
printStackTrace()는 예외가 어디에서 발생했는지 자세한 정보를 출력합니다.
public class Main {
public static void main(String[] args) {
try {
int result = 10 / 0;
} catch (ArithmeticException e) {
e.printStackTrace();
}
}
}
실행 결과는 다음과 비슷합니다.
java.lang.ArithmeticException: / by zero
at Main.main(Main.java:4)
printStackTrace()는 예외의 원인을 추적할 때 도움이 됩니다. 다만 사용자에게 그대로 보여주기보다는 개발자가 문제를 확인할 때 주로 사용합니다.
10. ArrayIndexOutOfBoundsException
배열의 범위를 벗어난 인덱스에 접근하면 ArrayIndexOutOfBoundsException이 발생할 수 있습니다.
public class Main {
public static void main(String[] args) {
int[] numbers = {10, 20, 30};
try {
System.out.println(numbers[3]);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("배열 인덱스 범위를 벗어났습니다.");
}
}
}
실행 결과는 다음과 같습니다.
배열 인덱스 범위를 벗어났습니다.
배열 길이가 3이면 사용할 수 있는 인덱스는 0, 1, 2입니다. numbers[3]은 범위를 벗어난 접근입니다.
11. NullPointerException
null 값을 가진 참조변수로 메서드를 호출하면 NullPointerException이 발생할 수 있습니다.
public class Main {
public static void main(String[] args) {
String text = null;
try {
System.out.println(text.length());
} catch (NullPointerException e) {
System.out.println("null 값에서는 메서드를 호출할 수 없습니다.");
}
}
}
실행 결과는 다음과 같습니다.
null 값에서는 메서드를 호출할 수 없습니다.
text는 실제 문자열 객체를 가리키고 있지 않기 때문에 length()를 호출할 수 없습니다.
12. NumberFormatException
숫자로 바꿀 수 없는 문자열을 숫자로 변환하려고 하면 NumberFormatException이 발생할 수 있습니다.
public class Main {
public static void main(String[] args) {
String text = "Java";
try {
int number = Integer.parseInt(text);
System.out.println(number);
} catch (NumberFormatException e) {
System.out.println("숫자로 변환할 수 없는 문자열입니다.");
}
}
}
실행 결과는 다음과 같습니다.
숫자로 변환할 수 없는 문자열입니다.
"Java"는 숫자 형태가 아니므로 정수로 변환할 수 없습니다.
13. 여러 catch 사용하기
예외 종류가 여러 개 발생할 수 있다면 catch를 여러 개 작성할 수 있습니다.
public class Main {
public static void main(String[] args) {
try {
String text = "Java";
int number = Integer.parseInt(text);
System.out.println(10 / number);
} catch (NumberFormatException e) {
System.out.println("숫자 변환 오류입니다.");
} catch (ArithmeticException e) {
System.out.println("산술 연산 오류입니다.");
}
}
}
실행 결과는 다음과 같습니다.
숫자 변환 오류입니다.
먼저 Integer.parseInt(text)에서 NumberFormatException이 발생했기 때문에 첫 번째 catch가 실행됩니다.
14. catch 순서 주의하기
여러 catch를 사용할 때는 더 구체적인 예외를 먼저 작성하고, 더 넓은 예외는 나중에 작성해야 합니다.
올바른 예
try {
int result = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("산술 연산 오류");
} catch (Exception e) {
System.out.println("기타 예외");
}
잘못된 예
try {
int result = 10 / 0;
} catch (Exception e) {
System.out.println("기타 예외");
} catch (ArithmeticException e) {
System.out.println("산술 연산 오류");
}
Exception은 많은 예외의 부모 타입입니다. 부모 타입을 먼저 catch하면 뒤에 있는 구체적인 예외 catch는 도달하기 어려워져 오류가 발생할 수 있습니다.
주의
여러 catch를 사용할 때는 구체적인 예외를 먼저, 넓은 예외를 나중에 작성합니다.
15. Exception으로 한 번에 처리하기
Exception은 여러 예외의 부모 클래스입니다. 그래서 다양한 예외를 한 번에 처리할 수 있습니다.
public class Main {
public static void main(String[] args) {
try {
int result = 10 / 0;
} catch (Exception e) {
System.out.println("예외가 발생했습니다.");
}
}
}
실행 결과는 다음과 같습니다.
예외가 발생했습니다.
다만 모든 예외를 무조건 Exception으로만 처리하면 어떤 문제가 발생했는지 구분하기 어려울 수 있습니다. 가능하면 필요한 예외 타입을 구체적으로 처리하는 것이 좋습니다.
16. finally란?
finally는 예외 발생 여부와 관계없이 마지막에 실행되는 블록입니다.
try {
예외가 발생할 수 있는 코드;
} catch (예외타입 e) {
예외 처리 코드;
} finally {
항상 실행할 코드;
}
finally는 파일 닫기, 연결 종료, 마무리 작업처럼 반드시 실행해야 하는 코드를 넣을 때 사용할 수 있습니다.
17. finally 예제
예외가 발생해도 finally 블록은 실행됩니다.
public class Main {
public static void main(String[] args) {
try {
System.out.println("try 실행");
int result = 10 / 0;
System.out.println(result);
} catch (ArithmeticException e) {
System.out.println("catch 실행");
} finally {
System.out.println("finally 실행");
}
System.out.println("프로그램 종료");
}
}
실행 결과는 다음과 같습니다.
try 실행
catch 실행
finally 실행
프로그램 종료
예외가 발생해서 catch가 실행되었지만, finally도 마지막에 실행되었습니다.
18. 예외가 발생하지 않아도 finally는 실행된다
예외가 발생하지 않아도 finally는 실행됩니다.
public class Main {
public static void main(String[] args) {
try {
System.out.println("try 실행");
int result = 10 / 2;
System.out.println("결과: " + result);
} catch (ArithmeticException e) {
System.out.println("catch 실행");
} finally {
System.out.println("finally 실행");
}
}
}
실행 결과는 다음과 같습니다.
try 실행
결과: 5
finally 실행
예외가 발생하지 않았기 때문에 catch는 실행되지 않았지만, finally는 실행되었습니다.
19. try-catch-finally 흐름 정리
예외 처리 흐름을 정리하면 다음과 같습니다.
예외가 발생하지 않는 경우
try 실행
↓
catch 건너뜀
↓
finally 실행
↓
다음 코드 실행
예외가 발생하는 경우
try 실행 중 예외 발생
↓
해당 catch 실행
↓
finally 실행
↓
다음 코드 실행
20. 예외 처리 전체 예제
이번에는 문자열을 숫자로 바꾸고 나눗셈을 수행하는 전체 예제를 보겠습니다.
public class Main {
public static void main(String[] args) {
String text = "0";
try {
int number = Integer.parseInt(text);
int result = 100 / number;
System.out.println("결과: " + result);
} catch (NumberFormatException e) {
System.out.println("숫자로 변환할 수 없습니다.");
} catch (ArithmeticException e) {
System.out.println("0으로 나눌 수 없습니다.");
} finally {
System.out.println("계산을 종료합니다.");
}
}
}
실행 결과는 다음과 같습니다.
0으로 나눌 수 없습니다.
계산을 종료합니다.
"0"은 숫자로 변환될 수 있지만, 100 / 0에서 산술 예외가 발생했습니다. 그래서 ArithmeticException을 처리하는 catch가 실행되었습니다.
21. 예외 처리를 사용할 때 생각할 점
예외 처리는 단순히 오류 메시지를 숨기는 문법이 아닙니다. 문제가 발생했을 때 프로그램이 어떻게 안전하게 대응할지 정하는 흐름입니다.
- 예외가 발생할 수 있는 위치를 먼저 파악합니다.
- 어떤 예외가 발생할 수 있는지 생각합니다.
- 사용자에게 보여줄 메시지를 정리합니다.
- 프로그램이 계속 실행되어야 하는지 중단되어야 하는지 결정합니다.
- 마무리 작업이 필요하면 finally를 사용합니다.
22. 예외 처리 사용 시 자주 하는 실수
예외 처리를 처음 배울 때는 아래와 같은 실수를 자주 합니다.
| 실수 | 문제점 | 해결 방법 |
모든 예외를 무조건 Exception으로만 처리 |
예외 원인을 구분하기 어려움 | 가능하면 구체적인 예외 타입 사용 |
| catch 순서 잘못 작성 | 구체적인 catch가 실행될 수 없음 | 구체적인 예외 먼저, 넓은 예외 나중에 작성 |
| catch 블록을 비워둠 | 문제가 발생해도 원인을 알기 어려움 | 메시지 출력이나 적절한 처리 작성 |
| try 범위를 너무 크게 잡음 | 어디서 문제가 생겼는지 파악하기 어려움 | 예외 가능성이 있는 부분 중심으로 작성 |
| 예외 처리를 오류 숨기기로 사용 | 잘못된 로직이 그대로 남을 수 있음 | 원인 해결과 안전한 흐름을 함께 고려 |
23. 직접 연습해보기
아래 코드를 직접 작성하고 실행해보세요.
public class Main {
public static void main(String[] args) {
String[] inputs = {"10", "0", "Java"};
for (int i = 0; i < inputs.length; i++) {
try {
int number = Integer.parseInt(inputs[i]);
int result = 100 / number;
System.out.println(inputs[i] + " 계산 결과: " + result);
} catch (NumberFormatException e) {
System.out.println(inputs[i] + "은 숫자가 아닙니다.");
} catch (ArithmeticException e) {
System.out.println(inputs[i] + "으로는 나눌 수 없습니다.");
} finally {
System.out.println("처리 완료");
}
System.out.println();
}
}
}
실행 결과는 다음과 같습니다.
10 계산 결과: 10
처리 완료
0으로는 나눌 수 없습니다.
처리 완료
Java은 숫자가 아닙니다.
처리 완료
24. 이번 글 정리
이번 글에서는 프로그램 실행 중 발생할 수 있는 문제를 처리하는 예외 처리에 대해 정리했습니다. 핵심 내용은 다음과 같습니다.
- 예외는 프로그램 실행 중 발생하는 문제 상황이다.
- 예외를 처리하지 않으면 프로그램이 중간에 종료될 수 있다.
- 예외 처리는 주로
try-catch문으로 처리한다. try에는 예외가 발생할 수 있는 코드를 작성한다.catch에는 예외가 발생했을 때 처리할 코드를 작성한다.- 예외가 발생하면 try 블록의 남은 코드는 건너뛰고 catch로 이동한다.
getMessage()로 예외 메시지를 확인할 수 있다.printStackTrace()로 예외 발생 위치를 확인할 수 있다.- 여러 예외가 발생할 수 있다면 catch를 여러 개 작성할 수 있다.
- 여러 catch를 사용할 때는 구체적인 예외를 먼저 작성해야 한다.
finally는 예외 발생 여부와 관계없이 실행된다.- 예외 처리는 오류를 숨기는 것이 아니라 안전한 흐름을 만드는 것이다.
한 줄 요약
예외 처리는 프로그램 실행 중 문제가 발생해도 프로그램이 갑자기 종료되지 않도록 try-catch-finally로 안전하게 처리하는 문법입니다.
다음 글 예고
다음 글에서는 [Java 개념노트 45] throws와 throw 이해하기라는 주제로 예외를 호출한 쪽으로 넘기거나 직접 발생시키는 방법을 정리해보겠습니다.
GWDEVELBlog Java 개념노트 시리즈

'Computer Science > Java' 카테고리의 다른 글
| [Java ] 개념노트 46 사용자 정의 예외 이해하기 (0) | 2026.06.16 |
|---|---|
| [Java] 개념노트 45 throws와 throw 이해하기 (0) | 2026.06.16 |
| [Java ] 개념노트 43 날짜와 시간 API 이해하기 (0) | 2026.06.15 |
| [Java ] 개념노트 42 Random 클래스 이해하기 (0) | 2026.06.15 |
| [Java ] 개념노트 41 Math 클래스 이해하기 (0) | 2026.06.15 |