본문 바로가기
BackEnd/Spring

예외와 예외 처리 방법

by 규난 2023. 4. 9.
728x90

예외란?

컴퓨터 프로그램에서 예외란, 프로그램이 실행 중에 발생한 예기치 않은 오류를 말합니다.

이러한 예외 상황을 처리하지 않으면 프로그램이 비정상적으로 종료될 수 있기 때문에 모든 예외는 적절하게 복구되든지 아니면 작업을 중단시키고 운영자 또는 개발자에게 통보하고 서비스를 이용하는 사용자에게 적절한 안내 메세지를 제공하는 등의 처리를 반드시 해줘야 합니다.

 

예외의 종류

이번 포스트에서는 Error에 대한 설명은 제외하겠습니다.

 

Exception (Checked Exception)

Exception 클래스와 이를 상속하고 Runtime Exception을 상속하지 않은 서브 클래스로 정의되는 예외입니다.

이 예외는 컴파일 시점에 예외 처리를 하는지 검사하기 때문에 개발자가 예외 처리를 강제하는 예외입니다.

이 예외를 던지는 메소드를 호출한 메소드는 catch 문을 사용해서 예외를 잡든지 아니면 throws를 정의해서 메소드 밖으로 던져서 반드시 예외 처리를 해야 합니다.

Runtime Exception (Unchecked Exception)

RuntimeException을 상속한 클래스들을 말합니다. 피할 수 있지만 개발자의 부주의로 인해서 발생할 수 있는 예외입니다.

이 예외는 컴파일 시점에 예외 처리에 대한 검사를 하지 않기 때문에 즉, 명시적인 예외 처리를 강제하지 않기 때문에 unchecked exception이라고 불리고 catch 문으로 잡거나 메소드를 throws로 선언하지 않아도 됩니다. 

자바 예외 계층 구조

사진 출처 - http://www.tcpschool.com/java/java_exception_class

 

여기서 한 가지 짚고 넘어가야 할 부분이 있는데 많은 개발자분들이 checked exception 발생 시 transaction이 rollback 되지 않고 unchecked exception 발생 시 transaction이 rollback 된다고 알고 있는데 이 말은 java 관점에서는 틀린 얘기고 spring framework에서는 어느 정도 맞는 얘기입니다.

 

java에서는 이 두 예외의 구분은 예외 처리의 강제성 여부를 나타낼 뿐 transaction의 rollback 여부는 포함하지 않습니다.

하지만 spring framework에서는 transaction의 rollback 여부를 @Transactional 어노테이션으로 쉽게 관리할 수 있는데 이 어노테이션에서 rollback에 대한 기본 전략이 checked exception에 대해서는 rollback을 하지 않고 unchecked exception에 대해서는 rollback을 하는 것이 기본 전략이기 때문에 많은 개발자분들이 checked exception 발생 시 transaction rollback 하지 않는다, unchecked exception 발생 시 transaction rollback을 한다고 착각하고 계신 거 같습니다.

이 기본적인 전략은 @Transactional 어노테이션의 rollbackFor, noRollbackFor 속성을 이용하여 명시적으로 예외 타입에 따라 rollback 여부를 결정할 수 있습니다.

 

그렇다면 spring framework는 왜 checked exception 발생 시 transaction에 대해서 rollback을 하지 않고 unchecked exception 발생 시 transaction에 대해서 rollback을 시킬까요? 그 이유는 checked exception은 예외 처리를 강제하기 때문에 개발자가 사전에 충분히 예측이 가능하고 복구에 대한 코드를 작성해 놓을 수 있기 때문에 rollback을 시키지 않는 것이고 unchecked exception은 예상할 수 있지만 checked exception과 반대로 예외 처리를 강제하지 않기 때문에 개발자의 실수로 인해 예외가 발생할 수 있으므로 rollback을 시키는 것입니다. 하지만 이것은 spring framework의 transaction에 대한 기본 전략이기 때문에 위에서 언급한 대로 명시적으로 예외 타입에 따라 rollback 여부를 개발자가 정할 수 있습니다.

 

그럼 다시 본론으로 돌아와 예외 처리 방법에 대해서 알아보도록 하겠습니다.

 

예외 처리 방법

예외 처리 방법은 예외 복구, 예외 처리 회피, 예외 전환 이렇게 3 가지가 존재합니다.

 

예외 복구

예외의 상황을 파악하고 문제를 해결해서 정상 상태로 돌려놓는 방법입니다.

예를 들어 사용자가 요청한 파일을 읽으려고 시도하다가 해당 파일이 없거나 다른 문제가 생겨서 IOException이 발생했을 때 예외 메세지가 사용자에게 그대로 던져지는 것이 아니라 사용자가 알기 쉽게 상황을 알려주고 다른 파일을 이용할 수 있도록 안내해 주는 방법도 예외를 복구했다 볼 수 있습니다.

 

예외 처리 회피

예외 처리를 자신이 담당하지 않고 자신을 호출한 쪽으로 던져버리는 것입니다. 이 방법은 자신을 사용하는 쪽에서 예외를 다루는 게 최선의 방법이라는 확신이 있을 때 사용하는 것이 좋습니다. throws 문으로 선언해서 예외가 발생하면 알아서 던져지게 하거나 catch 문으로 예외를 잡아서 로그를 남긴 후에 다시 예외를 던지는 방법을 사용합니다.

 

예외 전환

예외 회피와 비슷하게 예외를 복구해서 정상적인 상태로 만들 수 없기 때문에 예외를 메소드 밖으로 던지는 방법입니다.

예외 회피와 비슷하지만 다른 점은 발생한 예외를 그대로 던지는 게 아니라 적절한 예외로 전환해서 던지는다는 특징이 있습니다.

예외 전환은 두 가지의 목적으로 사용됩니다.

  1. 내부에서 발생한 예외가 적절한 의미를 부여해 주지 못해 의미를 분명하게 해줄 수 있는 예외로 바꾸기 위한 목적
  2. 불필요한 catch/throws를 피하기 위해 RuntimeException으로 포장하기 위한 목적

위 두 가지 목적 모두 새로운 예외를 만들고 원인(cause)이 되는 예외를 새로운 예외에 담아서 던지는 방식은 같지만 의미를 명확히 하려고 예외를 전환하는 첫 번째 방식과 달리 두 번째 방법은 주로 예외 처리를 강제하는 checked exception을 unckecked exception으로 전환하려는 경우에 사용됩니다.

 

출처 - 토비의 스프링 3.1 Vol 1 스프링의 이해와 원리

728x90

'BackEnd > Spring' 카테고리의 다른 글

Spring AOP - Advice, Pointcut  (0) 2023.08.06
Spring AOP  (0) 2023.08.05
스프링의 템플릿/콜백 패턴  (0) 2023.04.02
Spring - 테스트와 TDD  (1) 2023.03.26
Spring - 오브젝트와 의존관계(스프링의 IoC와 DI)  (0) 2023.03.21