결제는 됐는데 주문이 안 됐다고? 트랜잭션으로 막는 법

sangyong park·2025년 4월 7일

트랜잭션(Transaction)과 @Transactional

트랜잭션이란 ?

트랜잭션(Transaction)은 데이터베이스에서 하나의 논리적인 작업 단위를 의미한다.
여러 개의 작업(쿼리)이 하나의 묶음으로 처리되어, 전부 성공하거나, 전부 실패(롤백) 해야 하는 것이 핵심이다.

트랜잭션의 4가지 성질 (ACID)

  • Atomicity (원자성) -> 전부 성공하거나 실패해야 함
  • Consistency (일관성) -> 트랜잭션 전후의 DB 상태가 일관돼야 함
  • Isolation (격리성) -> 동시에 실행되는 트랜잭션 간 간섭 X
  • Durability (지속성) -> 트랜잭션 완료 시 결과는 영구적으로 반영
@Transactional
public void createOrder() {
    orderRepository.save(order);        // 주문 저장
    paymentService.pay();               // 결제 처리
    stockService.decreaseStock();       // 재고 감소
}
  • 위 3가지 작업 중 하나라도 실패하게 된다면 전체 작업을 롤백해서 DB 상태를 이전으로 되돌린다.

트랜잭션이 필요한 이유

  • 데이터의 정합성 보장
  • 부분 성공 방지 (결제는 됐는데 주문은 저장 안된 경우)
  • 실패 시 안전하게 되돌릴 수 있음

@Transactional이란?

Spring에서 트랜잭션을 간편하게 관리할 수 있도록 지원하는 어노테이션

사용 위치

  • 클래스 단위: 해당 클래스의 모든 public 메서드에 트랜잭션 적용
  • 메서드 단위: 해당 메서드에만 트랜잭션 적용
@Service
@Transactional
public class OrderService {
    public void createOrder(...) {
        // 트랜잭션 적용됨
    }
}

동작 방식 요약

  1. Spring이 트랜잭션을 시작
  2. 메서드 실행
  3. 예외가 발생하지 않으면 커밋
  4. 예외가 발생하면 롤백

readOnly = true 옵션

조회 전용 서비스에 사용한다면 ?

@Transactional(readOnly = true)
public List<Product> getProducts() {
    return productRepository.findAll();
}

장점

  • 변경 감지/쓰기 쿼리 막음
  • 성능 최적화
  • JPA flush X

주의할 점

  • @Transactional은 public 메서드에만 적용됨

  • 프록시 기반이므로 같은 클래스 내에서 내부 메서드 호출 시 적용 안 됨

  • 체크 예외(Checked Exception) 발생 시 롤백 안 됨 → rollbackFor 속성으로 명시 필요

결론

  • 트랜잭션은 논리적 작업 단위를 안전하게 처리하기 위한 필수 개념

  • @Transactional로 트랜잭션을 쉽게 관리할 수 있음

  • 조회만 할 경우 readOnly = true로 성능 최적화 가능

  • 실무에서 서비스 계층(Service Layer)에 가장 많이 사용함

profile
Dreams don't run away It is always myself who runs away.

0개의 댓글