본문 바로가기
Spring

Spring의 @Transactional

by setung 2021. 12. 15.

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은 예외를 강제하지 않는 예상치 못한 예외로 보기 때문에 롤백시킨다.

'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

댓글