라티의 작은 일기장

패스트캠퍼스 환급챌린지 6일차 미션 (2월 6일) : 10개 프로젝트로 시작하는 백엔드 웹개발 : 신입 개발자 취업 집중반 강의 후기 본문

Spring(Java)

패스트캠퍼스 환급챌린지 6일차 미션 (2월 6일) : 10개 프로젝트로 시작하는 백엔드 웹개발 : 신입 개발자 취업 집중반 강의 후기

코드라티 2025. 2. 6. 23:24

본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성하였습니다.

https://bit.ly/4gL1f1o

 

오늘은 트랜잭션 매니저와, 선언적 / 명시적으로 트랜잭션을 활용하는 방법, @Transactional 어노테이션을 활용한 트랜잭션 관리에서 주의할 점 등을 골고루 학습했다.

 

트랜잭션 매니저는 Service Layer에서 작성되는 비즈니스 로직이 특정 기술에 종속적으로 작성되면 안되기 때문에, (중간에 모종의 이유로 채택한 기술이 변경되었을 때 유연하게 기존 코드를 마이그레이션하기 위해서일듯) 독립적으로 트랜잭션과 관련된 로직을 Service Layer에서 관리하기 위해 필요하다. 즉, 트랜잭션 기능에 대한 추상화가 적용된 결과라고 할 수 있다.

 

connection 생성, commit, rollback 등 트랜잭션에서 수행되어야하는 로직을 트랜잭션 매니저가 대신 수행해주고(물론 메소드 호출은 필요), 특정 기술에 의존적인 Datasource를 주입받지 않아도 되는 장점이 있다.

 

public class AccountService {
    private final PlatformTransactionManager transactionManager;

    public AccountService(PlatformTransactionManager transactionManager) {
        this.transactionManager = transactionManager;
    }

    public void transferFunds(Account from, Account to, double amount) {
        TransactionStatus status = transactionManager.getTransaction(
            new DefaultTransactionDefinition()
        );

        try {
            // 비즈니스 로직 수행
            withdraw(from, amount);
            deposit(to, amount);
            
            transactionManager.commit(status);
        } catch (Exception e) {
            transactionManager.rollback(status);
            throw new RuntimeException("Transfer failed", e);
        }
    }
}

 

다만 connection을 생성하고, commit과 rollback을 특정 상황에서 실행하고 close를 하기 위해 트랜잭션 매니저가 제공하는 메소드의 호출이 불가피한데, 이 문제를 해결하기 위해서는 TransactionTemplate을 활용하면 된다.

 

이름에서도 알 수 있듯이, 위에서 언급했던 트랜잭션에서 필수적인 로직들을 대신 호출해주는 녀석이다.

TransactionTemplate을 사용하면, 개발자는 추상화 레벨 최상단에서 비즈니스 로직을 구현하기만 하면 되는것이다.

public class OrderService {
    private final TransactionTemplate transactionTemplate;

    public OrderService(PlatformTransactionManager transactionManager) {
        this.transactionTemplate = new TransactionTemplate(transactionManager);
        this.transactionTemplate.setTimeout(30); // 30초 타임아웃 설정
    }

    public void placeOrder(Order order) {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                try {
                    inventoryService.reduceStock(order);
                    paymentService.processPayment(order);
                    orderRepository.save(order);
                } catch (OutOfStockException ex) {
                    status.setRollbackOnly(); // 명시적 롤백
                    throw ex;
                }
            }
        });
    }
}

 

또한 서버의 성능 최적화를 위해 주로 읽기 전용, 쓰기 전용의 transactionTemplate을 만들어서 관리한다고 한다.

 

 

 

 

 

학습 시작 인증

 

학습 종료 인증

 

첫 번째 클립 수강 인증

 

두 번째 클립 수강 인증

 

학습 인증