티스토리 뷰

728x90
반응형

목차

     

    Transaction

     

    • 더 이상 쪼갤 수 없는 일처리의 최소 단위 -> 모두 성공하거나 모두 실패해야 함
    • 안정성을 보장하기 위해 다음의 원칙을 지킨다.

      • 원자성 - 트랜잭션은 쪼갤 수 없으며 모두 성공하거나 모두 실패해야 한다.
      • 일관성 - DB에 대한 비즈니스 로직이 트랜잭션 전후로 일관되어야 한다.
      • 고립성 - 모든 트랜잭션은 다른 트랜잭션의 영향을 받지 않는다.
      • 지속성 - 성공한 트랜잭션의 결과는 안정적으로 보존되어야 한다. 작업 도중 시스템 오류가 발생해도 마찬가지다.
    • 커밋 - 모든 작업을 정상 처리하겠다고 확정하는 명령어. 결과를 DB에 저장하고 트랜잭션을 종료한다
    • 롤백 - 작업 중 문제가 발생하여 트랜잭션 처리과정의 모든 변경사항을 취소하겠다고 확정하는 명령어이다.
    • JPA 역시 Hibernate의 구현을 거친 트랜잭션을 통해 JDBC, DB와 상호작용 한다.

     

    @Transactional

     

    스프링에서 가장 간단하게 트랜잭션을 적용하는 방법이다. 필요한 클래스, 메서드에 해당 애너테이션을 추가한다.

     

    ...
    
    import org.springframework.transaction.annotation.Transactional;
    
    @Service
    @Transactional // 추가
    public class MemberService {
        private final MemberRepository memberRepository;
    
        public MemberService(MemberRepository memberRepository) {
            this.memberRepository = memberRepository;
        }
        ...
    }

    예를 들어 특정 레포지토리를 사용하는 클래스에 적용하면 해당 클래스에서 그 레포지토리에 접근하는

     

    모든 메서드에 트랜잭션이 적용된다.

     

    참고로 @Transactional은 예상하지 못한 Unchecked Error, 즉 런타임 에러만을 롤백하기 때문에

     

    Checked Exception은 catch후 예외 전략을 수립하거나 Unchecked Exception으로 감싸주어야 한다. 

     

    계속해서 @Transaction(readOnly = true)와 같이 읽기 전용 설정을 할 수 있으며,

     

    이 경우에도 commit은 정상적으로 실행된다(flush 되지 않을 뿐, 여기서 flush란 영속성 컨텍스트와 DB의 동기화 과정이다).

     

    메서드 레벨에도 당연히 같은 애너테이션으로 트랜잭션 설정을 할 수가 있으며,

     

    이 경우 메서드 레벨 → 클래스 레벨 순으로 애너테이션이 적용된다.

     

    추가로 서로 다른 클래스에 위치한 메서드도 호출 순서에 따라 하나의 트랜잭션으로 묶는 것이 가능하다.

     

    Transaction Propagation

     

    트랜잭션 전파란 위 경우처럼 특정 트랜잭션 내부에서 다른 트랜잭션을 실행할 경우의 설정이다.

     

    애너테이션의 propagation 속성으로 지정할 수 있으며, 대략 아래와 같은 유형이 존재한다.

     

    종류 설명 다이어그램
    REQUIRED(default) 부모 트랜잭션이 존재하면 합류
    없다면 새로운 트랜잭션 생성
    예외 발생시 전체 Rollback
    REQUIRES_NEW 무조건 새로운 트랜잭션 생성
    기존의 트랜잭션은 새 트랜잭션 종료까지 정지
    MANDATORY 부모 트랜잭션이 존재하면 합류
    없다면 예외 발생
    NOT_SUPPORTED 부모 트랜잭션이 있다면 메서드 이후까지 보류
    없다면 트랜잭션 생성하지 않음
    NEVER 부모 트랜잭션이 있다면 예외 발생
    없다면 트랜잭션 생성하지 않음

     

    Transaction Isolation Level

     

    트랜잭션 고립 수준은 말 그대로 트랜잭션의 고립 수준을 조정할 수 있는 옵션이다.

     

    애너테이션의 isolation 속성으로 지정 가능하며, 복수의 트랜잭션이 실행 중일 때

     

    특정 트랜잭션이 다른 트랜잭션에 접근할 수 있는 정도를 나타낸다.

     

    대략 아래와 같다.

     

    종류 설명
    REPEATABLE_READ(default) SELECT시 현재 시점의 스냅샷을 만들고 조회한다.
    즉, 반복해서 조회해도 같은 결과를 얻는다.
    트랜잭션 내에서 일관성을 보장한다.
    READ_UNCOMMITTED Commit 되지 않은 데이터에 다른 트랜잭션이 접근할 수 있다.
    Commit 이나 Rollback에 상관없이 현재의 데이터를 읽어온다.
    Rollback 될 데이터도 읽어올 수 있으므로 주의가 필요하다.
    READ_COMMITTED Commit 된 데이터에 다른 트랜잭션이 접근할 수 있다.
    구현 방식의 차이로 Query 수행 시점의 데이터와 정확하게 일치하지 않을 수 있다.
    대량의 데이터를 이동하거나 복제할 때 사용된다.
    SERIALIZABLE 동일 데이터에 대해 두 개 이상의 트랜잭션이 수행될 수 없다.
    가장 단순하고 엄격한 격리수준이다.

     

    AOP

     

    애너테이션 없이 트랜잭션을 적용하는 방법이다.

     

    Transaction Manager를 DI 받은 별개의 트랜잭션 설정 파일을 만들어 빈 등록을 시킨 뒤

     

    Transaction Interceptor 타입의 메서드를 빈 등록해 설정을 구성하고

     

    Advisor 타입의 메서드를 빈 등록해 포인트 컷을 지정하면 된다.

     

    각 방법의 장단점은 아래와 같다.

     

      @Transactional AOP
    장점 손쉽게 사용 가능
    원하는 곳에만 설정 가능
    포인트컷에 따른 일괄 적용으로 누락될 염려 없음
    외부 라이브러리에 적용 가능
    단점 애너테이션이 누락될 가능성
    애너테이션이 중첩될 경우 기능하지 않을 가능성이 있다.
    외부 라이브러리에 적용 불가
    원하는 곳만 골라서 적용하기 번거로움
    따라서 원하지 않는 데이터까지 롤백될 가능성이 있음

     

    반응형
    댓글
    공지사항
    최근에 올라온 글
    최근에 달린 댓글
    Total
    Today
    Yesterday
    링크
    «   2025/01   »
    1 2 3 4
    5 6 7 8 9 10 11
    12 13 14 15 16 17 18
    19 20 21 22 23 24 25
    26 27 28 29 30 31
    글 보관함