ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • @Transaction
    Spring&SpringBoot 2025. 11. 13. 08:39

    트랜잭션 추상화

    // JDBC 트랜잭션 코드 예시
    public void accountTransfer(String fromId, String toId, int money) throws SQLException {
        Connection con = dataSource.getConnection();
        try {
            con.setAutoCommit(false); //트랜잭션 시작
            
            //비즈니스 로직
            bizLogic(con, fromId, toId, money);
            con.commit(); //성공시 커밋
        } catch (Exception e) {
            con.rollback(); //실패시 롤백
            throw new IllegalStateException(e);
        } finally {
            release(con);
        }
    }
    
    // JPA 트랜잭션 코드 예시
    public static void main(String[] args) {
        //엔티티 매니저 팩토리 생성
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpabook");
        EntityManager em = emf.createEntityManager(); //엔티티 매니저 생성
        EntityTransaction tx = em.getTransaction(); //트랜잭션 기능 획득
        
        try {
            tx.begin(); //트랜잭션 시작
            logic(em);  //비즈니스 로직
            tx.commit();//트랜잭션 커밋
        } catch (Exception e) {
            tx.rollback(); //트랜잭션 롤백
        } finally {
            em.close(); //엔티티 매니저 종료
        }
        emf.close(); //엔티티 매니저 팩토리 종료
    }
    • JDBC 트랜잭션에 의존하다가 JPA 기술로 변경하게 되면 서비스 계층의 트랜잭션을 처리하는 코드도 모두 함께 변경해야 한다

     

     

    스프링의 트랜잭션 추상화

    • 스프링 트랜잭션 추상화의 핵심은 PlatformTransactionManager 인터페이스
      • org.springframework.transaction.PlatformTransactionManager 

     

     

    트랜잭션 동기화

    스프링이 제공하는 트랜잭션 매니저

    • 트랜잭션 추상화
    • 리소스 동기화

    • 스프링은 트랜잭션 동기화 매니저를 제공한다
    • 트랜잭션 동기화 매니저는 쓰레드 로컬을 사용하여 커넥션을 동기화한다 따라서 멀티쓰레드 환경에서 안전하게 커넥션을 동기화할 수 있다

     

     

    트랜잭션 매니저의 전체 동작 흐름

    • 클라이언트 요청으로 서비스 로직 시작
    • 서비스 계층에서 transactionManger.getTransaction()을 호출해 트랜잭션 시작
    • 트랜잭션 매니저는 내부에서 데이터소스를 사용해서 커넥션 생성
    • 커넥션을 수동 커밋모드로 변경해서 실제 데이터베이스 트랜잭션 시작
    • 커넥션을 트랜잭션 동기화 매니저에 보관
    • 트랜잭션 동기화 매니저는 쓰레드 로컬에 커넥션 보관

    • 서비스는 비즈니스 로직 실행하면서 리포지토리 메서드 호출
    • 리포지토리 메서드는 트랜잭션이 시작된 커넥션이 필요하기 때문에 DataSourceUtils.getConnection() 사용해 트랜잭션 동기화 매니저에 보관된 커넥션을 꺼내 사용
    • 획득한 커넥션을 통해 SQL을 DB에 전달 후 실행

    • 비즈니스 로직 끝나면 트랜잭션을 종료하고 트랜잭션은 커밋/롤백하면 종료
    • 트랜잭션을 종료하기 위해 동기화된 커넥션이 필요해 트랜잭션 동기화 매니저를 통해 동기화된 커넥션을 획득
    • 획득한 커넥션을 통해 데이터베이스에 트랜잭션을 커밋하거나 롤백
    • 전체 리소스 정리

     

     

    트랜잭션 템플릿

    public class TransactionTemplate {
        private PlatformTransactionManager transactionManager;
    
        public <T> T execute(TransactionCallback<T> action){..}
        void executeWithoutResult(Consumer<TransactionStatus> action){..}
    }

     

     

    트랜잭션 AOP

    • 프록시를 사용하면 트랜잭션을 처리하는 객체와 비즈니스 로직을 처리하는 서비스 객체를 명확히 분리할 수 있다
    • 스프링이 제공하는 트랜잭션 AOP - @Transactional 애노테이션
      • org.springframework.transaction.annotation.Transactional

     

     

    • 트랜잭션 AOP 적용 전체 흐름
    • 선언적 트랜잭션 관리(Declarative Transaction Management)

     

     

    데이터소스, 트랜잭션 매니저 직접 등록

    # application.properties
    spring.datasource.url=jdbc:h2:tcp://localhost/~/test
    spring.datasource.username=sa
    spring.datasource.password=
    @Slf4j
    @SpringBootTest
    class MemberServiceV3_4Test {
        @TestConfiguration
        static class TestConfig {
            private final DataSource dataSource;
            public TestConfig(DataSource dataSource) {
                this.dataSource = dataSource;
            }
            
            @Bean
            MemberRepositoryV3 memberRepositoryV3() {
                return new MemberRepositoryV3(dataSource);
            }
            
            @Bean
            MemberServiceV3_3 memberServiceV3_3() {
                return new MemberServiceV3_3(memberRepositoryV3());
            }
        }
        ...
    }
    • 스프링부트가 application.properties에 지정된 속성을 참고해서 데이터소스와 트랜잭션 매니저를 자동으로 생성한다 
    • 프로그래밍 방식의 트랜잭션 관리(programmatic transaction management)
      • 테스트 시에 가끔 사용
    728x90

    'Spring&SpringBoot' 카테고리의 다른 글

    데이터 접근 기술 - 스프링 데이터 JPA  (0) 2025.11.20
    트랜잭션 커밋/롤백과 예외  (0) 2025.11.20
    트랜잭션, DB 락  (0) 2025.11.12
    JDBC  (0) 2025.11.12
    스프링 AOP 실무 주의사항  (0) 2025.10.21
Designed by Tistory.