Exception 에 대한 알아보자

이현지·2024년 4월 18일
2

개발을 하다 보면 exception 일 때 try~catch 로 처리하는 경우가 있고, Runtime Exception 으로 처리되게 하는 경우가 있다. 처리하는 방식이 어떻게 다른지, 어떤 방법이 더 선호되는지 알아보자.

우선 Exception 의 개념에 대해 먼저 알아보자.

Exception 이란?

Exception 은 한마디로 예외이다. 그렇다면 예외와 에러의 차이는 무엇일까?

  • 예외란 개발자가 구현한 로직 내에서 발생하는 것으로, 예측하여 처리가 가능하다.
  • 에러란 시스템 내 비정상적인 상황이 생겼을 때 발생하며, 미리 처리 및 예측이 불가하다.

이제 Exception 에 대해 간단히 알았으니, Exception 에 어떤 종류가 있는지 알아보자.

Exception 의 종류

다음 그림을 보면 Exception 이 Checked ExceptionUnchecked Exception 두가지로 나누어져 있는 것을 볼 수 있다.
이제 이 두가지의 차이를 알아보자.

Checked Exception

compile 단계에서 발생하는 exception 으로 반드시 예외에 대한 처리를 선언해야 한다.
ex) IOException, FileNotFoundException 등

  • try ~ catch 로 예외 처리

    public void test() {
        try {
            File file = new File("text.txt");
            FileReader fr = new FileReader(file);
    
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
  • throws FileNotFoundException 으로 예외를 전가, 상위 메서드의 선언부에도 시그니처 선언
    public void test() throws FileNotFoundException {
        File file = new File("text.txt");
        FileReader fr = new FileReader(file);
    }
    
    

Unchecked Exception

실행 단계에서 발생하는 exception 으로 예외에 대한 처리를 미리 할 수 없다.
ex) RuntimeException, NullPointerException, IllegalArgumentException 등

	public static void main(String[] args) {
        int[] array = new int[5];

        System.out.println(arr[6]);  // ArrayIndexOutOfBoundsException 발생
    }
    

checked exception 은 예외처리를 강제하여, try~catch 를 사용하여 예외를 잡거나, throws Exception 으로 예외를 전가하여 예외를 처리해야하고, 예외를 처리하 않으면 컴파일 오류가 발생하는 반면, RuntimeException 의 경우 예외 처리를 강제하지 않으며, 실행 시 예외가 발생하므로 컴파일 오류가 발생하지 않는다.

Checked Exception 에 대한 오해

일반적으로 스프링에서 Checked Exception 은 예외 발생 시 롤백이 되지않고, Unchecked Exception은 예외 발생 시 롤백이 되는 것으로 알고 있다.

하지만 이는 스프링의 기본 설정일 뿐이고, Checked Exception 또한 롤백되게 설정할 수 있다.

@Override
public boolean rollbackOn(Throwable ex) {
    return (ex instanceof RuntimeException || ex instanceof Error);
}
  • 위의 코드를 보면 rollabackOn의 경우 기본적으로 RuntimeException 과 Error 시에만 롤백을 한다.
@Transactional(rollbackFor = {RuntimeException.class, Error.class})
public void test() {
	
}
  • @Transactional 의 경우 기본적으로 사용하면 위와 같은 설정으로 RuntimeException 과 Error 시에만 롤백한다.

그렇다면 Checked Exception 도 롤백되게 설정하려면 어떻게 해야할까?

@Transactional(rollbackFor = Exception.class)
public void test() {
	
}
  • 다음과 같이 rollbackFor 설정에 특정 Exception 이 발생하면 롤백하도록 설정할 수 있다. 위와 같이 rollbackFor = Exception.class 로 작성하면, 모든 Exception 에 대해 롤백된다.

RuntimeException 이 더 좋다?

실무에서 경험해보면 try ~ catch 를 사용하여 예외를 처리하는 경우를 본 경우가 드물다. 또한 RuntimeException 을 사용하는 것을 권장한다. 왜 그럴까?

Checked Exception 을 사용할 때의 몇 가지 단점 때문이다.

  • Checked Exception 은 예외를 복구할 수 있을 때 사용한다.
    Checked Exception 을 사용하는 경우는 예외를 복구할 수 있는 경우이다. 하지만 일반적으로 예외를 복구할 수 있는 상황은 거의 없다. 예를 들어 사용자가 잘못된 값을 보낸 경우 exception 이 발생했을 때, exception 이 발생한 후 해당 프로세스가 종료되며, 재요청을 보내는 것이지 예외가 복구되는 것이다 아니다.

  • open / closed 원칙 위배
    checked exception 에서 예외를 상위 메소드로 던질 경우, 상위 메소드 선언부에도 시그니처를 변경해야한다. 만약 하위 메소드에서 checked exception 을 발생시키면, 이를 호출하는 모든 상위 메서드의 선언부를 변경해야한다. 이는 기존 코드의 변경을 최소화하여 수정을 가능하게 해야한다는 open/closed 원칙에 위배된다.

  • 다른 언어들은 checked exception 이 없다.
    java 외에 다른 프로그래밍 언어는 checked exception 이라는 개념이 없다. 다른 언어로 개발한다고 exception 처리에 문제가 있는 것은 아니므로 checked exception 이라는 개념이 굳이 필요없다. 물론 장점도 있지만 종속성 비용이 더 크다.

마무리

Checked Exception 에 대한 논란은 지속되어 왔다. Checked Exception 은 자바의 실수다 아니다로 많은 논란이 있었는데, 현재는 Checked Exception 을 사용하지 않는 방향으로 논란이 종결된 것 같다. Checked Exception 은 대규모의 프로그래밍을 개발할 때 오히려 생산성을 떨어트린다는 결과가 나왔고, 현재 Java 도 함수형 인터페이스에서 Checked Exception 을 허용하지 않고 있다.

이렇게 Exception 에 관련해서 개념과 논란에 대해 알아보며, 어떤 처리 방식이 선호되고, 단점이 무엇인지 알게된 시간이었다.

References

https://www.nextree.co.kr/p3239/

https://jangjjolkit.tistory.com/3

https://velog.io/@sangmin7648/당신의-Checked-Exception은-필요-없다

https://inpa.tistory.com/entry/JAVA-☕-예외-던지기throw-예외-연결Chained-Exception
https://velog.io/@eastperson/Java%EC%9D%98-Checked-Exception%EC%9D%80-%EC%8B%A4%EC%88%98%EB%8B%A4-83omm70j

profile
Backend Developer👩‍💻

0개의 댓글