트랜잭션이란 "하나의 작업 단위를 의미하며, 이 단위 내에서 실행되는 모든 작업이 성공해야 최종적으로 반영되고, 하나라도 실패하면 모든 작업이 취소(rollback)되는 메커니즘"을 말한다.
1. Atomicity(원자성)
트랜잭션 내의 모든 작업이 하나의 단위로 실행되어야 한다.
일부만 실행되거나 실패할 경우 전체를 롤백해야 한다.
2. Consistency(일관성)
트랜잭션이 성공적으로 완료되면 데이터는 항상 일관성 있는 상태를 유지해야 한다.
비즈니스 규칙과 데이터 무결성을 보장해야 한다.
3. Isolation(격리성)
여러 트랜잭션이 동시에 실행될 때 서로 간섭하지 않아야 한다.
격리 수준을 설정하여 데이터 정합성을 유지할 수 있다.
4. Durability(지속성)
트랜잭션이 성공적으로 완료되면, 변경된 데이터는 영구적으로 저장되어야 한다.
시스템 장애가 발생해도 데이터는 손실되지 않아야 한다.
스프링에서는 트랜잭션을 관리하는 방식으로 선언적 트랜잭션(Declarative Transaction)과 프로그래매틱 트랜잭션(Programmatic Transaction) 두 가지 방법을 제공한다.
가장 많이 사용되는 방식으로, 어노테이션(@Transactional)을 이용해 트랜잭션을 선언하면 스프링이 자동으로 트랜잭션을 관리해준다.
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Transactional
public void createUser(User user) {
userRepository.save(user); // 데이터베이스에 저장
}
}
@Transactional 을 메서드에 선언하면 해당 메서드가 실행될 때 트랜잭션이 시작되고, 성공적으로 끝나면 자동으로 커밋(commit) 된다.
만약 예외가 발생하면 롤백 (rollback) 된다.
클래스 레벨 적용
@Service
@Transactional
public class UserService {
// 이 클래스의 모든 메서드에 트랜잭션이 적용됨
}
클래스에 @Transactional 을 선언하면, 해당 클래스의 모든 메서드에 트랜잭션이 적용된다.
개발자가 직접 트랜잭션의 시작(BEGIN), 커밋(COMMIT), 롤백(ROLLBACK)을 코드로 제어하는 방식이다.
TransactionTemplate 또는 PlatformTransactionManager 를 사용하여 구현할 수 있다.
1. TransactionTemplate 사용
@Service
public class AccountService {
@Autowired
private TransactionTemplate transactionTemplate; // 트랜잭션 템플릿 주입
@Autowired
private AccountDAO dao;
public void transferMoney(int amount, String fromAcc, String toAcc) {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
try {
dao.withdraw(fromAcc, amount); // 출금
dao.deposit(toAcc, amount); // 입금
} catch (Exception e) {
status.setRollbackOnly(); // 예외 발생 시 롤백
}
}
});
}
}
✅ transactionTemplate.execute() 내부에서 트랜잭션이 실행된다.
✅ 예외가 발생하면 status.setRollbackOnly() 를 호출하여 롤백한다.
2. PlatformTransactionManager 사용
@Service
public class AccountService {
@Autowired
private PlatformTransactionManager transactionManager; // 트랜잭션 매니저 주입
@Autowired
private AccountDAO dao;
public void transferMoney(int amount, String fromAcc, String toAcc) {
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus status = transactionManager.getTransaction(def); // 트랜잭션 시작
try {
dao.withdraw(fromAcc, amount); // 출금
dao.deposit(toAcc, amount); // 입금
transactionManager.commit(status); // 정상 실행되면 커밋
} catch (Exception e) {
transactionManager.rollback(status); // 예외 발생 시 롤백
}
}
}
✅ 트랜잭션을 직접 시작하고(getTransaction) 성공 시 commit(), 실패 시 rollback() 호출한다.
✅ TransactionTemplate 보다 코드가 더 복잡하다.
트랜잭션은 데이터 무결성과 신뢰성을 보장하는 필수적인 기능이다
1. 데이터 일관성(Consistency) 유지
예를 들어, 은행 계좌 이체에서 돈이 출금되었는데 입금이 안 되면 문제가 발생한다.
2. 무결성(Integrity) 보장
예를 들어, 좌석 예매 시스템에서 같은 좌석이 여러 사람에게 동시에 예약되지 않도록 방지한다.
3. 시스템 장애 대비
예를 들어, 온라인 쇼핑몰에서 결제 중 서버가 다운되었을 때 결제가 실패해야 한다.
4. 동시성 문제 해결
예를 들어, 주식 거래 시스템에서 동일한 주식을 동시에 여러 사람이 매수할 때 문제를 방지한다.
💡 1. 은행 계좌 이체
⚠️ 트랜잭션이 없을 경우 발생할 문제
UPDATE bank_account SET balance = balance - 500 WHERE accNo = '100-100-1001'; -- A 계좌에서 500원 출금
-- (서버 다운, 네트워크 문제 발생)
UPDATE bank_account SET balance = balance + 500 WHERE accNo = '100-100-1002'; -- B 계좌에 500원 입금 (실행되지 않음!)
✅ 트랜잭션을 사용할 경우 (올바른 방법)
BEGIN TRANSACTION;
UPDATE bank_account SET balance = balance - 500 WHERE accNo = '100-100-1001'; -- A 계좌에서 500원 출금
UPDATE bank_account SET balance = balance + 500 WHERE accNo = '100-100-1002'; -- B 계좌에 500원 입금
COMMIT;
모든 SQL이 성공하면 COMMIT
중간에 실패하면 ROLLBACK 하여 원상 복구
💡 2. 온라인 쇼핑몰 결제
⚠️ 트랜잭션이 없을 경우
사용자가 상품을 장바구니에 추가
결제 요청을 보낸다.
결제 완료되기 전에 서버 장애 발생
→ 결제는 성공했는데 주문이 등록되지 않는다! (사용자는 돈을 냈지만 주문이 사라짐)
✅ 트랜잭션 적용
@Transactional
public void processOrder(OrderDTO order) {
paymentService.pay(order); // 결제 처리
orderService.createOrder(order); // 주문 정보 저장
inventoryService.updateStock(order); // 재고 감소
}
모든 과정이 성공해야만 주문이 완료됨
중간에 실패하면 모든 작업 취소(ROLLBACK)
💡 3. 좌석 예매 시스템
⚠️ 트랜잭션이 없을 경우
A 사용자가 좌석 예약 요청 (seat_no = 10)
동시에 B 사용자도 같은 좌석 예약 요청 (seat_no = 10)
동시에 요청이 처리되면 좌석이 중복 예약된다.
✅ 트랜잭션 적용
BEGIN TRANSACTION;
UPDATE seat_table SET status = 'reserved' WHERE seat_no = 10;
COMMIT;
seat_no = 10이 예약 처리되면 다른 사용자는 예약 불가
트랜잭션이 없으면 동시성 문제 발생 가능