1. 트랜잭션이란?
트랜잭션은 하나의 작업 단위로 묶여 전부 성공하거나 전부 실패해야 하는 실행 단위입니다.
즉, 반쯤 성공해서 데이터가 꼬이는 상황을 방지합니다.
예시
- 주문 생성
- 결제 처리
- 회원가입
필요성
- 예: 주문 생성 성공 → 재고 차감 실패
→ 주문은 생성됐지만 재고가 줄어들지 않아 데이터 정합성이 깨짐 - 해결: 전부 성공하면 COMMIT, 하나라도 실패하면 ROLLBACK
2. 트랜잭션의 ACID 특성
- Atomicity(원자성) : 전부 성공 또는 전부 실패
- Consistency(일관성) : 데이터 무결성 유지
- Isolation(독립성) : 동시에 실행돼도 서로 간섭 없음
- Durability(지속성) : 성공하면 영구 저장
3. 주문 생성 시 트랜잭션 흐름
3-1. API 요청
POST /orders 요청 시 수행할 일:
- 사용자 존재 확인
- 상품 존재 확인
- 재고 확인
- 주문 생성
- 주문상품 생성
- 재고 차감
- 결제 생성
3-2. Service 기준 순서도
1. Controller
↓
2. OrderService.createOrder() (@Transactional 시작)
-----------------------------------
1) User 조회
2) Product 조회
3) 재고 체크
4) Order 저장
5) OrderItem 저장
6) Product 재고 감소
7) Payment 생성
-----------------------------------
↓
3. COMMIT (모두 성공 시)
(중간 실패 시 예외 발생)
→ ROLLBACK
3-3. 실제 코드 예시
@Transactional
public OrderResponse createOrder(OrderRequest request) {
// 1. 사용자 조회
User user = userRepository.findById(request.getUserId());
// 2. 상품 조회
Product product = productRepository.findById(request.getProductId());
// 3. 재고 확인
if (product.getStock() < request.getQuantity()) {
throw new RuntimeException("재고 부족");
}
// 4. 주문 저장
Order order = orderRepository.save(new Order(...));
// 5. 주문상품 저장
orderItemRepository.save(new OrderItem(...));
// 6. 재고 감소
product.decreaseStock(request.getQuantity());
// 7. 결제 생성
paymentRepository.save(new Payment(...));
return OrderResponse.from(order);
}
위 메서드 전체가 하나의 트랜잭션으로 묶여 원자성이 보장됩니다.
4. 설계 사고 연결
- 왜 Controller에 @Transactional을 붙이지 않을까?
Controller는 요청의 입구 역할만 수행합니다.
트랜잭션은 비즈니스 로직 단위에 묶어야 하므로 Service 계층에 둡니다.
잘못된 설계
- 주문 생성 Service, 재고 차감 Service, 결제 생성 Service
- 각각 따로 트랜잭션 → 중간 실패 시 데이터 꼬임
올바른 설계
- 주문 생성 Service 하나에 모든 로직 포함
- 하나의 @Transactional → 원자성 보장
5. 최종 정리
트랜잭션은 비즈니스 로직을 전부 성공 혹은 전부 실패로 보장하는 실행 단위입니다.
주문 생성의 예를 들면, 주문 저장 → 재고 차감 → 결제 생성이 하나의 트랜잭션으로 묶여야 데이터 정합성이 유지됩니다.
'백엔드 기초 재정비 > 스프링 계층 구조 이해' 카테고리의 다른 글
| Exception 종류 정리 (0) | 2026.03.04 |
|---|---|
| 트랜잭션 실패 사례와 롤백 필요성 정리 (0) | 2026.03.03 |
| 로그인 API가 하는 일과 요청 → 응답 흐름 정리 (0) | 2026.02.27 |
| DTO vs Entity 정리 (0) | 2026.02.26 |
| Controller / Service / Repository 역할 정리 (0) | 2026.02.25 |