자바 예외처리 프로그래밍 · 2015-01-21 · java exception handling programming from...

21
자바 예외처리 프로그래밍 Java Exception Handling Programming from Yongwoo’s Park 1 자바 예외처리 프로그래밍 (2001 3 작성) from Yongwoo’s Park

Upload: others

Post on 26-Jul-2020

1 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 자바 예외처리 프로그래밍 · 2015-01-21 · Java Exception Handling Programming from Yongwoo’s Park 4 자바 예외처리 프로그래밍 from Yongwoo’s Park 1. 예외처리(Exception

자바 예외처리 프로그래밍

Java Exception Handling Programming from Yongwoo’s Park 1

자바 예외처리 프로그래밍 (2001 년 3 월 작성)

from Yongwoo’s Park

Page 2: 자바 예외처리 프로그래밍 · 2015-01-21 · Java Exception Handling Programming from Yongwoo’s Park 4 자바 예외처리 프로그래밍 from Yongwoo’s Park 1. 예외처리(Exception

자바 예외처리 프로그래밍

Java Exception Handling Programming from Yongwoo’s Park 2

Page 3: 자바 예외처리 프로그래밍 · 2015-01-21 · Java Exception Handling Programming from Yongwoo’s Park 4 자바 예외처리 프로그래밍 from Yongwoo’s Park 1. 예외처리(Exception

자바 예외처리 프로그래밍

Java Exception Handling Programming from Yongwoo’s Park 3

목 차

1. 예외처리 ........................................................................................................................................................................... 4

1.1 예외와 예외처리 ..........................................................................................................................................................4

1.1.1 예외와 예외처리 방법 ................................................................................................................................... 4

1.1.2 try/catch 블록 ...................................................................................................................................................... 5

1.1.3 try/catch/finally 블록 ......................................................................................................................................... 9

1.1.4 중첩 예외처리 블록 ...................................................................................................................................... 11

1.2 예외의 분류 .................................................................................................................................................................13

1.2.1 예외의 분류 .....................................................................................................................................................13

1.3 메소드에서 예외 던지기 .........................................................................................................................................19

1.3.1 메소드에서 예외 던지기.............................................................................................................................19

Page 4: 자바 예외처리 프로그래밍 · 2015-01-21 · Java Exception Handling Programming from Yongwoo’s Park 4 자바 예외처리 프로그래밍 from Yongwoo’s Park 1. 예외처리(Exception

자바 예외처리 프로그래밍

Java Exception Handling Programming from Yongwoo’s Park 4

자바 예외처리 프로그래밍

from Yongwoo’s Park

1. 예외처리( E x c e p t i o n H a n d l i n g )

1.1 예외( E x c e p t i o n )와 예외처리

프로그램이 실행되는 동안 예기치 못한 여러 가지 에러들이 발생할 수 있다. 파일을 열려고 하는

데 파일이 없다거나, A 드라이브에 있는 파일들의 리스트를 보려고 하는데 A 드라이브에 디스켓이

없다거나 , 또는 프로그램을 잘못 작성하여 0 으로 나누게 되어 ‘Divide by 0’라는 에러가 발생하면

서 프로그램이 정지된다거나 하는 등의 프로그램을 정지시키거나 시스템을 정지시킬 수 있는 에

러들이 흔히 발생할 수 있다.

이러한 에러들 중에서 프로그램 상에서 에러가 발생했다는 것을 감지할 수 있고, 프로그램 상에서

처리할 수 있는 에러를 자바에서는 예외라고 한다 . 다시 말해서, 자바에서는 프로그램 상에서 발

생할 수 있는 에러들에 대해서 예외로서 명세하고 있고, 어떤 경우에 어떤 예외가 발생할 수 있으

므로 예외가 발생했을 때 자바 프로그램에서는 어떻게 해야 한다는 것을 모두 명세해 주고 있다.

이렇게 프로그램 상에서 예외가 발생하는 것을 감지하고, 발생한 예외를 처리하는 것을 예외 처리

라고 한다.

1.1.1 예외와 예외처리 방법

자바에서는 예외가 발생하는지 테스트 할 수 있고 , 예외가 발생했을 경우 프로그램 상에서 처리할

수 있도록 하기 위해 예외의 종류를 정의하고, 프로그램 상에서 예외를 처리할 수 있도록 자바 언

어 수준에서 예외처리 구문들을 제공해 주고 있다 . 이렇게 예외가 발생했더라도 프로그램이 비정

상적으로 종료되지 않고, 예외를 처리하게 함으로서 좀 더 안정적이고 신뢰성 있는 프로그램을 작

성할 수 있도록 해 주는 것이다.

자바에서 예외를 처리하는 방법에는 다음과 같은 두 가지 방법이 있다.

l try/catch/finally 구문을 사용하여 예외가 발생한 곳에서 직접 처리한다.

l 발생한 예외를 자신을 호출한 메소드로 throw 문을 이용하여 던진다.

만약, 자바 어플리케이션을 작성한다고 했을 경우 , main 메소드가 아닌 다른 메소드에서 예외가 발

생하였다면 main 메소드 또는 다른 메소드에서 던져진 예외를 받게 될 것이고 , main 메소드에서

예외가 발생하였다면 자바 가상머신이 던져진 예외를 받아 처리하게 될 것이다. 왜냐하면 , main 메

Page 5: 자바 예외처리 프로그래밍 · 2015-01-21 · Java Exception Handling Programming from Yongwoo’s Park 4 자바 예외처리 프로그래밍 from Yongwoo’s Park 1. 예외처리(Exception

자바 예외처리 프로그래밍

Java Exception Handling Programming from Yongwoo’s Park 5

소드를 호출하는 것은 자바 가상머신이기 때문입니다. 다시 말해서, 예외를 처리하지 않을 경우

결국은 자바 가상머신에서 예외를 처리하게 된다는 것이다.

1.1.2 try/catch 블록

자바 프로그램 상에서 예외를 처리할 수 있도록 자바 언어 차원에서 예외처리 구문을 제공해 주

고 있는데, 가장 기본적인 예외처리 구문은 다음과 같은 try/catch 구문이다.

try {

// 예외를 발생시킬 가능성이 있는 문장

} catch(ExceptionType-1 exceptionName-n) {

// 예외가 발생했을 때, 예외를 처리하기 위한 문장

} catch(ExceptionType-2 exceptionName-2) {

// 두 개 이상의 예외가 발생했을 경우,

// 두 번째 예외가 발생했을 때, 예외를 처리하기 위한 문장

} catch(ExceptionType-n exceptionName-n) {

// 두 번째 예외를 처리하기 위한 문장

}

try/catch 구문의 예외처리 방법은 간단하니다. 먼저 , 예외가 발생할 여지가 있는 문장들을 try 블록

내에 위치시킨다 . 그리고, 예외가 발생했을 경우 이를 처리하기 위한 문장들을 catch 블록 내에 위

치시킨다. try 블록과 catch 블록의 기본 구조는 다음과 같다.

l try 블록: try 블록 내에는 예외를 발생시킬 가능성이 있는 문장들을 넣는다. 자바

가상머신은 try 블록 내의 문장을 수행하다가 예외가 발생하면, 발생한 예외를 던진다.

이렇게 던져진 예외는 해당 예외를 잡도록 설정된 catch 블록에서 잡히게 된다. 이렇게

예외가 잡히게 되면 catch 블록 내의 예외처리 문장들이 실행된다. 그러나 , try 블록 내의

문장을 수행할 때 아무런 예외도 발생하지 않는다면 , 이 try 블록과 연결된 catch 블록을

수행할 필요가 없으므로 건너띄게 된다. 왜냐하면, catch 블록의 목적은 예외가 발생했을

경우, 이 예외를 처리하기 위한 것이기 때문이다 . 이 때 , try 블록 내에 위치한 문장들은

하나의 예외를 발생시킬 수도 있고 , 아니면 여러 개의 예외를 발생시킬 수도 있다.

따라서, catch 블록은 이러한 모든 예외를 처리할 수 있도록 해 주어야 한다.

Page 6: 자바 예외처리 프로그래밍 · 2015-01-21 · Java Exception Handling Programming from Yongwoo’s Park 4 자바 예외처리 프로그래밍 from Yongwoo’s Park 1. 예외처리(Exception

자바 예외처리 프로그래밍

Java Exception Handling Programming from Yongwoo’s Park 6

l catch 블록: try 블록은 항상 catch 블록이나 finally 블록과 함께 사용되어야 한다 . catch

블록은 try 블록 내에서 예외가 발생하면 , 이 예외를 잡아서 에외처리하는 부분이다. catch

블록은 try 블록 다음에 위치해야 하며, 그 사이에는 다른 어떠한 문장도 쓸 수 없다.

하나의 try 블록은 여러 개의 catch 블록과 같이 사용될 수 있고 , 이렇게 함으로써 try

블록 내에서 발생할 수 있는 모든 예외를 처리할 수 있도록 하고 있다 . 이 때 , 각 catch

블록은 매개변수를 통해서 처리할 예외의 형식을 지정하게 된다. 다시 말해서, catch

블록은 매개변수를 통해서 처리할 예외를 넘겨받게 된다.

그림 1에서는 try/catch 구문을 이용하여 간단하게 예외처리 작업을 하는 예를 보여주고 있다. 그림

1에서 보여주고 있는 소스 코드 중에서 Class.forName( … ) 메소드를 실행할 경우,

ClassNotFoundException 예외가 발생할 가능성이 있다 . 그리고, DriverManager.getConnection(…) 메소

드를 실행할 때, SQLException 예외가 발생할 수 있다. 따라서, 다음과 같이 예외가 발생할 가능성

이 있는 문장들에 대해, 먼저 try 블록으로 묶어주고, 각각의 발생할 가능성이 있는 예외를 잡아서

처리하기 위한 catch 블록을 설정해 주어야 한다.

Connection conn = null;try {

Class. forName("sun.jdbc.odbc.JdbcOdbcDriver");conn = DriverManager.getConnection("jdbc:odbc:Guestbook", "sa", "");

} catch(SQLException e) {e.printStackTrace();

} catch(ClassNotFoundException e) {e.printStackTrace();

} 정상적인 프로그램 실행에외처리

그림 1. 예외처리 기본구문

자바 가상머신이 그림 1에서 보여주고 있는 소스 코드 중에서 try 블록을 수행하면서, 아무런 예

외도 발생하지 않을 경우, 아무런 예외도 발생하지 않았으므로 두 개의 catch 블록은 수행되지 않

을 것이다.

만약, 자바 가상머신이 그림 1에서 보여주고 있는 것과 같은 프로그램을 수행하던 중, JDBC 드라

이버에 해당하는 sun.jdbc.odbc.JdbcOdbcDriver 클래스를 찾지 못할 경우 그림 2에서 보여주는 것과

같이 ClassNotFoundException 예외가 발생하게 된다. 이 때, 발생한 예외는 해당 예외를 잡아서 처

리할 catch 블록을 만날 때까지 던져지게 된다. 그림 2을 살펴보면, 발생한 ClassNotFoundException

예외는 던져져서 해당 catch 블록 내에서 예외처리 되고 try/catch 구문 다음부터 계속 실행되게 된

다.

이 때, 예외처리의 가장 간단한 형태는 아무런 작업도 하지 않는 것이고, 그 다음 간단한 예외처

Page 7: 자바 예외처리 프로그래밍 · 2015-01-21 · Java Exception Handling Programming from Yongwoo’s Park 4 자바 예외처리 프로그래밍 from Yongwoo’s Park 1. 예외처리(Exception

자바 예외처리 프로그래밍

Java Exception Handling Programming from Yongwoo’s Park 7

리 작업은 System.out.println(“Exception: “ + e) 문장과 같이 표준 출력에 예외 메시지를 출력하거나,

또는 그림 2에서와 같이 e.printStackTrace() 문장을 이용하여 스택 덤프를 표준 출력 장치에 출력하

는 것이다.

Connection conn = null;try {

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");conn = DriverManager.getConnection("jdbc:odbc:Guestbook", "sa", "");

} catch(SQLException e) {e.printStackTrace();

} catch(ClassNotFoundException e) {e.printStackTrace();

}

X

정상적인 프로그램 실행에외처리

그림 2. ClassNotFoundException 예외가 발생한 경우

또는, 자바 가상머신이 그림 1에서 보여주고 있는 것과 같은 프로그램을 수행하던 중, JDBC 드라

이버를 정상적으로 로딩한 후 , 다음 문장에서 데이터베이스에 대한 연결을 설정하던 중 예외가 발

생했을 경우, 그림 3에서 보여주는 것과 같이 SQLException 예외가 발생하게 된다. 이 때 , 발생한

예외는 해당 예외를 잡아서 처리할 catch 블록을 만날 때까지 던져지게 된다 . 예외가 발생했을 때

해당 예외를 처리하기 위한 catch 블록을 모두 실행하였다면, 프로그램은 해당 try/catch 구문 다음

부터 계속 실행되게 된다.

Connection conn = null;try {

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");conn = DriverManager.getConnection("jdbc:odbc:Guestbook", "sa", "");

} catch(SQLException e) {e.printStackTrace();

} catch(ClassNotFoundException e) {e.printStackTrace();

}

X

정상적인 프로그램 실행에외처리

그림 3. SQLException 예외가 발생한 경우

이 때, catch 블록을 사용할 때 주의해야 할 사항이 있는데, 예외처리 블록인 catch 블록을 위치시

킬 때 상위자료형과 하위자료형의 관계를 따져 , 다음에서 보여주는 것과 같이 하위자료형에 해당

하는 예외를 처리하는 catch 블록을 앞에 위치시켜야 한다.

Page 8: 자바 예외처리 프로그래밍 · 2015-01-21 · Java Exception Handling Programming from Yongwoo’s Park 4 자바 예외처리 프로그래밍 from Yongwoo’s Park 1. 예외처리(Exception

자바 예외처리 프로그래밍

Java Exception Handling Programming from Yongwoo’s Park 8

만약, 그림 4에서와 같이 catch 블록을 배치하였을 경우, try 블록 내에서 예외가 발생하지 않는다

면 상관없겠지만, try 블록을 수행하던 중 JDBC 드라이버에 해당하는 sun.jdbc.odbc.JdbcOdbcDriver

클래스를 찾지 못할 경우 ClassNotFoundException 예외가 발생하게 된다 . 이 때,

ClassNotFoundException 예외가 발생 위치에서 던져져서 catch 블록으로 향하지만,

ClassNotFoundException 예외를 처리하기 위해 설정한 catch 블록까지 가지 못하고, 중간에

Exception 처리를 위해 설정된 catch 블록에서 잡혀 예외처리 된다.

Connection conn = null;try {

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");conn = DriverManager.getConnection("jdbc:odbc:Guestbook", "sa", "");

} catch(Exception e) {e.printStackTrace();

} catch(SQLException e) {e.printStackTrace();

} catch(ClassNotFoundException e) {e.printStackTrace();

} 정상적인 프로그램 실행에외처리

X

그림 4. 잘못된 catch 블록 배치

따라서, try 블록 내에서 ClassNotFoundException 예외가 발생했더라도, 예외처리의 흐름은 그림 4에

서 보여주는 것과 같은 예외처리 흐름을 갖게 된다 . 왜냐하면 , 자바에서는 상위자료형을 이용하여

하위자료형을 가리킬 수 있기 때문이다. 따라서 , 상위자료형에 해당하는 예외를 처리하기 위한

catch 블록이 앞에 오고, 하위자료형에 해당하는 예외를 처리하기 위한 catch 블록이 뒤에 오게 될

경우, 앞의 catch 블록에서 자신이 처리할 예외는 물론 , 하위자료형에 해당하는 예외도 가리킬 수

있으므로 자신이 처리하게 되는 것이다.

그러므로 , try 블록에서 발생할 수 있는 여러 개의 예외를 처리하기 위한 catch 블록을 여러 개 둘

경우에는 반드시 그림 5에서 보여주는 것과 같이 하위 자료형에 해당하는 예외를 처리하기 위한

catch 블록을 상위자료형에 해당하는 예외를 처리하기 위한 catch 블록보다 앞에 두어야 한다.

Page 9: 자바 예외처리 프로그래밍 · 2015-01-21 · Java Exception Handling Programming from Yongwoo’s Park 4 자바 예외처리 프로그래밍 from Yongwoo’s Park 1. 예외처리(Exception

자바 예외처리 프로그래밍

Java Exception Handling Programming from Yongwoo’s Park 9

Connection conn = null;try {

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");conn = DriverManager.getConnection("jdbc:odbc:Guestbook", "sa", "");

} catch(SQLException e) {e.printStackTrace();

} catch(ClassNotFoundException e) {e.printStackTrace();

} catch(Exception e) {e.printStackTrace();

} 정상적인 프로그램 실행에외처리

X

그림 5. 올바른 catch 블록 배치

1.1.3 try/catch/finally 블록

try/catch 구문과 함께 선택적으로 사용될 수 있는 구문으로 finally 구문이 있다. try/catch 블록에서

예외가 발생하거나 발생하지 않더라도 반드시 실행해야 하는 문장들이 있을 때, 바로 finally 블록

내에 위치시키게 된다 . finally 블록은 try/catch 블록의 제어가 끝난 후에 반드시 처리해야 할 마무

리 작업들을 처리하는 블록이므로, try 블록이나 catch 블록 바로 뒤에 위치해야 하며 그 사이에는

어떠한 것도 올 수 없다.

finally 블록은 예외 발생 시 반환되지 않고 종료되어 버린 시스템 자원(resources)을 반드시 반환하

도록 해야 한다는 필요성 때문에 만들어진 것으로써 , 주로 자료구조 및 시스템 자원을 반환하는

코드가 위치하게 된다. 또는 , 데이터베이스 연결을 닫기 위해 사용되기도 한다. 이러한 , try 블록,

catch 블록, 그리고 finally 블록의 기본 구조는 다음과 같다.

try {

// 예외를 발생시킬 가능성이 있는 문장

} catch(ExceptionType-1 exceptionName-n) {

// 예외가 발생했을 때, 예외를 처리하기 위한 문장

} catch(ExceptionType-2 exceptionName-2) {

// 두 개 이상의 예외가 발생했을 경우,

// 두 번째 예외가 발생했을 때, 예외를 처리하기 위한 문장

} catch(ExceptionType-n exceptionName-n) {

// 두 번째 예외를 처리하기 위한 문장

Page 10: 자바 예외처리 프로그래밍 · 2015-01-21 · Java Exception Handling Programming from Yongwoo’s Park 4 자바 예외처리 프로그래밍 from Yongwoo’s Park 1. 예외처리(Exception

자바 예외처리 프로그래밍

Java Exception Handling Programming from Yongwoo’s Park 10

} finally {

// try 블록 내에서 예외가 발생하던 하지 않던

// 반드시 수행해야 할 문장

}

만약, JDBC 프로그래밍을 해야 한다고 하자. 필요할 때마다 데이터베이스에 대한 연결을 유지하기

위해 Connection 객체를 생성하여 사용해야 한다고 할 때, 데이터베이스 작업을 모두 마친 후에는

생성했던 Connection 객체의 close() 메소드를 호출함으로써 데이터베이스에 대한 연결을 반드시 닫

아 주어야 한다.

이 때 , 데이터베이스에 데이터를 삽입하는 쿼리를 실행하는 중에 예외가 발생한다는 어떻게 할 것

인가? 물론, 데이터베이스에 데이터를 삽입하는 쿼리를 실행할 때 아무런 예외도 발생하지 않는다

면 Connection 객체의 close() 메소드를 호출함으로써 데이터베이스에 대한 연결을 닫아 줄 수 있지

만, 예외가 발생하면 그 작업이 어려워 질 수도 있다 . 이렇게 try 블록 내에서 예외가 발생하든지,

또는 발생하지 않든지 해 주어야 할 작업이 있을 경우, finally 블록을 이용할 수 있다.

자바 가상머신이 그림 6에서 보여주고 있는 프로그램의 try 블록 내의 문장들을 실행할 때 , try 블

록 내의 모든 문장들이 정상적으로 수행되었다 하더라도 , 반드시 try 블록과 연결된 finally 블록을

수행하게 된다. 이 때 , finally 블록 내에서 conn.close() 문장을 수행하게 되므로 , 데이터베이스에 대

한 연결을 닫아 줄 수 있다.

Connection conn = ConnectionPool.createConnection();PreparedStatement pstmt = null;try {

String query = "INSERT INTO x (a, b, c) VALUES (?, ?, ?)";pstmt = conn.prepareStatement(query);...pstmt .executeUpdate();

} catch(SQLException e) {e.printStackTrace();

} finally {conn.close();

} 정상적인 프로그램 실행에외처리

그림 6. 예외가 발생하지 않았을 경우의 프로그램 제어 흐름

만약, 자바 가상머신이 그림 6에서 보여주고 있는 프로그램의 try 블록 내의 문장들을 실행할 때,

그림 7에서 보여주는 것과 같이 conn.prepareStatement( … ) 메소드에서 예외가 발생했다고 하자. 이

때, SQLException 예외가 던져지고 , 이 예외는 SQLException 예외를 처리하기 위해 설정된 catch 블

록 내에서 예외처리 될 것이다 . catch 블록 내의 모든 문장들이 실행되면 , 마지막으로 catch 블록과

연결된 finally 블록으로 이동하여 finally 블록을 실행하게 된다.

Page 11: 자바 예외처리 프로그래밍 · 2015-01-21 · Java Exception Handling Programming from Yongwoo’s Park 4 자바 예외처리 프로그래밍 from Yongwoo’s Park 1. 예외처리(Exception

자바 예외처리 프로그래밍

Java Exception Handling Programming from Yongwoo’s Park 11

Connection conn = ConnectionPool .createConnection();PreparedStatement pstmt = null;try {

String query = "INSERT INTO x (a, b, c) VALUES (?, ?, ?)";pstmt = conn.prepareStatement(query);...pstmt.executeUpdate();

} catch(SQLException e) {e.printStackTrace();

} finally {conn.close();

}

pstmt = conn.prepareStatement(query);

정상적인 프로그램 실행에외처리

X

그림 7. 예외가 발생했을 경우의 프로그램 제어 흐름

1.1.4 중첩 예외처리 블록

예외처리를 위한 try/catch 블록은 중첩하여 사용할 수 있다. 다시 말해서, try 블록 내에서 try/catch

블록을 사용할 수 있고, 또는 catch 블록 내에서 try/catch 블록을 사용할 수 있다는 것이다. 물론,

try 블록 내에서 try/catch/finally 블록을 사용할 수 있고, 마찬가지로 finally 블록 내에서

try/catch/finally 블록을 사용할 수 있다는 것이다.

Connection conn = ConnectionPool.createConnection(); PreparedStatement pstmt = null; try { conn.setAutoCommit(false); String query = "INSERT INTO x (a, b, c) VALUES (?, ?, ?)"; pstmt = conn.prepareStatement(query); while(...) { ... if(pstmt.executeUpdate() < 1) { throw new SQLException("Insert failed"); } } conn.commit(); } catch(SQLException e) { e.printStackTrace(); try { conn.rollback(); } catch(SQLException e1) { e1.printStackTrace(); } } finally {

Page 12: 자바 예외처리 프로그래밍 · 2015-01-21 · Java Exception Handling Programming from Yongwoo’s Park 4 자바 예외처리 프로그래밍 from Yongwoo’s Park 1. 예외처리(Exception

자바 예외처리 프로그래밍

Java Exception Handling Programming from Yongwoo’s Park 12

try { conn.setAutoCommit(true); pstmt.close(); conn.close(); } catch(SQLException e1) { e1.printStackTrace(); } }

그림 8. 중첩 예외처리 구문을 사용하는 JDBC 트랜잭션 처리 예

그림 8에서 보여주고 있는 예제 코드는 JDBC 프로그램을 작성할 때, 트랜잭션을 처리하기 위한

프로그래밍 코드이다. 프로그램 코드를 전체적으로 살펴보면, 다음과 같이 중첩 예외처리 구문을

사용하고 있다는 것을 알 수 있다. 다음고 같이 중첩 try/catch/finally 블록을 사용할 때 , 한 가지

주의할 점이 있다.

그것은 바로 catch 문의 매개변수로 받은 예외 변수의 이름이 catch 문 내에서 사용되는 try/catch

블록에서 똑같이 사용되면 안된다는 것이다 . 다음에 나오는 것처럼, 바깥에 위치하는

try/catch/finally 블록의 catch 블록에서 예외를 받기 위해 사용한 변수명이 e 이므로, catch 블록 내

에 위치하는 try/catch 블록의 catch 블록에서 예외를 받기 위해 사용하는 변수명은 e 와 다른 e1 이

라고 해 준 것이다.

try {

} catch(SQLException e) {

try {

} catch(SQLException e1) {

}

} finally {

try {

} catch(SQLException e) {

}

}

그림 8에서 보여주고 있는 소스 코드를 살펴보면, 바깥 try/catch/finally 블록의 try 블록 내에서 먼

저 conn.setAutoCommit(false) 메소드를 이용하여 자동 커밋 모드를 해제한다. 다시 말해서, INSERT

쿼리를 모두 성공할 경우에만 데이터베이스에 반영하고, 그렇지 않고 ISNERT 쿼리가 하나라도 실

패하였을 경우에는 데이터베이스에 반영하지 않는다는 것이다.

Page 13: 자바 예외처리 프로그래밍 · 2015-01-21 · Java Exception Handling Programming from Yongwoo’s Park 4 자바 예외처리 프로그래밍 from Yongwoo’s Park 1. 예외처리(Exception

자바 예외처리 프로그래밍

Java Exception Handling Programming from Yongwoo’s Park 13

이 때 , INSERT 쿼리를 모두 성공적으로 수행하였다는 것은 while 문이 끝날 때까지 예외가 발생하

지 않았다는 것을 의미한다고 할 수 있다. 따라서, while 문을 정상적으로 수행한 후, 현재까지 실

행한 INSERT 쿼리를 데이터베이스에 반영하기 위해 conn.commit() 메소드를 호출하면 된다.

그리고, finally 블록으로 이동하여 , conn.setAutoCommit(true) 메소드를 호출하여 원래데로 자동 커밋

모드를 설정하고 , INSERT 쿼리를 실행하기 위해 생성한 pstmt 객체의 close() 메소드를 호출하고,

마지막으로 데이터베이스에 대한 연결을 닫기 위해 conn 객체의 close() 메소드를 호출하면 된다.

이 때 , conn.setAutoCommit(true), pstmt.close(), conn.close() 등의 문장을 실행할 때, SQLException 에외

가 발생할 가능성이 있으므로 반드시 try/catch 블록으로 묶어주어야 한다.

만약, 바깥 try/catch/finally 블록의 try 블록 내에서 INSERT 쿼리를 반복적으로 실행하던 도중에 예

외가 발생하였다면, 지금까지 실행했던 INSERT 쿼리 작업을 취소함으로써 데이터베이스에 반영되

지 않도록 해 주어야 한다. 이를 위해, try 블록 내에서 SQLException 예외가 발생하면 이를 잡아

처리하도록 설정된 catch 블록 내에서 conn.rollback() 메소드를 실행해 주어야 한다 . 이 때,

conn.rollback() 문장을 실행할 때 , SQLException 에외가 발생할 가능성이 있으므로 반드시 try/catch

블록으로 묶어주어야 한다. 다음으로, finally 블록으로 이동하여 finally 블록을 실행하면 된다.

이와 같은 작업을 할 수 있도록 하기 위해, 필요하기 때문에 중첩 예외처리 블록을 사용할 수 있

도록 해 주는 것이다. 다시 말해서 , try 블록 , catch 블록, finally 블록 등에서 예외가 발생할 가능성

이 있는 문장을 실행할 수 있으므로, 중첩 예외처리 블록을 제공해 주는 것이다.

1.2 예외의 분류

1.2.1 예외의 분류

자바에서는 try/catch/finally 구문을 자바 언어 수준에서 제공해 줌으로써, 자바 프로그램 내에서 예

외를 처리할 수 있도록 해 주고 있다. 그런데 , 이러한 예외에 대해서 어떤 메소드를 호출했을 경

우, 어떤 예외가 발생할 수 있는지에 대해 미리 정의해 놓고 있다. 그림 9에서는 자바에서 정의하

고 있는 예외 클래스 계층도를 자세히 보여주고 있다.

Page 14: 자바 예외처리 프로그래밍 · 2015-01-21 · Java Exception Handling Programming from Yongwoo’s Park 4 자바 예외처리 프로그래밍 from Yongwoo’s Park 1. 예외처리(Exception

자바 예외처리 프로그래밍

Java Exception Handling Programming from Yongwoo’s Park 14

java.lang.Objectjava.lang.Object

java.lang.Throwablejava.lang.Throwable

java.lang.Errorjava.lang.Error java.lang.Exceptionjava.lang.Exception

java.lang.RuntimeExceptionjava.lang.RuntimeException……

Unchecked Exception Checked Exception

그림 9. 자바에서 예외 클래스의 계층도

자바에서는 기본적으로 프로그램 내에서 try/catch 구문을 이용하여 예외처리를 하지 못하는 Error

와 try/catch 구문을 이용하여 예외처리 가능한 Exception 등 두 가지로 나누어 예외를 정의하고 있

다. 이 때, Exception 은 다시 RuntimeException 과 그 외의 다른 Exception 으로 구분된다. 자바에서

는 다음과 같이 크게 세 가지의 예외로 분류하고 있다.

l Error: 자바 프로그램 상에서 잡아서 처리할 수 없는 에러를 나타낸다.

l RuntimeException 을 상속하는 예외: RuntimeException 을 상속하는 예외들은 프로그램의

실행시에 발생하는 예외로서, 컴파일러가 컴파일시에는 잡지 못한다.

l Exception 을 상속하는 예외 중 RuntimeException 을 제외한 나머지 예외: Exception 을

상속하는 예외들 중에서 RuntimeException 을 제외한 나머지 예외들은 컴파일러에서

컴파일 할 때 잡아주는 예외로서 반드시 try/catch 구문을 이용하여 예외처리를 해 주어야

하는 예외이다.

먼저, Error는 AWTError, LinkageError, ThreadDeath, VirtualMachineError 등과 같이 비정상적인 상태를

나타내지만, 자바 프로그램에서는 try/catch 구문을 이용하여 잡지 못하기 때문에 정상적인 상태로

인식하게 된다. 다시 말해서, ThreadDeath 와 같은 에러가 발생했더라도 자바 프로그램에서는 이 에

러를 잡을 방법이 없으므로 정상적인 상태로 인식하게 된다는 것이다 . 그리고 , 이러한 에러는 자

바 컴파일러를 통해서도 검사하지 못한다.

다음으로 , RuntimException 을 상속하는 예외는 프로그램 수행 중에 발생하는 에러들에 대해 정의하

고 있으므로 물론 컴파일러에서 검사하지 않는다. 이러한 예외는 컴파일러가 컴파일 시에 잡지 못

하는 예외로서, 프로그램을 실행하면서 잘못된 상황이 발생했을 경우에만 예외가 발생한다는 것을

Page 15: 자바 예외처리 프로그래밍 · 2015-01-21 · Java Exception Handling Programming from Yongwoo’s Park 4 자바 예외처리 프로그래밍 from Yongwoo’s Park 1. 예외처리(Exception

자바 예외처리 프로그래밍

Java Exception Handling Programming from Yongwoo’s Park 15

알 수 있는 예외이다. 실제로, RuntimException 을 상속하는 예외는 프로그래머의 잘못에 의해 발생

할 수 있는 예외로서, 프로그램의 테스트 및 디버깅 시에 충분히 잡아줄 수 있는 예외이다 . 예를

들면, NullPointerException 예외는 프로그래머가 참조형 변수에 대해 new 연산자를 이용하여 인스

턴스 생성을 하지 않은 상태로 사용하려고 할 경우 발생하는 예외이다.

int a[]=null; ... i = a[0]; System.out.println("a[0]="+ a[0]); // 6 번 라인

그림 10. NullPointerException 예외가 발생하는 프로그램 예

위와 같은 프로그램을 컴파일 하더라도 컴파일러에서는 별다른 컴파일 에러가 발생하지 않지만,

컴파일 한 후 생성된 클래스를 실행할 경우 실행시에 다음과 같은 예외가 발생한다 . 이 때 , 예외

메시지를 자세히 살펴보면 , 예외가 발생할 때의 스택의 상태를 자세히 보여주고 있다 . 따라서, 예

외 메시지에 나타나는 자바 프로그램 파일명 , 발생한 메소드, 그리고 소스 코드 내에서의 라인 번

호를 참조하여 해당 에러가 발생한 위치를 찾을 수 있다 . 다음에 나오는 예외 메소드에서는

ExceptionTest2.java 프로그램의 main() 메소드에서 6 번째 라인에서 예외가 발생했다는 것을 알 수

있다.

Exception in thread "main" java.lang.NullPointerException: at ExceptionTest2.main(ExceptionTest2.java:6)

그림 11. NullPointerException 예외 메시지

이와 같이, 프로그래머의 잘못된 로직에 의해 발생하는 예외의 경우 , 자바 프로그램을 직접 테스

트 및 디버깅 하면서 충분히 잡을 수 있는 예외이다 . 따라서, 프로그램 실행시에 발생하는 예외

메시지를 자세히 살펴보기 바란다.

마지막으로, Exception 을 상속하는 예외들 중에서 RuntimeException 을 제외한 나머지 예외들은 프

로그램 상에서 try/catch 구문을 이용하여 예외처리 하지 않을 경우 , 해당 소스 프로그램을 컴파일

할 때 컴파일러가 에러 메시지를 발생시킨다.

실제로, 자바에서는 메소드를 사용할 경우 프로그래머의 잘못이 아닌 불가항력적으로 발생할 수

있는 에러에 대해, 메소드에서 예외를 발생시킬 수 있다는 것을 모두 명세하고 있다. 다시 말해서,

프로그래머가 아무리 프로그램을 잘 작성했더라도 최악의 경우 발생할 수 있으므로, 자바에서는

안정적인 프로그램을 작성할 수 있도록 하기 위해 예외를 발생시킬 수 있는 모든 메소드에 대해

서 어떤 경우에 어떤 예외를 발생시키는 지에 대해서 모두 명세하고 있다. 따라서, 이러한 메소드

를 호출하는 문장을 사용할 경우에는, 반드시 try/catch 구문을 이용하여 예외처리 해 주어야 한다.

예를 들어 , 다음과 같이 프로그램 내에서 ClassNotFoundException 예외를 발생시킬 수 있다고 명세

Page 16: 자바 예외처리 프로그래밍 · 2015-01-21 · Java Exception Handling Programming from Yongwoo’s Park 4 자바 예외처리 프로그래밍 from Yongwoo’s Park 1. 예외처리(Exception

자바 예외처리 프로그래밍

Java Exception Handling Programming from Yongwoo’s Park 16

된 Class.forName(...) 메소드를 호출하거나, 또는 SQLException 예외를 발생시킬 수 있다고 명세된

DriverManager.getConnection(...) 메소드와 conn.close() 메소드 등을 사용하고 있지만 , try/catch 구문을

이용하여 예외처리를 해 주지 않을 경우 컴파일 시에 컴파일 에러가 발생한다.

Class.forName(jdbcDriver); Connection conn = DriverManager.getConnection(jdbcUrl, "sa", ""); ... conn.close();

그림 12. try/catch 구문을 이용하여 예외처리 하지 않은 경우

위와 같은 코드를 포함하고 있는 프로그램을 컴파일 할 경우 , 다음과 같은 컴파일 에러가 발생한

다. 왜냐하면, 프로그램 내에서 사용하고 있는 메소드에 대해 자바에서는 예외를 발생시킬 수 있

다고 명세하고 있지만, 실제로 프로그램 내에서 try/catch 구문을 이용하여 예외처리를 하고 있지

않기 때문이다 . 실제로, 컴파일 시에 발생하는 컴파일 에러 메시지를 살펴보면,

ClassNotFoundException 예외 또는 SQLException 예외를 try/catch 구문을 이용하여 반드시 잡아주거

나, 또는 이 코드를 포함하고 있는 메소드에서 해당 예외를 던질 수 있도록 메소드 선언이 이루어

져야 한다는 것이다.

X.java:9: unreported exception java.lang.ClassNotFoundException; must be caught or declared to be thrown Class.forName(jdbcDriver); ^ X.java:10: unreported exception java.sql.SQLException; must be caught or declared to be thrown Connection conn = DriverManager.getConnection(jdbcUrl, "sa", ""); ^ X.java:13: unreported exception java.sql.SQLException; must be caught or declared to be thrown conn.close(); ^

그림 13. try/catch 구문을 이용하여 예외처리 하지 않은 경우, 컴파일 시에 발생하는 컴파일 에러

메시지

ClassNotFoundException 예외 또는 SQLException 예외의 경우, 프로그램을 사용하기 위한 환경설정

(CLASSPATH)이 잘못되었거나 또는 데이터베이스 시스템이 비정상적으로 동작하는 등과 같이 프

로그래머가 프로그래밍 할 때는 고려할 수 없는 그러한 예외이기 때문에 프로그래머가 프로그램

을 아무리 잘 작성했다 하더라도 불가항력적으로 발생할 수 있는 예외이다. 따라서, 이러한 예외

에 대해 컴파일 시에 try/catch 구문을 이용하여 예외처리를 함으로써 안정적인 프로그램을 작성할

수 있도록 해 주고 있다.

try {

Page 17: 자바 예외처리 프로그래밍 · 2015-01-21 · Java Exception Handling Programming from Yongwoo’s Park 4 자바 예외처리 프로그래밍 from Yongwoo’s Park 1. 예외처리(Exception

자바 예외처리 프로그래밍

Java Exception Handling Programming from Yongwoo’s Park 17

Class.forName(jdbcDriver); Connection conn = DriverManager.getConnection(jdbcUrl, "sa", ""); /* ... */ } catch(Exception e) { e.printStackTrace(); } finally { conn.close(); }

그림 14. try/catch 구문을 이용하여 예외처리 한 경우

일반적으로, 그림 12에서 보여주고 있는 코드에 대해, try/catch 구문을 이용하여 그림 14에서와

같이 예외처리를 해 줄 것이다. 그러나, 그림 14에서와 같이 try/catch 구문을 이용하여 예외처리를

한 경우 , 그림 15과 같은 컴파일 에러가 발생한다. 왜냐하면, 그림 14에서와 같이 try/catch 구문을

이용하여 예외처리를 해 주면서, conn 변수 선언문이 try 블록 내로 들어가게 되므로 , finally 블럭

내에서는 conn 변수를 참조할 수 없는 것이다. 따라서, 변수 선언문을 블록 내에 위치시킬 때는

반드시 그 유효범위를 고려해 주어야 한다.

X.java:16: cannot resolve symbol symbol : variable conn location: class X conn.close(); ^

그림 15. “cannot resolve symbol” 컴파일 에러 발생

따라서, 그림 14에서 보여주고 있는 소스 코드에서 conn 변수 선언문을 try 블럭 밖으로 위칳시켜

주어야 한다. 이를 위해 , 일반적으로 다음과 같이 할 것이다. 그러나, 다음과 같이 할 경우에도 문

제는 여전히 존재한다.

Connection conn; try { Class.forName(jdbcDriver); conn = DriverManager.getConnection(jdbcUrl, "sa", ""); /* ... */ } catch(Exception e) { e.printStackTrace(); } finally { conn.close(); }

그림 16. try 블럭 밖에서 conn 변수 선언

Page 18: 자바 예외처리 프로그래밍 · 2015-01-21 · Java Exception Handling Programming from Yongwoo’s Park 4 자바 예외처리 프로그래밍 from Yongwoo’s Park 1. 예외처리(Exception

자바 예외처리 프로그래밍

Java Exception Handling Programming from Yongwoo’s Park 18

만약, 그림 16에서와 같이 conn 변수를 선언하고 있는 문장을 try 블록 밖으로 위치시켰다고 하더

라도, 컴파일 시에 그림 17에서와 같이 에러가 발생한다. 왜냐하면 , conn 변수의 선언문을 try 블록

밖으로 위치시켰다고 하더라고, 실제로 conn 변수에 특정 값을 대입하고 있는 문장은 try 블록 내

에 위치한다 . 이러한 이유로, finally 블록 내에서 conn.close() 문장을 사용한 것은 초기화 되지 않은

conn 변수를 사용한 것을 의미하게 된다. 따라서, conn 변수와 같은 참조형 변수를 선언할 때는 반

드시 null 값으로 초기화시켜 주는 프로그래밍 습관을 들이기 바란다.

X.java:17: variable conn might not have been initialized

conn.close();

X.java:17: unreported exception java.sql.SQLException; must be caught or declared to

be thrown

conn.close();

그림 17. 컴파일 에러 발생

다음으로 , finally 블록 내에서 conn.close() 문을 호출하고 있지만, Connection 클래스의 close() 메소

드는 SQLException 예외를 발생시킬 수 있다고 명세되어 있다 . 따라서 , conn.close() 메소드를 finally

블록 내에서 호출하고 있다고 하더라고, 반드시 conn.close() 메소드를 try/catch 구문을 이용하여 예

외처리 해 주어야 한다 . 그림 12에소 보여주고 있는 소스 코드에 대해 어떠한 컴파일 에러도 발생

하지 않도록 완전하게 수정한 소스 코드를 살펴보면, 다음과 같다.

Connection conn=null; t r y { Class.forName(jdbcDriver); conn = DriverManager.getConnection(jdbcUrl, "sa", ""); } catch(Exception e) { e.printStackTrace(); } finally { try { conn.close(); } catch(SQLException e) { e.printStackTrace(); } }

그림 18. try/catch 구문을 이용하여 완전하게 예외처리 한 소스 코드

Page 19: 자바 예외처리 프로그래밍 · 2015-01-21 · Java Exception Handling Programming from Yongwoo’s Park 4 자바 예외처리 프로그래밍 from Yongwoo’s Park 1. 예외처리(Exception

자바 예외처리 프로그래밍

Java Exception Handling Programming from Yongwoo’s Park 19

1.3 메소드에서 예외 던지기

1.3.1 메소드에서 예외 던지기

자바에서는 프로그래머가 원하면 예외를 강제로 발생시킬 수도 있다 . 자바의 모든 예외는

Throwable 클래스 또는 Throwable 클래스를 상속하는 서브클래스의 인스턴스로 표현된다 . 또한 , 자

바에서 제공해 주지 않는 예외에 대해서는 자바 프로그램의 개발자가 새롭게 정의하여 사용할 수

있고, 필요에 따라 이 예외를 발생시킬 수 있다.

자바에서 발생하는 모든 예외(Checked Exception)들에 대해, 발생한 곳에서 직접 처리하거나 처리할

곳을 지정하여 그 예외를 던져줄 수 있다 . 다시 말해서 , 메소드 내에서 발생한 예외를 해당 메소

드가 처리하지 않는다면 예외가 발생되었다는 것을 이 메소드를 호출한 메소드에게 알려서 처리

할 수 있도록 해 주어야 하는데, 이러한 과정을 “예외를 던진다”라고 한다.

이렇게, 예외가 발생할 가능성이 있는 메소드에서 예외를 직접 처리하지 않고 , 이 메소드를 호출

한 쪽으로 예외를 던지기 위해서는 메소드의 선언 다음에 throws 문을 사용하여 던지고자 하는 예

외들을 나열해 주어야 한다. 이 때, 한 개 이상의 예외를 던질 수 있고 , 던지고자 하는 예외들은

','를 이용하여 구분해 주면 된다. 예를 들면, 다음과 같다.

protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, java.io.IOException { ... }

그림 19. 예외를 던지도록 선언된 메소드

그림 19에서는 service() 메소드에서는 ServletException 예외와 java.io.IOException 예외를 던질(발생

시킬) 수 있다는 것을 명세하고 있다. 이 때, service() 메소드에서 두 개 이상의 예외를 던질 수 있

다는 것을 나타내기 위해 각 예외를 ‘,’를 이용하여 구분하고 있다.

메소드에서 자신이 예외를 처리하지 않고 ‘예외를 던진다’고 throws 문을 이용하여 메소드를 선언

했을 경우, 실제로 메소드 내에서 해당 예외를 던지는 부분이 있어야 한다. 이를 위해 throw 문을

사용할 수 있다. 그리고 , 이렇게 예외를 강제로 발생시키기 위해 자바 프로그램 개발자가 해 주어

야 할 일들이 몇 가지가 있는데, 다음과 같다.

l 먼저, throw 문 다음에는 java.lang.Throwable 클래스를 상속 받는 클래스의 인스턴스가

나타나야 한다.

l 그리고, throw 문은 try/catch 블록 내에서 사용되어야 한다.

Page 20: 자바 예외처리 프로그래밍 · 2015-01-21 · Java Exception Handling Programming from Yongwoo’s Park 4 자바 예외처리 프로그래밍 from Yongwoo’s Park 1. 예외처리(Exception

자바 예외처리 프로그래밍

Java Exception Handling Programming from Yongwoo’s Park 20

l 메소드 선언시 throws 문을 이용하여 명세한 예외만 던질 수 있다.

실제로, 메소드 선언시 명세한 예외를 메소드 내에서 던지는 예를 살펴보면, 다음과 같다.

public void delete(long seqNum) throws SQLException { deletePstmt.setInt(1, (int)seqNum); if(deletePstmt.executeUpdate() < 1) { throw new SQLException("Delete failed"); } }

그림 20. 예외를 던지도록 선언된 메소드 내에서 예외를 던지는 예

그림 20에서 보여주고 있는 소스 코드를 살펴보면, delete() 메소드를 선언할 때 throws 문을 이용하

여 SQLException 예외를 던질 수 있다는 것을 명세하고, 실제로 삭제된 항목이 하나도 없는 상황

과 같은 예외 상황이 발생했을 경우, 메소드 내에서 throw 문을 이용하여 직접 예외를 던지고 있

는 것을 볼 수 있다. 이 때, 다음과 같이 예외를 생성하여 예외를 던지고 있다.

throw new SQLException("Delete failed");

그리고, 메소드가 throws 문을 가진 메소드를 호출하였다면, 다음 중 하나의 작업을 반드시 해 주

어야 하며, 그렇지 않을 경우 컴파일 에러가 발생합니다.

l try/catch 문을 사용하여 예외를 처리한다.

l 메소드를 throws 로 선언하여 호출한 메소드에게 예외를 던진다.

l catch 문과 throw 문을 사용하여 예외를 처리하고, 다음 메소드에게도 예외를 던진다.

메소드를 재정의할 때 throws 부분은 상속되지 않으므로, throws 문을 포함한 메소드를 재정의할

때는 다음과 같은 특별한 규칙을 따라 재정의 해 주어야 한다.

l 하위 메소드는 상위 메소드에서 던지는 예외, 또는 상위 메소드에서 던지는 예외의 하위

예외만을 던지도록 throws 절을 이용하여 명세되어야 한다.

l 메소드가 throws 문을 이용하여 예외를 던지도록 명세되었을 경우 , 메소드 내에서는

throws 문에 명시된 예외를 던지거나 , 또는 throws 문에 명시된 예외의 하위 예외만을

던질 수 있다.

Page 21: 자바 예외처리 프로그래밍 · 2015-01-21 · Java Exception Handling Programming from Yongwoo’s Park 4 자바 예외처리 프로그래밍 from Yongwoo’s Park 1. 예외처리(Exception

자바 예외처리 프로그래밍

Java Exception Handling Programming from Yongwoo’s Park 21

l 메소드가 throws 문을 이용하여 예외를 던지도록 명세되었다고 하지라도 , 메소드

내에서는 아무런 예외를 던지지 않을 수도 된다.