코드잇 스프린트/TIL

[TIL] DB 트랜잭션 개념

solytory 2026. 9. 2. 13:15

트랜젝션에 대한 기본적인 원리에 대해서만 설명하고 JAVA와 관련된 기법들(전파, 예외처리 등등)은 JDBC를 진행할 때 정리

트랜잭션이란

  • 하나의 논리적인 작업단위를 의미해서 이 단위 내의 작업이 모두 성공 하거나 모두 실패해야하는 작업의 집합
  • 전통적으로 관계형 데이터베이스의 핵심 특징이며, 최근에는 일부 NoSQL도 제한적으로 트랜잭션을 지원한다

 

트랜잭션의을 제어하기 위한 조건 (자세한건 이전 포스팅 확인)

  • 트랜잭션이 논리적 작업 단위로서 안전하게 수행되려면 ACID(원자성, 일관성, 격리성, 지속성)를 만족해야 한다. 이 중 격리성(Isolation)은 여러 트랜잭션이 동시에 실행돼도 서로 간섭받지 않아야 한다는 원칙이며, 이를 얼마나 엄격하게 지킬지는 Isolation Level(L0~L3)로 설정한다. 그리고 이 Isolation을 실제로 구현하는 기술이 동시성 제어(Concurrency Control) — 즉 Locking Mechanism(Pessimistic/Optimistic Lock)이다.

 

트랜잭션이 필요한 상황

  • 은행 ATM에서 계좌 이체시, A 계좌 출금과 B계좌 입금이 하나의 트랜잭션으로 묶이지 않으면 돈은 사라지거나 중복되는 데이터 정합성 깨지는 현상 발생 
  • 다중 테이블 조작 : 주문과 결제, 사용자 등록과 포인트 적립 등
  • 중간 오류 발생 가능성 : 네트워크 지연, 서버 다운, 코드 오류 등
  • 동시성 처리 : 여러 사용자가 동시에 같은 데이터를 수정할 경우
💡 뜻 알고 넘어가기
- 데이터 정합성 : 내가(개발자가) 정의한 데이터의 규칙/의미가 항상 지켜지는 상태

 

 

트랜잭션 상태와 생명주기

  • 트랜잭션은 단순히 시작 → 커밋 or 롤백으로 끝나는 것이 아니라, 실행 중 다양한 상태를 거치며 명확한 생명주기를 갖는다.

 

트랜잭션의 흐름 요약

  1. 트랜잭션 시작 (BEGIN)
  2. 비즈니스 로직 실행
  3. 예외 유무에 따라 커밋 또는 롤백
  4. 트랜잭션 종료

 

트랜잭션의 상태 변화

  • 트랜잭션 시작 → 활성 → 작업완료 → 부분완료 → 커밋
  • 트랜잭션 시작 → 활성 → 오류발생 → 롤백 
활성(Active) 트랜잭션이 시작되어 로직 실행 중
부분 완료
(Partially Committed)
모든 작업이 성공하고 커밋 직전 상태
커밋됨(Committed) 트랜잭션이 성공적으로 반영됨 (데이터 베이스 변경사항 적용)
실패(Failed) 트랜잭션 중 오류 발생
롤백됨(Aborted) 오류로 인해 변경 사항 모두 취소됨

 

 

트랜잭션의 처리 방식

  1. 선언적 방식(declarative)
  2. 프로그래밍 방식 (programmatic)

 

선언적 트랜잭션 (@Transactional)

  • 스프링에서 가장 일반적으로 사용하는 방식
  • 트랜잭션이 필요한 메서드나 클래스에 @Transactional 어노테이션을 붙이면 스프링이 해당 범위를 자동으로 트랜잭션으로 감싸주는 매우 편리한 방식
  • AOP 기반으로 동작 (프록시 객체가 트랜잭션 경계를 관리)
    https://soly-log.tistory.com/137  →예전에 AOP관련해서 적어놓은것 Proxy로 감싸저있는 부분에서 트랜잭션관리가 들어가는것
  • 선언만으로 커밋/롤백 자동처리
  • 메서드 실행 중 예외 발생 시 자동으로 롤백

 

@Service
public class OrderService {

    @Transactional
    public void placeOrder(OrderRequest request) {
        
        // 첫 번째 세부 트랜잭션 : 주문 내역 등록
        orderRepository.save(...);
        
        // 두 번째 세부 트랜잭션 : 결제 진행
        paymentService.charge(...);
    }
}

 

프로그래밍 방식 트랜잭션 (TransactionTemplate)

  • 명시적으로 트랜잭션 경계를 제어하는 방식으로 주로 복잡한 조건이나 동적 트랜잭션 처리 시 사용되며 선언적 방식보다는 유연하지만 코드가 증가한다.
  • 코드로 트랜잭션을 직접 감쌈
  • 성공/실패 처리 분기, 중첩 처리 등이 더 유연하다.
  • rollbackOnly 등 조건부로도 롤백이 가능하다.
@Service
public class OrderService {

    private final TransactionTemplate transactionTemplate;
    private final OrderRepository orderRepository;

    public OrderService(PlatformTransactionManager transactionManager, OrderRepository orderRepository) {
        this.transactionTemplate = new TransactionTemplate(transactionManager);
        this.orderRepository = orderRepository;
    }

    public void placeOrder(OrderRequest request) {
        
        transactionTemplate.executeWithoutResult(status -> {
            orderRepository.save(...);
            // 중간에 예외 발생 시 자동 롤백
        });
    }
}

 

반응형