오류(error) : 시스템에 무엇인가 비정상적인 상황이 발생한 경우. 프로그램이 실행 중 어떤 원인에 의해서 오작동을 하거나 비정상적으로 종료되는 경우가 있는데 이러한 결과를 초래하는 원인.
- Java에서는 주로 JVM(Java Virtual Machine)에서 발생시키는 것이고,
예외(Exception)
와 반대로 Application Code에서 잡아도 처리할 제대로 방법이 없다. OutOfMemoryError
,ThreadDeath
,StackOverflowError
등
에러는 발생 시점에 따라서 3가지로 분류할 수 있다.
Compile Error (컴파일 에러)
: 컴파일 할 때 발생하는 에러. syntax error(문법 오류)도 포함됨. - 컴파일 시 발생하는 에러- 소스코드를 컴파일을 하면
컴파일러
가 소스코드에 대해오타
나Syntax Error(잘못된 구문)
, 자료형 체크등의 기본적인 검사를 수행하여 오류를 잡아낼 수 있다. - 소스코드를 컴파일러가 컴파일하는 시점에서 발생하는 에러를 컴파일 에러라 하며 이 시점에서 발생하는 문제들을 수정 후 컴파일을 성공적으로 마칠경우 클래스 파일(*.class) 파일이 생성된다.
- 소스코드를 컴파일을 하면
Runtime Error (런타임 에러)
: 프로그램 실행 도중에 발생하는 에러 - 실행 시 발생하는 에러- 컴파일러는 컴파일 시점에서 문법 오류나 오타같은 컴파일 시점에서 예측 가능한오류는 잡아줄 수 있지만, 실행중 발생할 수 있는 잠재적인 에러까지는 잡을 순 없다.
- 컴파일은 완료되어서 컴파일 에러는 없지만 실행 중 발생할 수 있는 에러이다.
Logical Error (논리적 에러)
: : 컴파일도 잘되고 실행도 잘되지만 의도한 것과 다르게 동작하는 것.- 컴파일도 정상적으로 되고 런타임 에러도 발생하지 않았지만 개발자가 의도한 대로 동작하지 않는 에러를 말한다.
- API가 응답값을 주도록 했으나 응답값을 안주거나, 아무 동작을 안하거나, 버그가 생기는 등을 의미한다
예외(exception) : 입력 값에 대한 처리가 불가능하거나, 프로그램 실행 중에 참조된 값이 잘못된 경우 등 정상적인 프로그램의 흐름을 어긋나는 것
- Java에서
Exception
은 개발자가 직접 Application Code내에서 처리 할 수 있어, 예외 상황에 대해 미리 예측하여 Handling할 수 있다. - Exception, RuntimException, IOException 등
오류가 시스템 레벨에서 발생한다면 예외(Expceiton)은 개발자가 구현한 로직에서 발생한다.
런타임 시점에서 발생하는 오류는 에러(error)와 예외(exception)으로 나뉜다.
컴파일러가 소스코드 컴파일중 발생한 에러를 잡았다 해서 실행 도중에 발생할 수 있는 잠재적인 오류까지는 검사할 수 없다 . 이것이 런타임 에러이다.
런타임 에러를 방지하기 위해서는 프로그램 실행 도중 발생할 수 있는 모든 경우의수를 고려하여 이에 대한 대비를 하는것이 필요한데
자바에서는 실행 시(rumtime) 발생할 수 있는 프로그램 오류를 에러(rror)와 예외(exception) 두가지로 구분하였다
따라서 개발자는 예외 처리(exception handling)를 통해 예외 상황을 처리할 수 있도록 코드의 흐름을 바꿀 필요가 있다.
• 에러(Error): 메모리 부족(OutOfMemoryError)이나 스택오버플로우(StackOverflowError)와 같이 일단 발생하면 복구할 수 없는 심각한 오류
• 예외(exception): 인자값 Null 에러, NPE(NullPointException)같은 발생하더라도 수습이 가능한 덜 심각한 오류.
자바 예외 클래스의 구조
자바는 실행 시 발생할 수 있는 오류들(Error와 Exception)을 클래스로 정의하였다.
- 예외 클래스도 클래스이고, 모든 클래스의 조상은 Object 클래스이므로 Exception과 Error 클래스 역시 Object 클래스의 Object 클래스의 자손들이다.
예외 클래스들은 2그룹으로 나눌 수 있다.
- Exception 클래스를 상속받고 RuntimeException을 상속받지 않은 예외들 - CheckedException (확인된 예외)
- RuntimeException을 상속받은 예외들 - UncheckedException(확인되지 않은 예외)
- Throwable : Java의 모든 오류 및 예외의 상위 클래스. 이 클래스(또는 해당 하위 클래스 중 하나)의 인스턴스인 개체만 JVM에 의해 throw되거나 Java
throw
문에 의해 throw될 수 있다.- 마찬가지로 이 클래스 또는 해당 하위 클래스 중 하나만
catch
절로 catch할 수 있다. - 예외의 컴파일 타임 검사 목적을 위해,
Throwable
하위 클래스 도Throwable
아닌 하위 클래스는 확인된 예외로 간주한다.RuntimeException
Error
- 마찬가지로 이 클래스 또는 해당 하위 클래스 중 하나만
- Exception : 클래스 Exception과 해당 서브클래스는 애플리케이션이 파악하고자 하는 예외 조건을 보여주는 Throwable 이다.
- 예외 클래스 및 RuntimeException을 상속받은 하위 클래스가
아닌
, 모든 하위 클래스 예외는checked 예외
이다.- RuntimeException은 Unchecked 예외이다.
- 체크된 예외는 메서드 또는 구성 요소의 실행에 의해 슬로우며 메서드 또는 구성 요소의
경계 밖으로 전파될 수 있는 경우
메서드 또는 구성 요소의 throw 구로 선언해야 한다.
- 예외 클래스 및 RuntimeException을 상속받은 하위 클래스가
- Error : 클래스 Error 는 애플리케이션이
catch
하는것을 시도해서는 안되며, 심각한 문제를 나타내는 Throwable의 하위 클래스.- 이러한 오류는 대부분 비정상적인 상태이다.
- ThreadDeath 오류는 "정상적인" 조건이지만 대부분의 응용 프로그램이 오류를 catch하려고 시도해서는 안 되기 때문에 Error의 하위 클래스이다.
- 메소드 실행 중에 발생할 수 있지만 포착되지 않은 Error의 하위 클래스를 throws 절에서 선언할 필요는 없다.
- 즉, Error 와 Error의 하위 클래스는 컴파일 타임 예외 검사를 위해
unchecked 예외
로 간주된다.
RuntimeException
RumtimeException은 JVM 정상 작동 중, 즉 애플리케이션 실행 시점에 발생할 수 있는 예외들의 상위 클래스이다.
RuntimeException
은 Program 실행 중에 발생하며 System 환경적으로나, Input Value가 잘못된 경우, 의도적으로 개발자가 설정한 조건을 위배했을 때 throw 되게 하는 등, Application 실행 도중에 발생하는Exception
이다.RuntimeException
은명시적으로 예외 처리를 하지 않아도 되는
Exception
이다.- Exception 처리를 명시하지 않아도 Program 구동에 아무 문제가 없다.
- 그러나 다른 문제를 야기할 수 있으니 처리할 수 있는 만큼 처리해주는 것이 좋다.
RuntimeException 과 ErrorClass들을
UnchckedException
이라고 묶으며,
RuntimeException 과 ErrorClass들을 제외한 예외 클래스들을CheckedException
로 묶는다,
CheckedException과 UncheckedException
CheckedException (확인된 예외)
RuntimeException을 상속받지 않은 클래스들을 CheckedExcpetion이라고 한다.
예외가 발생할 수 있는것이 확인되기 때문에 반드시 명시적으로 처리해야 한다.
CheckedException
은 반드시 예외 처리 해야하는 Exception
*으로, *Compile 시점에서 Exception
발생이 확인될 수 있으므로 반드시 명시적으로 처리해야 한다. 그렇지 않으면 컴파일러가 에러를 잡는다
- 메소드 내에서 try catch를 하든, 메소드 밖으로 throws를 통해서 던져서
명시적으로
처리해야 한다.- 이것은 문법적으로 강제적이다.
- CheckedException은 `Error와 RuntimeException을 상속받지 않은 Exception 들을 모두 포함한다.
Error
,FileNotFoundException
,ClassNotFoundException
Spring @Transaction 어노테이션 Rollback
기본 정책
이 Unchcked Exception과 error들이다.
즉 설정을 바꾸지 않으면CheckedException
은 Transaction 처리시에 Exception이 발생해도 Rollback을 하지 않는다.하지만 어떤 예외가 발생하면 롤백을 할 것이냐 말 것이냐는 개발자가 정하는 것이다.
- CheckedException들이 롤백이 안되는 것이 아니다.
- @Transactional(rollbackFor=Exception.class) 옵션으로 모든 예외에 대해서 롤백할 수 있다.
- Checked Exception을 try-catch문으로 더 구체적인 Unchecked Exception으로 감싸주면 롤백이 가능하다.
UncheckedException (확인되지 않은 예외)
RuntimeException을 상속받은 모든 예외 클래스들을 UnchckedException 이라고 한다.
예외가 발생할 수 있는 것이 확인되지 않기 때문에 처리할 방법을 고민해야 한다.
UncheckedException
은 명시적으로 예외 처리 해주지 않아도 되는Exception
으로, **Runtime
시점에서Exception
이 발생해야 확인되고, 컴파일 시점에는 확인되지 않는 예외이다.- 주로 프로그래머들의 실수나 예견되지 못한 값 처리 등, 잘못된 값 입력 등에 의해서 일어나는 예외이다.
- 그러니까 확인되지 않은 예외(UncheckedException)이다.
UncheckedException
은RuntimeException
을 상속받는Exception
들을 포함한다.NullPointerException
,ClassCastException
,IllegalArgumentException
등
Spring @Trasactional 어노테이션과 Rollback에 관련된 checkedException과 UncheckedException의 고찰
스프링 트랜잭셔널 어노테이션 과 예외들의 관계들을 정리한 블로그들을 보고 백기선님 영상을 보니까 뭔가 잘못 공부하고 있단 생각을 들었다
스프링프레임워크 @Transactionl 트랜잭션 사용 시 체크드 익셉션은 롤백 수행
x
, 언체크드 익셉션은 롤백 수행o
그런데 @Transactional 어노테이션 옵션을 보면 rollbackfor
와 같은 옵션들이 있다.
- 특정한 예외를 잡으면 롤백이 되도록 설정하는것.
이 rollbackfor를 Exception.class 으로 잡으면 어떻게 될까?
- 모든 Exception, 즉 CheckedException 까지 롤백을 하게 되는 것이다.
또한 noRollbackFor
라는 옵션이 있는데, 이걸로 특정 Unchecked Exception을 설정하게 되면?
- 어떻게 될것인가?
그럼 다시 생각해보면 저 *@Transactionl 트랜잭션 사용 시 체크드 익셉션은 롤백 수행 x
, 언체크드 익셉션은 롤백 수행 o
*라는 말은 부정확한 의미가 된다.
Spring @Transactional의 예외 발생 시
기본 rollback을 수행하는 정책
은 언체크드익셉션, 즉 RuntimeException과 그 하위 클래스들이고, 개발자가(우리) 비즈니스와 상황에 맞게 알맞게 처리할 수 있다.개발자는 상황에 맞게 예외를 처리할 수 있어야 하며, 스프링 트랜잭션도 그렇게 할 수 있도록 옵션을 지원한다.
rollbackFor, noRollbackFor 등
다시한번 정리하자면
Spring @Transactional의 예외 발생 시
기본 rollback을 수행하는 정책
은 UnchecedExceptiop, 즉 RuntimeException과 그 하위 클래스들이고, 개발자가(우리) 비즈니스와 상황에 맞게 알맞게 처리할 수 있게 rollbackFor, noRollbackFor. 옵션을 지원해 준다.
어디까지나 기본 정책이 체크드 익셉션은 롤백을 하지 않는것이고, 불가능한 것이 아니다.
스프링이 옵션을 제공하니까 우리는 그것을 알맞게 (상황에 맞게도 같은 말이 될 것 같다) 사용하면 되는 것이다.
우리는 문제는 상황에 맞게 다양하게 해결할 수 있어야 한다.
Checked Exception에서 Rollback이 안되는 이유
메소드 API를 설계할 때 해당 메소드 호출이 어떤 예외를 발생 시키는지 또한 API 규악의 중요한 내용이고, 때로는 그런 예외에 대한 처리를 호출자에게 강제할 수 있어야 한다는 뜻인 것 같다.
개발자가 컴파일 시 예측/처리 가능한 예외의 처리를 개발자에게 강제하기 위해 Checked Exception은 개발자가 처리하라 라는 뜻같다.
어노테이션을 사용하든 AOP에 설정을 하든 스프링은 Unchecked Exception(RuntimeException)과 Error 발생 시 롤백 적용을 기본 정책으로 한다.
@Override
public boolean rollbackOn(Throwable ex) {
return (ex instanceof RuntimeException || ex instanceof Error);
}
스프링에서 제공하는 트랜잭션 설정 클래스 DefaultTransactionAttribute 의 메소드 rollbackOn를 보면 RuntimeException과 Error인 경우에 true를 반환한다.
또한 @Transactional 어노테이션의 옵션들을 보면
/**
* Defines zero (0) or more exception {@linkplain Class classes}, which must be
* subclasses of {@link Throwable}, indicating which exception types must cause
* a transaction rollback.
* <p>By default, a transaction will be rolled back on {@link RuntimeException}
* and {@link Error} but not on checked exceptions (business exceptions). See
* {@link
...
*/
Class<? extends Throwable>[] rollbackFor() default {};
- will be rolled back on {@link RuntimeException} and {@link Error} - 런타임 엑셥과 에러들 (언체크드 익셉션)
- but not on checked exceptions (business exceptions). - 체크드 익셉션은 롤백 안함
@Transactional 어노테이션을 아무것도 설정하지 않은 default
사용하게 된다면 다음과 같이 기본 정책 적용된다
@Transactional(rollbackFor = {RuntimeException.class, Error.class})
public void save(AnyEntity entity) {
...
}
정리
컴파일 시점에~ | CheckedException (확인되는 예외) | UncheckedException (확인되지 않은 예외 ) |
---|---|---|
확인 시점 | Compile | Runtime |
처리 시점 | 반드시 예외 처리 | 명시적으로 하지 않아도 무관 |
예시 | ClassNotFoundException | RuntimeException, NPE |
스프링 @Transactional을 사용해서 트랜잭션 안에서 예외가 발생할 시,
Rollback 처리되는 기본 정책
의 예외들은 UncheckedException 이며 (RuntimeException, Error)
이 기본정책을 default로 사용하면 CheckedException들은 rollback 되지 않는다.
그러나 이 정책은 언제든지 변경할 수 있게 스프링에서
@Transactional( 옵션들 ) 에서 변경할 수 있고 개발자가 선택할 수 있으므로 상황에 맞게 적절하게 처리하면 된다.
- noRollbackFor, rollbaclFor 등등
'Java' 카테고리의 다른 글
Java - double brace (생성과 동시에 초기화, 함수호출) (0) | 2022.11.20 |
---|---|
Java List to String array. 리스트를 스트링으로 (0) | 2022.11.14 |
Java interface 사용 이유, interface의 장단점. (2) | 2022.09.29 |
Java 동시성 제어 - 멀티스레드, Syncronized, volatile, Atomic (0) | 2022.09.04 |