티스토리 뷰

@Transactional 사용시 주의사항

  • @Transactional을 클래스 또는 메써드 레벨에 명시하면 해당 메써드 호출시 지정된 트랜잭션이 작동하게 된다. 단, 조건이 있다. 해당 클래스의 Bean을 다른 클래스의 Bean에서 호출할 때만 @Transactional을 인지하고 작동하게 된다.(같은 빈 내에서 @Transactional이 명시된 다른 메써드를 호출해도 작동하지 않는다.) Spring Framework는 내부적으로 AOP를 통해 해당 어노테이션을 인지하여 프록시를 생성하여 트랜잭션을 자동 관리하기 때문이다. [관련 링크1] [관련 링크2]

Propagation.REQUIRED

@Transactional(propagation = Propagation.REQUIRED)
public void doSomething() { ... }
  • 특정 메써드의 트랜잭션이 Propagation.REQUIRED로 설정되었을 때의 트랜잭션 동작은 다음과 같다. 기본적으로 해당 메써드를 호출한 곳에서 별도의 트랜잭션이 설정되어 있지 않았다면 트랜잭션를 새로 시작한다.(새로운 연결을 생성하고 실행한다.) 만약, 호출한 곳에서 이미 트랜잭션이 설정되어 있다면 기존의 트랜잭션 내에서 로직을 실행한다.(동일한 연결 안에서 실행된다.) 예외가 발생하면 롤백이 되고 호출한 곳에도 롤백이 전파된다. 이러한 Propagation.REQUIRED 동작 방식을 원할 경우 기본값으로 설정되어 있기 때문에 생략해도 된다. [관련 링크]
  • 만약, 해당 메써드가 호출한 곳와 별도의 쓰레드라면 어떤 동작이 일어날까? 답은 전파 레벨과 상관 없이 무조건 별도의 트랜잭션을 생성하여 해당 메써드를 실행한다. Spirng은 내부적으로 트랜잭션 정보를 ThreadLocal 변수에 저장하기 때문에 다른 쓰레드로 트랜잭션이 전파되지 않는다. [관련 링크1] [관련 링크2] [관련 링크3]

Propagation.REQUIRES_NEW

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void doSomething() { ... }
  • Propagation.REQUIRES_NEW로 설정되었을 때에는 매번 새로운 트랜잭션을 시작한다.(새로운 연결을 생성하고 실행한다.) 만약, 호출한 곳에서 이미 트랜잭션이 설정되어 있다면(기존의 연결이 존재한다면) 기존의 트랜잭션은 메써드가 종료할 때까지 잠시 대기 상태로 두고 자신의 트랜잭션을 실행한다. 새로운 트랜잭션 안에서 예외가 발생해도 호출한 곳에는 롤백이 전파되지 않는다. 즉, 2개의 트랜잭션은 완전히 독립적인 별개로 단위로 작동한다. [관련 링크1] [관련 링크2]

Propagation.NESTED

@Transactional(propagation = Propagation.NESTED)
public void doSomething() { ... }
  • Propagation.NESTED는 기본적으로 앞서 설명한 Propagation.REQUIRED와 동일하게 작동한다. 중요한 차이점은, SAVEPOINT를 지정한 시점까지 부분 롤백이 가능하다는 것이다. 유의할 점은, 데이터베이스가 SAVEPOINT 기능을 지원해야 사용이 가능하다. (대표적으로 Oracle이 해당한다.)

참고 글

댓글
댓글쓰기 폼