java
CHAPTER 74 / 99
읽기 약 2분
FUNCTION
트랜잭션 관리
핵심 개념
@Transactional 동작 원리·전파·격리 수준·롤백 규칙 — 결제 처리의 트랜잭션 설계.
본문
@Transactional 기본
@Service
@RequiredArgsConstructor
public class PaymentService {
private final PaymentRepository paymentRepo;
private final OrderRepository orderRepo;
private final InventoryRepository inventoryRepo;
@Transactional
public Payment processPayment(Long orderId, BigDecimal amount) {
// 1. 주문 조회
Order order = orderRepo.findById(orderId)
.orElseThrow(OrderNotFoundException::new);
// 2. 재고 차감
inventoryRepo.decrementStock(order.getProductId(), order.getQuantity());
// 3. 결제 저장
Payment payment = Payment.create(order, amount);
paymentRepo.save(payment);
// 위 3 단계 모두 같은 트랜잭션
// 어느 하나 실패하면 모두 롤백
return payment;
}
}전파 (Propagation)
public enum Propagation {
REQUIRED, // 기본 — 트랜잭션 있으면 참여, 없으면 새로 시작
REQUIRES_NEW, // 항상 새 트랜잭션 (현재 일시 정지)
SUPPORTS, // 있으면 참여, 없어도 OK
NOT_SUPPORTED, // 트랜잭션 없이 실행
MANDATORY, // 반드시 트랜잭션 안에서 호출
NEVER, // 트랜잭션 있으면 예외
NESTED, // 중첩 트랜잭션 (savepoint)
}
@Service
public class OrderService {
@Transactional
public void placeOrder(Order order) {
orderRepo.save(order);
sendNotification(order); // 이 안에서 별도 트랜잭션
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void sendNotification(Order order) {
// 부모 트랜잭션과 무관하게 독립 실행
// 알림 실패해도 주문은 저장
try {
notificationRepo.save(...);
} catch (Exception e) {
// 알림 실패 로깅만
}
}
}격리 수준 (Isolation)
public enum Isolation {
DEFAULT, // DB 기본값 (PostgreSQL: READ_COMMITTED)
READ_UNCOMMITTED, // Dirty read 가능 (거의 안 씀)
READ_COMMITTED, // Dirty read 차단
REPEATABLE_READ, // Phantom read 가능
SERIALIZABLE, // 모든 동시성 문제 차단 (가장 느림)
}
@Service
public class TransferService {
@Transactional(isolation = Isolation.SERIALIZABLE)
public void transfer(Long fromId, Long toId, BigDecimal amount) {
// 동시 송금 시 일관성 보장
Account from = accountRepo.findByIdForUpdate(fromId);
Account to = accountRepo.findByIdForUpdate(toId);
from.withdraw(amount);
to.deposit(amount);
accountRepo.save(from);
accountRepo.save(to);
}
}롤백 규칙
@Service
public class OrderService {
// 기본 — Unchecked 예외만 롤백 (RuntimeException, Error)
@Transactional
public void placeOrder(Order order) {
// RuntimeException 발생 시 롤백
// IOException(checked) 발생 시 롤백 X
}
// 명시적 — Checked 예외도 롤백
@Transactional(rollbackFor = {Exception.class})
public void placeOrderStrict(Order order) {
// 모든 예외에서 롤백
}
// 특정 예외는 롤백 안 함
@Transactional(noRollbackFor = {NotificationFailedException.class})
public void placeOrderNotify(Order order) {
orderRepo.save(order);
try {
sendNotification(order); // 알림 실패해도 주문 유지
} catch (NotificationFailedException e) {
// 무시
}
}
}readOnly 최적화
@Service
@Transactional(readOnly = true) // 클래스 레벨 — 모든 메서드 readOnly
public class UserQueryService {
private final UserRepository userRepo;
public User findById(Long id) {
return userRepo.findById(id)
.orElseThrow(UserNotFoundException::new);
}
public List<User> findAll() {
return userRepo.findAll();
}
@Transactional // 메서드 레벨 — readOnly 오버라이드
public User updateName(Long id, String name) {
User user = findById(id);
user.setName(name);
return user;
}
}
// readOnly의 효과:
// - JPA dirty checking 생략 (더 빠름)
// - 일부 DB는 읽기 전용 트랜잭션 최적화
// - 의도 명확화 (코드 가독성)다음 챕터
CH.6 "예외 처리" — @ControllerAdvice 글로벌 처리.
AI 프롬프트
🤖 AI에게 잘 물어보는 법 — 모델·전략별 프롬프트
Claude
무료: Sonnet 4.6 / Pro $20/mo: Opus 4.6
내 Spring 코드의 @Transactional 부분을 분석해서 롤백·격리 수준 적정성와 개선 우선순위를 알려줘.
ChatGPT
무료: GPT-5.5 / Plus $20/mo: GPT-5.5 Pro
@Transactional vs 다른 패턴 비교를 실전 사례 5개로 보여주고 Propagation 옵션 비교를 알려줘.
Gemini
무료: 2.5 Flash / Pro $19.99/mo: 3.1 Pro
내 코드베이스 전체를 분석해서 @Transactional 관련 트랜잭션 누락·과도 위치를 보고해줘.
Grok
무료: Grok 4.1 / SuperGrok $30/mo
2026년 한국 기업의 @Transactional 채택률과 한국 SI/SaaS 트랜잭션 패턴를 솔직히 알려줘.
⭐ 이것만 기억하세요
트랜잭션 관리는 이 3가지만 확실히 잡으세요
1.@Transactional은 AOP 프록시 — 외부 호출에서만 동작 (같은 클래스 내부 호출 시 무효)
2.Propagation.REQUIRES_NEW로 독립 트랜잭션, readOnly로 조회 최적화
3.다음 챕터 CH.6에서 예외 처리 — 글로벌 에러 응답 표준화
공유하기
진행도 74 / 99