You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
스프링 기본적으로 체크 예외는 비즈니스 의미가 있을때 사용하고 런타임(언체크) 예외는 복구 불능한 예외로 가정한다.
체크 예외 : 비즈니스 의미가 있을때 사용
언체크 예외 : 복구 불가능한 예외 - 공통 처리
참고로 꼭 이런 정책을 다 따를 필요는 없다. 그때는 앞서 배운 rolllbackFor 이라는 옵션을 사용해서 체크 예외도 롤백하면 된다.
그런데 비즈니스 의미가 있는 **“비즈니스 예외”**라는 것이 무슨 뜻일까? 간단한 예제로 알아보자
“비즈니스 요구사항”
주문을 하는데 상황에 따라 다음과 같이 조치한다.
“정상” : 주문시 결제를 성공하면 주문 데이터를 저장하고 결제 상태를 ‘완료’로 처리한다.
“시스템 예외” : 주문시 내부에 복구 불가능한 예외가 발생하면 전체 데이터를 롤백한다.(runtime exception)
“비즈니스 예외” : 주문시 결제 잔고가 부족하면 주문 데이터를 저장하고 결제 상태를 “ 대기”로 처리한다.
이 경우 “고객에게 잔고 부족을 알리고 별도의 계좌로 입금하도록 안내한다.”
이때 결제 잔고가 부족하면 NotEnoughMoneyException 이라는 체크 예외가 발생한다고 가정한다. 이 예외는 시스템에 문제가 있어서 발생하는 시스템 예외가 아니다. 시스템은 정상 동작했지만 비즈니스 상황에서 문제가 되기 때문에 발생한 예외이다. 더 자세히 설명하자면, 고객의 잔고가 부족한 것은 시스템에 문제가 있는 것이 아니다. 오히려 시스템은 문제 없이 동작한것이고, 비즈니스 상황이 예외인것이다. 이런 예외를 비즈니스 예외라 한다. 그리고 비즈니스 예외는 매우 중요하고 반드시 처리해야 하는 경우가 많으므로 체크 예외을 고려할 수 있다.
시스템 예외 : 시스템적 장애, 예외로 인한 예외
비즈니스 예외 : 비즈니스적으로 정상 플로우를 못타는 예외
실제 코드로 알아보자 > 테스트를 제외하고 src/main 에 작성하기
packagehello.springtx.order;
importlombok.RequiredArgsConstructor;
importlombok.extern.slf4j.Slf4j;
importorg.springframework.stereotype.Service;
importorg.springframework.transaction.annotation.Transactional;
@Slf4j@Service@RequiredArgsConstructorpublicclassOrderService {
privatefinalOrderRepositoryorderRepository;
//JPA는 트랜잭션 커밋 시점에 Order 데이터를 DB에 반영한다.@Transactionalpublicvoidorder(Orderorder) throwsNotEnoughMoneyException {
log.info("order 호출");
orderRepository.save(order);
log.info("결제 프로세스 진입");
if (order.getUsername().equals("예외")) {
log.info("시스템 예외 발생");
thrownewRuntimeException("시스템 예외");
}elseif(order.getUsername().equals("잔고부족")) {
log.info("잔고부족 비즈니스 예외 발생");
order.setPayStatus("대기");
thrownewNotEnoughMoneyException("잔고가 부족합니다."); // 예외 던지기
}else {
//정상 승인log.info("정상 승인");
order.setPayStatus("완료");
}
log.info("결제 프로세스 완료");
}
}
여러 상황을 만들기 위해서 사용자 이름(’username’) 에 따라서 처리 프로세스를 다르게 했다.
기본 : payStatus 를 완료 상태롤 처리하고 정상 처리된다.
예외 : RuntimeException(”시스템 예외”) 런타임 예외가 발생한다.
잔고부족 :
payStatus를 “대기”상태로 처리한다.
NotEnoughMoneyException(”잔고가 부족합니다.”) 체크 예외가 발생한다.
잔고 부족은 payStatus를 대기 상태로 두고 체크 예외가 발생하지만 , order 데이터는 커밋되기를 기대한다.
NotEnoughMMoneyException은 시스템에 문제가 발생한게 아니라 비즈니스 문제 상황을 예외를 통해 알려준다. 마치 return값처럼 사용된다.(return으로 바꿔도 된다.) 따라서 이 경우에는 트랜잭션을 커밋하는 것이 맞다. 이 경우 롤백하면 생성한 Order자체가 사라진다. 그러면 고객에게 잔고부족을 알리고 별도의 계좌로 입금하도록 안내해도 주문(’Order’)자체가 사라지기 때문에 문제가 된다.
그런데 비즈니스 상황에 따라 체크 예외의 경우에도 트랜잭션을 커밋하지 않고, 롤백하고 싶을 수도 있다. 이때는 rollbackFor 옵션을 사용하면 된다.
런타임 예외는 항상 롤백된다. 체크 예외의 경우 rollbackFor 옵션을 사용해서 비즈니스 상황에 따라서 커밋과 롤백을 선택하면 된다.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
예외와 트랜잭션 커밋, 롤백 - 기본
예외가 발생했는데 내부에서 예외처리를 하지 못하고 트랜잭션 범위(’@transactional’ 가 적용된 AOP’) 밖으로 예외를 던지면 어떻게 될까?

