예외(Exception)란?

 

프로그래밍 언어의 문법에 맞지 않게 프로그램을 작성하면 컴파일 오류가 발생한다.

그렇기 때문에 실행 이전에 문법에 맞지 않게 작성 된 오류는 미리 걸러내어야 하는데, 프로그램 실행 중에 동적으로 변하는 배열의 인덱스같은 경우 컴파일 시점에서 걸러낼 수가 없다. 이와 같은 프로그램 실행 중에 발생하는 런타임 오류(Run Time Error)는 미리 걸러낼 수가 없어 자바에서는 예외(Exception)을 사용하여 처리한다.

 

JVM이 프로그램을 실행하다가 예외가 발생하는 경우, 그 예외에 맞는 오브젝트를 throw라는 문법을 통해 예외를 발생시킨다.

 

 

 

자바에서 제공하는 예외

 

아래의 Exception Hierachy in Java 이미지를 보면,

 

자바 다형성에 의해 Exception으로 선언 된 Exception e에서 IndexOutOfBoundsException, NullPointerException 등등을 catch할 수 있는 것이다.

 

 

 

예외 구분

출처: https://madplay.github.io/post/java-checked-unchecked-exceptions

 

RuntimeException을 상속하지 않는 클래스는 Checked Exception, 상속한 클래스는 Unchecked Exception으로 분류된다.

 

앞서 자바 다형성에 의해 Exception을 상속한 여러 예외들은 Exception에서 catch하여 처리할 수 있다고 하였는데,

자바에서는 RuntimeException과 이를 상속한 클래스는 명시적으로 예외처리를 하지 않아도 된다.

catch로 잡거나 throw로 호출한 메서드로 예외를 던지지 않아도 상관이 없다는 뜻이다.

 

 

 

이미지에 트랜잭션 처리가 조금 헷갈리게 쓰여져 있는데

Checked Exception 발생 시 프로그램은 Rollback이 되지 않고, Unchecked Exception은 Rollback이 진행 된다.

 

즉 런타임 예외는 발생하면 롤백되지만, 입출력과 같은 예외는 발생하더라도 롤백되지않고 트랜잭션이 커밋 된다는 이야기

 

(((스프링에서 트랜잭션 어노테이션을 사용해도 Checked Exception은 롤백되지 않기 때문에 반드시 로직의 롤백여부를 판단하여 구현해야한다는 것)))

 

결론적으로 Checked Exception을 만나면 더 구체적인 Unchecked Exception을 발생시켜 정확한 정보를 전달하고 로직의 흐름을 끊어야 한다는 것이다.

 

 

예외 처리란?

 

프로그램 실행 중 예외가 발생할 때, 프로그램에서 예외 처리를 따로 하지 않으면 프로그램은 강제 종료된다.

예외를 처리하는 방법에는 예외 복구, 예외 처리 회피, 예외 전환이 있다.

 

앞서 자바에서 JVM은 예외가 발생하면 예외 오브젝트를 만들어 던진다고 하였는데,

문법에 맞지 않는 오류 뿐 아니라 개발자들이 허용하지 않는 예외 상황이 있다면 이를 소스 코드로 구현할 수 있다.

 

 

[ 예외 복구 ]

  • 예외를 잡아서 일정 시간, 조건만큼 대기하고 재시도를 반복한다.
  • 최대 재시도 횟수를 넘기면 예외를 발생시킨다.
final int MAX_RETRY = 100;
public Object someMethod() {
    int maxRetry = MAX_RETRY;
    while(maxRetry > 0) {
        try {
            ...
        } catch(SomeException e) {
            // 로그 출력. 정해진 시간만큼 대기한다.
        } finally {
            // 리소스 반납 및 정리 작업
        }
    }
    // 최대 재시도 횟수를 넘기면 직접 예외를 발생시킨다.
    throw new RetryFailedException();
}

 

 

[ 예외 처리 회피 ]

  • throw
import java.io.IOException;

public class IOService {
    public String read() {
        String text = ""; // read string from file;
        if(text == null || text.isEmpty()) {
            throw new IOException("Content is empty");
        }
        return text;
    }
}


출처: https://imasoftwareengineer.tistory.com/89 [삐멜 소프트웨어 엔지니어]

 

우리가 "Content is empty" String이 아닌 IOException을 리턴하는 이유는 이 read 메서드를 사용하는 개발자에게 예외처리를 미루고자 하기 때문이다. 이 메서드를 부른 메서드(Caller)에게 예외를 처리하는 의무를 주는 것이다.

 

개발자들이 프로그램에 빈 텍스트를 입력받았을 때 처리하고자 하는 내용이 각각 다를 수 있으므로

Caller로 예외를 throw하기 위해서는 아래와 같이 사용한다.

 

 

  • throws
import java.io.IOException;

public class IOService {
    public String read() throws IOException {
        String text = ""; // read string from file;
        if(text == null || text.isEmpty()) {
            throw new IOException("Content is empty");
        }
        return text;
    }
}


출처: https://imasoftwareengineer.tistory.com/89 [삐멜 소프트웨어 엔지니어]

 

read 메서드를 부르는 caller 메서드가 Main이라고 했을 때,

아래와 같이 Main에서 try-catch를 사용하여 예외를 처리하도록 하기 위함이다.

 

import java.io.IOException;

public class Main {
  public static void main(String[] args) {
   	 IOService ioService = new IOService();
     try { 
     	ioService.read();
     } catch (IOException e) { 
     	// 예외처리 할 내용 
     }
  }
}

출처: https://imasoftwareengineer.tistory.com/89 [삐멜 소프트웨어 엔지니어]

 

 

 

[ 예외 전환 ]

예외 회피와 비슷하지만, 적절한 예외로 전환해서 throw하는 방법

// 조금 더 명확한 예외로 던진다.
public void add(User user) throws DuplicateUserIdException, SQLException {
    try {
        // ...생략
    } catch(SQLException e) {
        if(e.getErrorCode() == MysqlErrorNumbers.ER_DUP_ENTRY) {
            throw DuplicateUserIdException();
        }
        else throw e;
    }
}

// 예외를 단순하게 포장한다.
public void someMethod() {
    try {
        // ...생략
    }
    catch(NamingException ne) {
        throw new EJBException(ne);
        }
    catch(SQLException se) {
        throw new EJBException(se);
        }
    catch(RemoteException re) {
        throw new EJBException(re);
        }
}

 

 

 

 

[ 참고한 포스팅 ]

 

자바 예외 구분 :: Checked Exception, Unchecked Exception

https://madplay.github.io/post/java-checked-unchecked-exceptions

 

예외처리

https://imasoftwareengineer.tistory.com/89

 

Checked Exception

https://cheese10yun.github.io/checked-exception/

복사했습니다!