LostCatBox

Transaction 전파단계 학습

Word count: 403Reading time: 2 min
2025/11/26 Share

spring 에서 전파단계를 학습하여, Transaction을 더 잘 다뤄보자

테스트 상황

둘다 @Transactional을 의존하며,

PaymentService.processPayment() -> PointService.usePoint()를 호출한다.

1
2
3
graph LR

PaymentService.processPayment --> PointService.usePoint

테스트 방법

usePoint() 메서드의 @Transactional(propagation = XXX) 전파 단계를 바꿔가며,

상황 및 에러를 확인해보자

전파 단계별 특징과 예시

REQUIRED

  • 의미: 트랜잭션이 필요함(없으면 새로 만듬)

    • 기존 트랜잭션 없음: 새로운 트랜잭션을 생성함
    • 기존 트랜잭션이 있음: 기존 트랜잭션에 참여함
  • 예시

    • 각 메서드의 @Transactional 설정

      • processPayment()

        • @Transactional
        • Try-catch 문으로 usePoint()의 예외 처리됨
      • usePoint()

        • @Transactional
        • throw IllegalArgumentException("Treansactional 테스트용 예외")
    • 이 전파단계에서의 에러

      1
      org.springframework.transaction.UnexpectedRollbackException: Transaction silently rolled back because it has been marked as rollback-only

REQUIRES_NEW

  • 의미: 항상 새로운 트랜잭션이 필요함
    • 기존 트랜잭션 없음: 새로운 트랜잭션을 생성함
    • 기존 트랜잭션이 있음: 기존 트랜잭션을 보류시키고 새로운 트랜잭션을 생성함
  • 예시
    • 각 메서드의 @Transactional 설정
      • processPayment()
        • @Transactional
        • Try-catch 문으로 usePoint() 예외 처리완료.
      • usePoint()
        • @Transactional(propagation = Propagation.REQUIRES_NEW)
        • throw IllegalArgumentException("Treansactional 테스트용 예외")
    • 이 전파단계에서의 에러
      • 없음. -> rollback-only 마크가 상위 트랜잭션에게 전달되지않는다.

SUPPORTS

  • 의미: 트랜잭션이 있으면 지원함(트랜잭션이 없어도 됨)

    • 기존 트랜잭션 없음: 트랜잭션 없이 진행함
    • 기존 트랜잭션이 있음: 기존 트랜잭션에 참여함
  • 예시

    • 각 메서드의 @Transactional 설정

      • processPayment()
        • @Transactional
        • Try-catch 문으로 usePoint() 예외 처리완료.
      • usePoint()
        • @Transactional(propagation = Propagation.SUPPORTS)
        • throw IllegalArgumentException("Treansactional 테스트용 예외")
    • 이 전파단계에서의 에러 -> 기존 트랜잭션 존재했으므로 rollback-only marked

      1
      org.springframework.transaction.UnexpectedRollbackException: Transaction silently rolled back because it has been marked as rollback-only

NOT_SUPPORTED

  • 의미: 트랜잭션을 지원하지 않음(트랜잭션 없이 진행함)

    • 기존 트랜잭션 없음: 트랜잭션 없이 진행함
    • 기존 트랜잭션이 있음: 기존 트랜잭션을 보류시키고 트랜잭션 없이 진행함
  • 예시

    • 각 메서드의 @Transactional 설정

      • processPayment()

        • @Transactional
      • usePoint()

        • @Transactional(propagation = Propagation.NOT_SUPPORTED)
        • SQL 쿼리문 실행
    • 이 레벨에서의 에러 : Transaction 이 없어서 쿼리 실행불가

    1
    jakarta.persistence.TransactionRequiredException: Query requires transaction be in progress, but no transaction is known to be in progress

MANDATORY

  • 의미: 트랜잭션이 의무임(트랜잭션이 반드시 필요함)

    • 기존 트랜잭션 없음: IllegalTransactionStateException 예외 발생
    • 기존 트랜잭션이 있음: 기존 트랜잭션에 참여함
  • 예시

    • 각 메서드의 @Transactional 설정

      • processPayment()
        • X
      • usePoint()
        • @Transactional(propagation = Propagation.MANDATORY)
        • SQL 쿼리문 실행
    • 이 전파단계에서의 에러 :

      1
      org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory'

NEVER

  • 의미: 트랜잭션을 사용하지 않음(기존 트랜잭션도 허용하지 않음)

    • 기존 트랜잭션 없음: 트랜잭션 없이 진행
    • 기존 트랜잭션이 있음: IllegalTransactionStateException 예외 발생
  • 예시

    • 각 메서드의 @Transactional 설정
      • processPayment()
        • @Transactional
      • usePoint()
        • @Transactional(propagation = Propagation.NEVER)
        • SQL 쿼리문 실행
    • 이 전파단계에서의 에러 :
    1
    org.springframework.transaction.IllegalTransactionStateException: Existing transaction found for transaction marked with propagation 'never'
CATALOG
  1. 1.
  2. 2. 테스트 상황
  3. 3. 테스트 방법
  4. 4. 전파 단계별 특징과 예시
    1. 4.1. REQUIRED
    2. 4.2. REQUIRES_NEW
    3. 4.3. SUPPORTS
    4. 4.4. NOT_SUPPORTED
    5. 4.5. MANDATORY
    6. 4.6. NEVER