예외 발생시 스프링 트랜잭션 AOP는 예외의 종류에 따라 트랜잭션을 커밋하거나 롤백한다.
실제 이렇게 동작하는지 코드로 확인
결과

트랜잭션이 커밋, 롤백되었는지 로그로 확인하는 방법이 있다.
application.properties
.JpaTransactionManager가 로그를 남긴다.

핵심은 Creating new transaction

밑에 세개가 다 끝난 후에 completing 된다.

RuntimeException 덕에 Rolling back 이 터짐
코드 runtimeException() 실행 : 런타임 예외
결과
코드 checkedException () 실행 : 체크 예외
결과
코드 rollbackFor() 실행 : 체크 예외를 강제로 롤백
결과
예외와 트랜잭션 커밋, 롤백 - 활용
스프링은 왜 체크예외는 commit, 언체크(런타임)에러는 rollback 할까?
스프링 기본적으로 체크 예외는 비즈니스 의미가 있을때 사용하고 런타임(언체크) 예외는 복구 불능한 예외로 가정한다.
참고로 꼭 이런 정책을 다 따를 필요는 없다. 그때는 앞서 배운
rolllbackFor이라는 옵션을 사용해서 체크 예외도 롤백하면 된다.그런데 비즈니스 의미가 있는 **“비즈니스 예외”**라는 것이 무슨 뜻일까? 간단한 예제로 알아보자
“비즈니스 요구사항”
주문을 하는데 상황에 따라 다음과 같이 조치한다.
이때 결제 잔고가 부족하면
NotEnoughMoneyException이라는 체크 예외가 발생한다고 가정한다. 이 예외는 시스템에 문제가 있어서 발생하는 시스템 예외가 아니다. 시스템은 정상 동작했지만 비즈니스 상황에서 문제가 되기 때문에 발생한 예외이다. 더 자세히 설명하자면, 고객의 잔고가 부족한 것은 시스템에 문제가 있는 것이 아니다. 오히려 시스템은 문제 없이 동작한것이고, 비즈니스 상황이 예외인것이다. 이런 예외를 비즈니스 예외라 한다. 그리고 비즈니스 예외는 매우 중요하고 반드시 처리해야 하는 경우가 많으므로 체크 예외을 고려할 수 있다.실제 코드로 알아보자 > 테스트를 제외하고
src/main에 작성하기여러 상황을 만들기 위해서 사용자 이름(’username’) 에 따라서 처리 프로세스를 다르게 했다.
payStatus를 완료 상태롤 처리하고 정상 처리된다.RuntimeException(”시스템 예외”)런타임 예외가 발생한다.payStatus를 “대기”상태로 처리한다.NotEnoughMoneyException(”잔고가 부족합니다.”)체크 예외가 발생한다.payStatus를 대기 상태로 두고 체크 예외가 발생하지만 ,order데이터는 커밋되기를 기대한다.테스트 코드
실행해보면 테이블을 만드는데
Hibernate 가 실행하는 SQL을 다 로그로 남긴다.
결과

별도의 설정이 없으면 자동 테이블 생성 기능이 있다.( 메모리 DB)
참고로 테이블 자동생성은 application.properties에
spring.jpa.hibernate.ddl-auto옵션을 조정할 수 있다.none: 테이블을 생성하지 않는다.create: 애플리케이션 시작 시점에 테이블을 생성한다.정상처리


런타임예외
결과

트랜잭션 commit 될때 insert 쿼리 없어진다.
결과

정리
NotEnoughMMoneyException은 시스템에 문제가 발생한게 아니라 비즈니스 문제 상황을 예외를 통해 알려준다. 마치 return값처럼 사용된다.(return으로 바꿔도 된다.) 따라서 이 경우에는 트랜잭션을 커밋하는 것이 맞다. 이 경우 롤백하면 생성한Order자체가 사라진다. 그러면 고객에게 잔고부족을 알리고 별도의 계좌로 입금하도록 안내해도 주문(’Order’)자체가 사라지기 때문에 문제가 된다.rollbackFor옵션을 사용하면 된다.rollbackFor옵션을 사용해서 비즈니스 상황에 따라서 커밋과 롤백을 선택하면 된다.정리
프록시 도입 후 전체 과정> 이해하기
트랜잭션 적용 확인
트랜잭션 적용 위치
트랜잭션 AOP 주의사항 - 프록시 내부 호출
스프링에서 AOP기능은 public 메서드에서만 적용된다.
AOP 초기화 시점 주의
트랜잭션 옵션들
예외, 트랜잭션 커밋, 롤백 - 기본
예외, 트랜잭션 커밋, 롤백 - 활용
명령어
ctrl +shift + T: Test 만들기창ctrl + alt + V: Extract / IntroduceAll reactions