💡 Spring 핵심 개념 인터뷰 Q&A

@Transactional(propagation = REQUIRED)로 선언되어 있을 때정리
REQUIRED , 카페에서 커피 주문하고 결제하는 상황상황:
1. 고객이 ‘커피 주문, 포인트 적립’ 을 한 번에 요청
2. ‘주문 처리 서비스’ → ‘포인트 적립 서비스’를 내부에서 호출
설명 :
코드 :
@Transactional // 트랜잭션 A 시작, 주문 처리 서비스 (부모)
public void orderCoffee() {
saveOrder(); // 커피 주문 저장
savePointHistory(); // 포인트 적립 호출 (아래)
// 트랜잭션 A 끝에서 commit 또는 rollback
}
@Transactional(propagation = REQUIRED) // 포인트 적립 서비스 (자식)
public void savePointHistory() {
// 트랜잭션 A에 그대로 참여함
}
| 시점 | 동작 | 트랜잭션 상태 |
|---|---|---|
| 1 | orderCoffee() 호출 → 트랜잭션 A 시작 | 트랜잭션 A 시작됨 |
| 2 | 커피 주문 저장 (INSERT orders...) | 트랜잭션 A 안에서 실행 |
| 3 | savePointHistory() 호출 | 트랜잭션 A를 그대로 사용 |
| 4 | 포인트 적립 저장 (INSERT points...) | 여전히 트랜잭션 A 안 |
| 5(성공) | 예외 발생 없음 → 트랜잭션 A 커밋 | 두 작업 모두 반영됨 |
| 5’(실패) | 도중 예외 발생 → 트랜잭션 A 롤백 | 두 작업 모두 취소됨 |
orderCoffee, savePointHistory)가 실행하면서 하나의 트랜잭션을 공유하고,Connection conn = dataSource.getConnection();
conn.setAutoCommit(false); // 트랜잭션 시작
try {
// SQL 실행 1
// SQL 실행 2
conn.commit(); // 둘 다 성공하면 반영
} catch (Exception e) {
conn.rollback(); // 하나라도 실패하면 전체 취소
}
| 전파속성 | 설명 |
|---|---|
REQUIRED | Spring이 기존 트랜잭션을 감지 → 그 트랜잭션의 JDBC Connection을 그대로 재사용 |
REQUIRES_NEW | 기존 트랜잭션을 중단(pause)하고, 새 Connection을 요청해서 별도 트랜잭션 수행 |
REQUIRES_NEW는항상 새로운 트랜잭션을 생성 하며, 기존 트랜잭션은 일시 정지(pause)되고, 새로운 JDBC Connection 객체를 새로 열어서 독립적으로 커밋/롤백을 수행합니다.// 외부 트랜잭션 A
Connection connA = dataSource.getConnection();
connA.setAutoCommit(false); // 트랜잭션 A 시작
// 내부 메서드에서 REQUIRES_NEW
Connection connB = dataSource.getConnection();
connB.setAutoCommit(false); // 트랜잭션 B 시작 (별도 커넥션)
// 트랜잭션 B 작업
try {
// SQL 실행 (connB)
connB.commit(); // 내부 작업 커밋
} catch (Exception e) {
connB.rollback(); // 내부 작업만 롤백
}
// 외부 트랜잭션 계속 진행
try {
// SQL 실행 (connA)
connA.commit(); // 외부 트랜잭션 커밋
} catch (Exception e) {
connA.rollback(); // 외부 트랜잭션 롤백
}
REQUIRED는 전체 작업을 하나의 트랜잭션으로 묶어 함께 성공하거나 함께 실패하도록 할 때 사용합니다.
REQUIRES_NEW는 주 트랜잭션과는 별개로, 반드시 따로 성공하거나 실패하게 만들고 싶은 작업에 사용합니다
REQUIRED
REQUIRES_NEW