본문 바로가기

Back-End/토비의 스프링3

6-6. 트랜잭션 속성 & 6-7. 어노테이션 트랜잭션 속성과 포인트컷

이전 포스팅에서 스프링의 트랜잭션 추상화를 설명하면서 넘어간게 하나 있다.

트랜잭션 매니저에서 트랜잭션을 가져올 때 사용한 DefaultTransactionDefinition 오브젝트다.

 

트랜잭션 정의

더 이상 쪼갤 수 없는 최소 단위의 작업이라는 점에서 모두 같은 개념이지만, 트랜잭션의 동작방식을 제어할 수 있는 다른 몇가지 조건이 있다.

 

트랜잭션 전파 ( Transaction Propagation )

트랜잭션의 경계에서 이미 진행 중인 트랜잭션이 있을 때 또는 없을 때 어떻게 동작할지 결정하는 방식

 

예제 : A 트랜잭션이 끝나지 않은 시점에서 B를 호출했다면 B는 어떤 트랜잭션 안에서 동작할까?

 

  1. A+B 하나의 트랜잭션으로 처리 : (2)에서 에러가 나면 B도 롤백이 된다.
  2. A / B 별도의 트랜잭션으로 처리 : (2)에서 에러가 나도 B 결과에는 영향을 주지 않는다

  • PROPAGATION_REQUIRED
    • 가장 많이 사용되는 속성 ( default 값 )
    • 진행 중인 트랜잭션이 있으면 참여하고, 없으면 새로 시작
  • PROPAGATION_REQUIRES_NEW
    • 항상 새로운 트랜잭션을 시작
    • 독립적인 트랜잭션이 보장되어야 하는 경우
  • PROPAGATION_NOT_SUPPORTED
    • 트랜잭션 없이 동작, 진행 중인 트랜잭션이 있어도 무시
    • 트랜잭션 없이 동작하게 할거면 뭐하러 경계 설정을 함?
    • 포인트컷을 이용하여 특정 메소드가 AOP 적용대상이 되지 않도록 할 수 있지만 그럼 포인트컷이 상당히 복잡해짐 ( 사실 아직 와닿지는 않는다. )

격리 수준 ( Isolation Level )

서버 환경에서 여러 개의 트랜잭션이 동시에 진행 될 수 있다. 가능하다면 모든 트랜잭션이 순차적으로 진행돼서 다른 트랜잭션에 독립적이면 좋겠지만, 이렇게 되면 성능이 크게 떨어질 수 있다. 그렇기 때문에 적절한 격리 수준 설정이 필요하다.

 

기본 격리 수준은 DB나 Datasource에 설정되어 있는 디폴트 격리수준을 따른다는 DefaultTransactionDefinition에 설정된 ISOLATION_DEFAULT이다. 디폴트 격리수준을 따르는게 좋지만, 특별한 작업을 수행하는 메소드의 경우는 독자적인 격리 수준을 지정할 필요가 있다.

 

제한시간

트랜잭션을 수행하는 제한시간(timeout)을 설정할 수 있다.

기본 설정은 제한 시간이 없다.

제한 시간은 트랜잭션을 직접 시작할 수 있는 PROPAGATION_REQUIRED, PROPAGATION_REQUIRES_NEW와 함께 사용해야 의미가 있다.

 

읽기전용

트랜잭션 내에서 데이터를 조작하는 시도를 막아줄 수 있다. 또한 데이터 액세스 기술에 따라서 성능이 향상될 수 있다.

 

Annotation 트랜잭션 속성과 포인트컷

가끔은 메소드에 따라 제각각 속성이 다른, 세밀하게 튜닝된 트랜잭션 속성을 적용해야 하는 경우가 있다. 이런 경우라면 메소드 이름 패턴을 이용해서 일괄적으로 트랜잭션 속성을 부여하는 방식은 적합하지 않다. 매번 포인트컷과 어드바이스를 새로 추가해줘야 하기 때문이다.

 

@Transactional

 

 

트랜잭션 속성을 정의하는 것이지만, 동시에 포인트컷의 자동등록에도 사용된다.

 

트랜잭션 부가기능 적용 단위는 '메소드'이다.

  • 문제 1 : 코드가 지저분해짐
  • 문제 2 : 같은 설정을 여기저기서 반복함

대체 정책

(5.6) -> (4) -> (2.3) -> (1) 순서로 @Transactional이 부여됐는지 확인하고 있다면 이 속성을 적용한다.

  • 구현 방법 1 - interface에 @Transactional을 두기
    • 구현 클래스가 바뀌어도 트랜잭션 속성을 유지할 수 있는 장점
  • 구현 방법 2 - 타깃 클래스나 타깃 메소드에 적용하기
    • 마음이 편함

@Transactional 적용 대상은 클라이언트가 사용하는 인터페이스가 정의한 메소드이므로 인터페이스에 두는게 바람직하다. 하지만 인터페이스를 사용하는 프록시 방식의 AOP가 아닌 방식으로 적용하면 인터페이스에 정의한 @Transactional은 무시되게 때문에 클래스에 선언하는 것을 권장한다(??)

 

트랜잭션 Annotation 적용

  • 트랜잭션 설정이 직관적이고 간단해 보임, 편하다.
  • 단점 1 - 트랜잭션 적용 대상 손쉽게 파악 불가
  • 단점 2 - 사용 정책을 잘 만들어 두지 않으면 무분별하게 사용하거나 자칫 빼먹을 위험