본문 바로가기
Spring

Spring의 @Transactional

by setung 2021. 12. 15.
728x90

Transaction 이란

여러 쿼리를 논리적으로 하나의 작업 단위로 묶는 것을 의미한다.

예로 계좌 이체가 있다. 적어도 보내는 사람과 받는 사람의 계좌는 업데이트가 되어야 한다.

이 두 번의 DB 작업을 논리적으로 하나의 작업으로 묶는 것이다.

 

Transaction 성질

원자성 : 트랜잭션의 쿼리 결과들이 모두 반영되거나, 모두 반영되지 않아야 한다.

일관성 : 트랜잭션은 일관성 있는 데이터베이스 상태를 유지한다.

격리성 : 동시에 실행되는 트랜잭션들이 서로 영향을 미치지 않도록 격리해야 한다.

지속성 : 트랜잭션을 성공적으로 마치면 결과가 항상 저장되어야 한다.

 

Spring의 @Transactional

Mybatis, hiberbate, jdbcTemplate 디비 접근 기술에 따라 트랜잭션을 적용하는 코드가 다 제각각이다. 그래서 스프링에선 @Transactional이란 추상 서비스를 제공한다. @Transational은 클래스와 메서드 단위에 적용이 가능하며 어노테이션을 붙이게 되면 Proxy를 만들게 된다. 즉 PSA와 AOP인 셈이다.

 

@Transactional의 속성

[Isolation (트랜잭션 격리)]

트랜잭션에서 일관성 없는 데이터 허용 수준을 설정한다

▶ default

  • DB의 Isolation Level을 따른다.

 Read_Uncommited (lv.0)

  • 가장 낮은 격리 수준으로 커밋되지 않는 트랜잭션의 데이터 읽기를 허용한다.
  • 동기 작업이 없기 때문에 속도가 빠르다.
  • Dirty Read, Non-Repeatable Read, Phantom Read 이슈로 데이터 불일치 위험이 있다.

 Read_Committed(lv.1)

  • 커밋이 완료된 트랜잭션의 변경사항만 다른 트랜잭션에서 조회 가능하다.
  • 트랜잭션이 값을 변경하고 커밋하는 시점마다 다른 트랜잭션에서 데이터 조회 시 불일치가 나타날 수 있다. (Non-Repeatable Read)
  • Drity Read 방지하지만 Non-Repeatable Read, Phantom Read 이슈가 있다.

 REPEATABLE_READ (level 2)

  • 트랜잭션 범위 내에서 조회한 내용이 항상 동일함을 보장한다.
  • 하지만 새로 추가되거나 삭제된 데이터를 제한하지 않는다. (Phantom Read)
  • Drity Read, Non-Repeatable Read 방지하지만 Phantom Read 이슈가 있다.

 SERIALIZABLE (level 3)

  • 가장 강력한 트랜잭션 격리 수준으로 한 트랜잭션에서 사용하는 데이터를 다른 트랜잭션에서 접근을 막는다.
  • Drity Read, Non-Repeatable Read, Phantom Read 방지한다.

레벨이 높아질수록 데이터 무결성은 유지하나 그만큼 성능에 불리하다.

상황에 맞게 적절한 격리 레벨을 사용하는 것이 중요하겠다.

 

[propagation (전파 옵션) ]

트랜잭션을 생성 및 호출에 대한 설정이다.
부모의 트랜잭션을 그대로 사용하거나 새로운 트랜잭션을 생성할 수 있다.

▶ REQUIRED

  • 부모 트랜잭션이 존재한다면 부모 트랜잭션의 속성을 따르고, 그렇지 않다면 새로운 트랜잭션을 생성한다.

▶ SUPPORTS

  • 부모 트랜잭션이 존재한다면 부모 트랜잭션의 속성을 따르고, 그렇지 없다면 새로 트랜잭션을 생성하지 않는다.

▶ REQUIRES_NEW

  • 부모 트랜잭션 유무와 상관없이 항상 새로운 트랜잭션을 생성한다. 
  • 부모 트랜잭션이 존재한다면 새로 만든 트랜잭션 작업이 끝날 때까지 보류시킨다.

▶ MANDATORY

  • 부모 트랜잭션을 따르며, 부모 트랜잭션이 존재하지 않다면 예외를 발생시킨다. 

▶ NOT_SUPPORTED

  • 트랜잭션을 사용하지 않고, 부모 트랜잭션이 있다면 보류시킨다.

▶ NEVER

  • 트랜잭션을 절대 사용하지 않는다.
  • 부모 트랜잭션이 존재한다면 예외를 발생시킨다.

▶ NESTED

  • REQUIRES_NEW처럼 새로운 트랜잭션을 만든다.
  • 새로운 트랜잭션은 부모 트랜잭션의 커밋과 롤백에 영향을 받는다. 하지만 새로운 트랜잭션의 커밋과 롤백은 부모 트랜잭션에 영향을 주지 않는다.

 

[readOnly 속성]

트랜잭션을 읽기 전용으로 설정한다.
Insert, Update, Delete 작업이 진행되면 예외가 발생한다.
읽기 전용 트랜잭션의 성능은 기본 트랜잭션보다 성능이 좋다. 

 

[timeout 속성 ]

지정한 시간 내에 트랜잭션 처리를 수행하지 못할 경우 Rollback을 수행한다.
기본값은 -1이며 timeout을 사용하지 않는다는 의미이다.

 

[트랜잭션 롤백 예외]

 noRollbackFor

특정 예외 발생 시 rollback하지 않는다.

 

 rollbackFor

특정 예외 발생 시 rollback 한다.

 

Checked Exception 같은 경우 예외 처리를 강제하기 때문에 스프링에선 하나의 로직이라 보고 롤백시키지 않는다. UnChecked Exception은 예외를 강제하지 않는 예상치 못한 예외로 보기 때문에 롤백시킨다.

728x90

'Spring' 카테고리의 다른 글

Spring Data Jpa의 N+1 문제  (0) 2022.02.07
JDK Dynamic Proxy와 CGLIB  (0) 2021.12.07
Spring AOP  (0) 2021.12.02
Spring Boot에 Redis Cache 적용해보기  (0) 2021.11.25
Spring JPA Specification을 사용해 유연하게 조회 API 만들기  (3) 2021.11.08