Java에서 예외가 발생할 경우 프로그램의 흐름에 대해..

  • Post author:
  • Post category:
  • Post comments:0 Comments
  • Post last modified:December 7, 2020

Java 프로그램을 작성하는데 있어 예외를 처리하는 것은 프로그램의 신뢰성을 보장하기 위해 매우 중요합니다. 실제 프로젝트를 진행하게 되면 예외처리와 관련한 코드의 비중이 매우크기도 하죠.

만약 하나의 커다란 테스크가 여러개의 작업으로 나뉘어진 경우 그중 하나의 작업에서 예외가 발생할 경우 테스크 전체를 어떻게 처리할 것인가 하는 문제를 생각해보면 예외처리를 통해 상황에 맞는 전략을 세우게 될 것 입니다.

다른 측면에서 보면 이는 로깅 전략과도 연관이 있는데 이 글에서는 Java에서 예외가 발생하는 경우 기본적인 코드의 흐름이 어떻게 되는지에 대해 이야기 하고자 합니다.

Java의 코드 수행은 좌에서 우로 위에서 아래로 흘러간다는 것을 염두하고 다음의 몇가지 상황을 상정해 보았습니다.

1. 예측하지 못한 상황에서 예외가 발생할 경우.

서브루틴이라면 예외를 상위로 전가시킬 수 있겠지만 메인 프로그램이라면 예외가 발생한 시점에 프로그램의 동작이 중단됩니다. 현실에 빗대어 생각해 보자면 프로그램 상의 일련의 작업 파이프 라인을 공장에서의 하나의 생산 라인이라고 하면 예외가 발생한다는 것은 생산 라인의 어딘가에서 문제가 발생해서 라인 전체의 작업이 중단되는 것과 같다고 볼 수 있겠습니다.

1의 상황이 발생한다면 프로그램의 치명적인 결함이 되기 때문에 이를 해소하기 위해 try-catch 구문을 이용한 예외처리를 Java에서는 제공하고 있습니다.

2. 예외가 발생하는 시점의 코드를 try-catch 구문으로 처리한 경우.

예외는 역시 발생하지만 예외처리를 하지 않은 곳에서 문제가 발생하지 않는 한 코드는 끝까지 수행되게 됩니다. 하지만 이경우에도 고려해야할 문제가 있는데 다음의 코드를 보면..

package when.error.occurs;

public class SumOfErrors {
public static void main(String[] args) throws Exception{
MakeError error = new MakeError();
int loopCount = 1;
System.out.println("Start Message !");

while (true) {
System.out.println("Number of loop count : " + loopCount);

try {
System.out.println("Before error");
error.makeSomeErrors();
System.out.println("After error");
} catch (Exception e) {
e.printStackTrace();
//error occurs in catch area..
//error.makeSomeErrors();
System.out.println("Message in catch area");
} finally {
//error occurs in finally area..
//error.makeSomeErrors();
System.out.println("Message in finally area");
}

loopCount++;
System.out.println("Wait for 3000ms...");
Thread.sleep(3000);
}

}

}

이 코드에서 MakeError 클래스는 단순히 강제로 예외를 발생시켜 호출한 곳으로 전가(throws)시키는 메소드인 makeSomeErrors를 가지고 있습니다.

error.makeSomeErrors(); 호출 시점에 예외가 발생하게 되는데 해당 라인 이후의 try 영역의 코드는 수행되지 않고 catch 영역으로 넘어가는 것을 알 수 있습니다. 그렇기 때문에 try영역으로 감싸게 될 코드는 이러한 흐름을 고려하여 포함시켜야 한다고 볼 수 있습니다. finally 영역의 경우는 예외 발생 여부와 관계없이 반드시 수행을 진행하기 때문에 이러한 문제를 해소하기 위해 사용될 수 있습니다.

실행 결과는 다음과 같습니다.

Start Message !
Number of loop count : 1
Before error
java.lang.Exception: Exception in subroutine
at when.error.occurs.MakeError.makeSomeErrors(MakeError.java:5)
at when.error.occurs.SumOfErrors.main(SumOfErrors.java:14)
Message in catch area
Message in finally area
Wait for 3000ms...
...

“After Error” 메시지는 건너 뛴것을 확인할 수 있습니다.

2-1. catch 영역에서 예외가 발생할 경우.

샘플 코드의 주석을 해제하고 테스트해보면 알 수 있겠지만 catch 영역의 예외가 발생한 시점 이후의 코드는 수행되지 않습니다 “Message in catch area” 메시지는 건너 뛰게 되며 finally 영역의 코드가 수행된 후 1번과 같은 결과에 도달함을 알 수 있습니다. 만약 하위 Exception 클래스로 catch 영역을 세분화 하는 경우 정의되지 않은 예외가 발생하는 문제에 주의 해야함을 알 수 있습니다.

2-2. finally 영역에서 예외가 발생할 경우.

역시 샘플 코드의 주석을 해제하고 테스트해보면 finally 영역의 예외 발생 이후의 코드는 수행되지 않고 “Message in finally area” 메시지는 건너 뛰는 것을 확인할 수 있습니다. 역시 1과 같은 결과에 도달함을 알 수 있습니다.

마치며..

일반적으로 J2EE 어플리케이션을 작성하는 경우 서블릿 컨테이너 위에서 프로그램이 동작하기 때문에 main 메소드를 작성할일이 없어 어지간한 상황이 아니라면 컨테이너가 죽는 경우는 없겠지만 독립 어플리케이션을 작성하는 경우라면 이런 흐름을 충분히 고려해서 프로그램을 작성해야 할 것 입니다.

Author Details
Linus Lee aka y1sh former ATiMania.com sysop during 2001-2012. DevSecOps Engineer who likes tech, science, programming and solving problems 🙂
0 0 votes
Article Rating
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments