트랜젝션에 대한 기본적인 원리에 대해서만 설명하고 JAVA와 관련된 기법들(전파, 예외처리 등등)은 JDBC를 진행할 때 정리
트랜잭션이란
- 하나의 논리적인 작업단위를 의미해서 이 단위 내의 작업이 모두 성공 하거나 모두 실패해야하는 작업의 집합
- 전통적으로 관계형 데이터베이스의 핵심 특징이며, 최근에는 일부 NoSQL도 제한적으로 트랜잭션을 지원한다
트랜잭션의을 제어하기 위한 조건 (자세한건 이전 포스팅 확인)
- 트랜잭션이 논리적 작업 단위로서 안전하게 수행되려면 ACID(원자성, 일관성, 격리성, 지속성)를 만족해야 한다. 이 중 격리성(Isolation)은 여러 트랜잭션이 동시에 실행돼도 서로 간섭받지 않아야 한다는 원칙이며, 이를 얼마나 엄격하게 지킬지는 Isolation Level(L0~L3)로 설정한다. 그리고 이 Isolation을 실제로 구현하는 기술이 동시성 제어(Concurrency Control) — 즉 Locking Mechanism(Pessimistic/Optimistic Lock)이다.
트랜잭션이 필요한 상황
- 은행 ATM에서 계좌 이체시, A 계좌 출금과 B계좌 입금이 하나의 트랜잭션으로 묶이지 않으면 돈은 사라지거나 중복되는 데이터 정합성 깨지는 현상 발생
- 다중 테이블 조작 : 주문과 결제, 사용자 등록과 포인트 적립 등
- 중간 오류 발생 가능성 : 네트워크 지연, 서버 다운, 코드 오류 등
- 동시성 처리 : 여러 사용자가 동시에 같은 데이터를 수정할 경우
💡 뜻 알고 넘어가기
- 데이터 정합성 : 내가(개발자가) 정의한 데이터의 규칙/의미가 항상 지켜지는 상태
트랜잭션 상태와 생명주기
- 트랜잭션은 단순히 시작 → 커밋 or 롤백으로 끝나는 것이 아니라, 실행 중 다양한 상태를 거치며 명확한 생명주기를 갖는다.
트랜잭션의 흐름 요약
- 트랜잭션 시작 (BEGIN)
- 비즈니스 로직 실행
- 예외 유무에 따라 커밋 또는 롤백
- 트랜잭션 종료
트랜잭션의 상태 변화
- 트랜잭션 시작 → 활성 → 작업완료 → 부분완료 → 커밋
- 트랜잭션 시작 → 활성 → 오류발생 → 롤백
| 활성(Active) | 트랜잭션이 시작되어 로직 실행 중 |
| 부분 완료 (Partially Committed) |
모든 작업이 성공하고 커밋 직전 상태 |
| 커밋됨(Committed) | 트랜잭션이 성공적으로 반영됨 (데이터 베이스 변경사항 적용) |
| 실패(Failed) | 트랜잭션 중 오류 발생 |
| 롤백됨(Aborted) | 오류로 인해 변경 사항 모두 취소됨 |
트랜잭션의 처리 방식
- 선언적 방식(declarative)
- 프로그래밍 방식 (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(...);
// 중간에 예외 발생 시 자동 롤백
});
}
}
반응형
'코드잇 스프린트 > TIL' 카테고리의 다른 글
| [TIL] 논리적 모델링 (0) | 2026.09.02 |
|---|---|
| [TIL] 개념적 모델링 ERD (0) | 2026.09.02 |
| [TIL] 데이터베이스 트랜잭션 격리레벨(Isolation Lavel) (0) | 2026.09.02 |
| [TIL] 데이터베이스 동시성 제어 (Concurrency Control) (0) | 2026.09.02 |
| [TIL] 데이터 베이스의 확장 (0) | 2026.09.02 |