F-LAB JAVA · 7주차 · Phase 6 · PlatformTransactionManager
🎯 Phase 6 시작 — Spring 의 트랜잭션 추상화
이 Unit을 끝내면 다음을 답할 수 있어야 한다.
PlatformTransactionManager 는 Spring 의 트랜잭션 추상화 인터페이스로 getTransaction · commit · rollback 3 메서드만 정의해 5주차 DIP (의존성 역전) + 6주차 DataSource 와 동일한 구조를 트랜잭션에 적용 — 애플리케이션은 인터페이스에만 의존하고 실제 구현체 (DataSourceTransactionManager / HibernateTransactionManager / JpaTransactionManager) 는 상황에 맞게 선택해 교체할 수 있으며 이것이 @Transactional 자동화의 직접적 기반이다.
PlatformTransactionManager 는 Spring 의 트랜잭션 추상화 핵심 인터페이스 다 (org.springframework.transaction).
단 3 메서드 만 정의 —getTransaction(definition)(트랜잭션 시작, TransactionStatus 반환),commit(status)(커밋),rollback(status)(롤백) — 이 인터페이스 자체는 동작 X, 구현체 (DataSourceTransactionManager 등) 가 실제 동작.
5주차 DIP / 6주차 DataSource 와 정확히 같은 구조 — 애플리케이션은 인터페이스 (PlatformTransactionManager) 에만 의존 하고 실제 구현체 (DB / ORM 따라) 는 빈으로 주입받아 사용한다 — OCP (Open-Closed Principle) 적용.
구현체 3가지 (Phase 6.2 상세) — (1) DataSourceTransactionManager (JDBC / JdbcTemplate), (2) HibernateTransactionManager (Hibernate 직접), (3) JpaTransactionManager (JPA / Spring Data JPA) — 사용 시 코드 변경 X, 빈 교체만으로 가능.
TransactionTemplate 은 PlatformTransactionManager 를 한 단계 더 추상화 — 람다 (Callback) 로 비즈니스 로직 전달하면 트랜잭션 관리 자동 (수동의 try/catch/finally 대체).
이 추상화 위에 @Transactional 어노테이션 + AOP/프록시 가 얹혀 자동화의 정점이 된다 (Phase 7 ★★★).
PlatformTransactionManager = 표준 콘센트:
상황:
- 가전 (애플리케이션 코드)
- 콘센트 (PlatformTransactionManager 인터페이스)
- 발전소 (실제 구현체: DataSource/Hibernate/JPA TM)
표준 콘센트:
- 모든 가전이 같은 콘센트 (220V)
- 발전소가 어디든 (수력/원자력/태양광) X 상관
- 콘센트만 알면 됨
PlatformTransactionManager 정신:
- 애플리케이션 = 인터페이스만 의존
- 어떤 DB / ORM 이든 같은 방식
- 5주차 DIP, 6주차 DataSource 와 같음
3 메서드 = 콘센트의 3 단자:
- getTransaction = 전기 시작
- commit = 전기 사용 후 정리
- rollback = 사고 시 차단
5주차 + 6주차 + 7주차 응축:
- 5주차: 인터페이스 의존 (DIP)
- 6주차: DataSource 추상화
- 7주차 Part B: TM 추상화 (같은 정신)
3 구현체 = 3 발전소 (Phase 6.2):
- JDBC TM (수력)
- Hibernate TM (원자력)
- JPA TM (태양광)
TransactionTemplate:
- 콘센트 + 멀티탭
- 람다로 비즈니스 전달
- 트랜잭션 자동
@Transactional (Phase 7):
- "스마트 가전"
- 어노테이션만으로
- 자동
→ PlatformTransactionManager = 표준 콘센트, 인터페이스만 의존, 구현체 교체 가능.
1. PlatformTransactionManager 정의
2. 인터페이스 추상화의 의미
3. 3가지 핵심 메서드
4. 5주차 DIP 정신 재현
5. 6주차 DataSource 와 같은 사상
6. 인터페이스 의존 (OCP)
7. TransactionStatus / TransactionDefinition
8. TransactionTemplate 활용
9. Phase 6.2 예고 (3가지 구현체)
PlatformTransactionManager:
Spring 의 트랜잭션 추상화 인터페이스:
- 패키지: org.springframework.transaction
- 3 메서드만 정의
- 구현체가 실제 동작
→ 모든 Spring 트랜잭션의 기반
package org.springframework.transaction;
public interface PlatformTransactionManager extends TransactionManager {
// 트랜잭션 시작
TransactionStatus getTransaction(TransactionDefinition definition)
throws TransactionException;
// 커밋
void commit(TransactionStatus status) throws TransactionException;
// 롤백
void rollback(TransactionStatus status) throws TransactionException;
}
인터페이스 = 약속:
PlatformTransactionManager:
- "이런 메서드 있다는 약속"
- 동작 X (자체로는)
구현체:
- "약속 지킴"
- 실제 동작
→ 인터페이스 + 구현체
추상화의 위치:
┌─────────────────────────────────────┐
│ Application Code │
└────────────┬────────────────────────┘
│ PlatformTransactionManager 만 의존
↓
┌─────────────────────────────────────┐
│ PlatformTransactionManager (인터페이스) │
└────────────┬────────────────────────┘
│ 빈으로 주입 (Spring DI)
↓
┌──────────────┬──────────────┬──────────────┐
│ DataSource TM │ Hibernate TM │ JPA TM │
│ (JDBC) │ (Hibernate) │ (JPA) │
└──────────────┴──────────────┴──────────────┘
// ILIC 의 트랜잭션 추상화 활용
// 1. 의존성: 인터페이스만
@Service
public class ShipmentService {
@Autowired
private PlatformTransactionManager transactionManager; // 인터페이스
// 실제로는 JpaTransactionManager 가 주입 (Spring Boot 자동)
// 코드는 모름 (그게 정신)
public void process() {
TransactionStatus status = transactionManager.getTransaction(
new DefaultTransactionDefinition()
);
try {
// 비즈니스
transactionManager.commit(status);
} catch (Exception e) {
transactionManager.rollback(status);
throw e;
}
}
}
class PlatformTransactionManager {
TransactionStatus getTransaction(TransactionDefinition d) { return null; }
void commit(TransactionStatus s) {}
void rollback(TransactionStatus s) {}
}
class TransactionStatus {}
class TransactionDefinition {}
class DefaultTransactionDefinition {}
PlatformTransactionManager transactionManager;
@interface Autowired {}
@interface Service {}
PlatformTransactionManager 의 정의는?
답:
1. 인터페이스:
3 메서드:
패키지:
약속:
추상화:
공통점 추출:
- JDBC, Hibernate, JPA 의 트랜잭션
- 공통 동작 (begin/commit/rollback)
- 인터페이스로 표현
세부는 숨김:
- JDBC 의 setAutoCommit
- Hibernate 의 EntityTransaction
- JPA 의 EntityTransaction
- 모두 다른 방식
→ 인터페이스 위로는 같음
효과:
1. 코드 단순:
- 인터페이스만
- 세부 모름
2. 교체 가능:
- JDBC → JPA 변경 시
- 구현체만 교체
- 코드 그대로
3. 테스트 쉬움:
- Mock 구현체
- 단위 테스트
4. 학습 ↓:
- 1 인터페이스
- vs 3 구현체 모두
6주차 DataSource:
DataSource (인터페이스):
- getConnection()
구현체:
- HikariDataSource
- DriverManagerDataSource
- ...
애플리케이션:
- DataSource 의존
- 구현체 모름
→ 같은 패턴!
같은 사상:
6주차 DataSource:
- Connection 추상화
- 어떤 풀이든 같은 방식
7주차 PlatformTransactionManager:
- 트랜잭션 추상화
- 어떤 TM 이든 같은 방식
→ 정확히 같음
→ 5주차 디자인 패턴의 적용
추상화의 비용:
장점:
- 위 4가지
비용:
- 한 단계 더 (호출 깊이)
- 디버깅 시 추가 단계
- 학습 곡선
보통:
- 비용 < 장점
- 추상화 활용
ILIC 의 추상화 활용
ILIC = Spring Boot:
- PlatformTransactionManager 자동 (Spring 이 빈 등록)
- 구현체: JpaTransactionManager
- 코드는 인터페이스만
미래 변경 시 (DB 변경):
- MySQL → PostgreSQL: 구현체 그대로
- JPA → JdbcTemplate: 구현체 다를 수
- 하지만 코드 그대로
추상화의 가치:
- 변경 안전
- 일관 코드
인터페이스 추상화의 의미는?
답:
1. 추상화:
효과:
6주차 DataSource:
사상:
TransactionStatus getTransaction(TransactionDefinition definition)
throws TransactionException;
getTransaction:
의미:
- 트랜잭션 시작 또는 기존 참여
파라미터:
- TransactionDefinition: 트랜잭션 정의
- 전파 (propagation)
- 격리 (isolation)
- timeout
- readOnly
반환:
- TransactionStatus: 트랜잭션 상태
- 신규 / 기존
- rollback 표시 가능
void commit(TransactionStatus status) throws TransactionException;
commit:
의미:
- 트랜잭션 커밋
- DB 에 영구 반영
파라미터:
- TransactionStatus: getTransaction 의 반환
내부 동작:
- 변경 사항 DB 반영
- 락 해제
- 자원 정리
void rollback(TransactionStatus status) throws TransactionException;
rollback:
의미:
- 트랜잭션 롤백
- 변경 사항 취소
파라미터:
- TransactionStatus
내부 동작:
- 변경 사항 취소
- 메모리 정리
- 자원 정리
// 사용 패턴 (수동, 하지만 추상화)
@Service
public class ShipmentService {
@Autowired PlatformTransactionManager tm;
public void process() {
// 1. 트랜잭션 시작
TransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus status = tm.getTransaction(def);
try {
// 2. 비즈니스 로직
// ...
// 3. 커밋
tm.commit(status);
} catch (Exception e) {
// 4. 롤백
tm.rollback(status);
throw e;
}
}
}
class PlatformTransactionManager {
TransactionStatus getTransaction(TransactionDefinition d) { return null; }
void commit(TransactionStatus s) {}
void rollback(TransactionStatus s) {}
}
class TransactionStatus {}
class TransactionDefinition {}
class DefaultTransactionDefinition extends TransactionDefinition {}
PlatformTransactionManager tm;
수동 직접 vs PlatformTM:
수동 직접 (Phase 5):
- JDBC: conn.setAutoCommit(false), commit, rollback
- JPA: em.getTransaction().begin/commit/rollback
- DB / ORM 별 다름
PlatformTM:
- 항상 같음: getTransaction / commit / rollback
- 구현체가 차이 처리
- 일관 인터페이스
→ 추상화의 효과
// ILIC 의 PlatformTM 사용 (수동 활용, 자동화 전)
@Service
public class ShipmentService {
@Autowired
private PlatformTransactionManager tm;
@Autowired
private ShipmentRepository repo;
public void processShipment(Long id) {
// 1. 정의
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setName("processShipment");
def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
def.setTimeout(30);
// 2. 시작
TransactionStatus status = tm.getTransaction(def);
try {
// 3. 비즈니스 (어떤 ORM 이든)
Shipment s = repo.findById(id).orElseThrow();
s.markAsShipped();
// 4. 커밋
tm.commit(status);
} catch (Exception e) {
// 5. 롤백
tm.rollback(status);
throw new RuntimeException(e);
}
}
}
// → 인터페이스 사용
// → 어떤 TM 이든 같은 코드
// → 수동이지만 추상화
class Shipment { void markAsShipped() {} }
ShipmentRepository repo;
interface ShipmentRepository { java.util.Optional<Shipment> findById(Long id); }
class PlatformTransactionManager {
TransactionStatus getTransaction(TransactionDefinition d) { return null; }
void commit(TransactionStatus s) {}
void rollback(TransactionStatus s) {}
}
class TransactionStatus {}
class TransactionDefinition {
static int ISOLATION_READ_COMMITTED = 0;
}
class DefaultTransactionDefinition extends TransactionDefinition {
void setName(String s) {}
void setIsolationLevel(int i) {}
void setTimeout(int t) {}
}
PlatformTransactionManager tm;
3가지 핵심 메서드는?
답:
1. getTransaction:
commit:
rollback:
수동 직접 vs:
DIP (Dependency Inversion Principle):
"고수준 모듈은 저수준 모듈에 의존 X.
둘 다 추상화 (인터페이스) 에 의존."
애플리케이션 (고수준) →
PlatformTransactionManager (추상) ←
DataSourceTransactionManager (저수준)
추상화 의존:
애플리케이션:
@Autowired PlatformTransactionManager tm;
// ↑ 인터페이스만 의존
실제 동작:
- JpaTransactionManager (실제 구현)
- 또는 DataSourceTransactionManager
- 코드는 모름
→ DIP 충족
OCP (Open-Closed Principle):
"확장에 열려 있고 변경에 닫혀 있어야"
새 TM 추가 시:
- 구현체 추가 (확장 OK)
- 기존 코드 변경 X
- 빈 등록만
→ OCP 충족
5주차 패턴 매핑:
- DI: TM 빈 주입
- DIP: 인터페이스 의존
- OCP: 구현체 교체 가능
- 전략 패턴: TM 이 전략
- 템플릿 패턴: TransactionTemplate
→ 5주차 디자인 패턴 응축
같은 정신:
6주차 DataSource:
- DataSource (인터페이스)
- HikariDataSource (구현체)
- 5주차 DIP 적용
7주차 PlatformTM:
- PlatformTransactionManager (인터페이스)
- DataSourceTM / HibernateTM / JpaTM (구현체)
- 5주차 DIP 적용
→ 똑같은 패턴
→ "익숙해진 패턴 그대로"
// ILIC 의 5주차 정신 적용
// 5주차 디자인 패턴 적용 결과:
// 1. DI (Spring Boot 가 자동)
@Service
public class ShipmentService {
@Autowired
private PlatformTransactionManager tm; // DI
}
// 2. DIP
// - 애플리케이션 = 인터페이스 의존
// - 구현체 모름
// 3. OCP
// - 새 TM 추가? 구현체만
// - 기존 코드 X 변경
// 4. 전략 패턴
// - TM = 전략
// - 다른 TM 으로 교체 가능
// 5. 빈 교체 (구현체 변경)
@Bean
public PlatformTransactionManager transactionManager() {
return new JpaTransactionManager(emf); // 1. JPA 사용
// 또는:
// return new DataSourceTransactionManager(dataSource); // 2. JDBC
}
// → 5주차 패턴의 완벽 응축
class JpaTransactionManager {
JpaTransactionManager(EntityManagerFactory emf) {}
}
class DataSourceTransactionManager {
DataSourceTransactionManager(DataSource ds) {}
}
class PlatformTransactionManager {}
EntityManagerFactory emf;
DataSource dataSource;
class EntityManagerFactory {}
interface DataSource {}
@interface Service {}
@interface Autowired {}
@interface Bean {}
5주차 DIP 정신의 재현은?
답:
1. DIP:
OCP:
5주차 패턴:
같은 정신:
6주차 DataSource:
javax.sql.DataSource (인터페이스):
public interface DataSource {
Connection getConnection() throws SQLException;
// ...
}
구현체:
- HikariDataSource (가장 빠른 풀)
- DriverManagerDataSource (단순)
- C3P0, DBCP, ...
| 항목 | DataSource (6주차) | PlatformTransactionManager (7주차) |
|---|---|---|
| 인터페이스 | javax.sql.DataSource | org.springframework.transaction.PlatformTransactionManager |
| 메서드 수 | 여러 | 3 (getTransaction/commit/rollback) |
| 추상화 대상 | Connection 제공 | 트랜잭션 관리 |
| 구현체 | HikariDataSource 등 | DataSourceTM, HibernateTM, JpaTM |
| 애플리케이션 의존 | DataSource 만 | PlatformTM 만 |
| 사상 | DIP / OCP | DIP / OCP (동일) |
같은 구조:
6주차:
Application
↓ DataSource (인터페이스)
HikariDataSource (구현체)
7주차:
Application
↓ PlatformTransactionManager (인터페이스)
JpaTransactionManager (구현체)
→ 정확히 같음
학습의 누적:
6주차에서 DataSource 학습 →
7주차에서 PlatformTM 도 같은 패턴 →
"익숙한 패턴 재인식" →
깊은 이해
3-5-6-7주차의 응축:
- 3주차 (함수형): 람다 (TransactionTemplate)
- 5주차 (디자인 패턴): DI / DIP / OCP / 템플릿+전략
- 6주차 (DB 접근): DataSource 추상화
- 7주차 Part B: 같은 사상으로 TM 추상화
→ 자바 진영 추상화의 일관 사상
추상화의 깊이:
Application
↓
PlatformTransactionManager (인터페이스)
↓
JpaTransactionManager (구현체)
↓
EntityManagerFactory (JPA)
↓
DataSource (인터페이스, 6주차)
↓
HikariDataSource (구현체, 6주차)
↓
JDBC Driver
↓
DB
→ 6 단계 추상화!
→ 각 단계 5주차 DIP 적용
ILIC 의 6주차 + 7주차 통합
ILIC 의 빈 구조 (Spring Boot 자동):
1. HikariDataSource (6주차)
2. EntityManagerFactory (JPA + Hibernate, 7주차)
3. JpaTransactionManager (7주차)
application.yml 설정:
spring:
datasource: { url, username, password, hikari }
jpa: { hibernate, properties }
Spring Boot:
- 위 3 빈 모두 자동 생성
- 자동 연결
- 코드 X
애플리케이션:
@Autowired DataSource dataSource; // 인터페이스
@PersistenceContext EntityManager em; // 인터페이스
@Autowired PlatformTransactionManager tm; // 인터페이스
// 모두 인터페이스 의존
// 5주차 + 6주차 + 7주차 정신
→ ILIC = 추상화의 결정체
6주차 DataSource 와 같은 사상은?
답:
1. 6주차 DataSource:
7주차 PlatformTM:
사상:
누적:
OCP 적용:
애플리케이션:
- PlatformTransactionManager 만 의존
- 구현체 모름
새 TM 추가 시:
- 구현체 추가 (확장)
- 기존 코드 변경 X
- 빈 등록만
→ "확장에 열려, 변경에 닫혀"
// 1. JPA 사용 (현재)
@Bean
public PlatformTransactionManager transactionManager(
EntityManagerFactory emf) {
return new JpaTransactionManager(emf);
}
// 2. JDBC 로 변경 (가정)
@Bean
public PlatformTransactionManager transactionManager(
DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
// 3. Hibernate 직접 (가정)
@Bean
public PlatformTransactionManager transactionManager(
SessionFactory sessionFactory) {
return new HibernateTransactionManager(sessionFactory);
}
// 애플리케이션 코드는?
@Autowired PlatformTransactionManager tm;
// → 그대로! 변경 X
class PlatformTransactionManager {}
class JpaTransactionManager extends PlatformTransactionManager {
JpaTransactionManager(EntityManagerFactory emf) {}
}
class DataSourceTransactionManager extends PlatformTransactionManager {
DataSourceTransactionManager(DataSource ds) {}
}
class HibernateTransactionManager extends PlatformTransactionManager {
HibernateTransactionManager(SessionFactory sf) {}
}
EntityManagerFactory emf;
DataSource dataSource;
SessionFactory sessionFactory;
class EntityManagerFactory {}
interface DataSource {}
class SessionFactory {}
PlatformTransactionManager tm;
@interface Bean {}
@interface Autowired {}
OCP 의 가치:
1. 변경 안전:
- 기존 코드 변경 X
- 새 구현 추가만
2. 테스트:
- Mock TM 으로 테스트
- 단위 테스트
3. 마이그레이션:
- JDBC → JPA 등
- 구현체만 교체
4. 다중 환경:
- 개발 / 테스트 / 운영
- 각자 다른 TM 가능
// 다중 TM (멀티 DataSource 등)
@Configuration
public class DataSourceConfig {
@Primary
@Bean(name = "mainTransactionManager")
public PlatformTransactionManager mainTM(
@Qualifier("mainEmf") EntityManagerFactory emf) {
return new JpaTransactionManager(emf);
}
@Bean(name = "logTransactionManager")
public PlatformTransactionManager logTM(
@Qualifier("logDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
// 사용 시 어떤 TM 인지 명시
@Transactional("mainTransactionManager")
public void mainBusiness() { ... }
@Transactional("logTransactionManager")
public void logging() { ... }
class JpaTransactionManager extends PlatformTransactionManager {
JpaTransactionManager(EntityManagerFactory emf) {}
}
class DataSourceTransactionManager extends PlatformTransactionManager {
DataSourceTransactionManager(DataSource ds) {}
}
class PlatformTransactionManager {}
class EntityManagerFactory {}
interface DataSource {}
@interface Configuration {}
@interface Primary {}
@interface Bean { String name(); }
@interface Qualifier { String value(); }
@interface Transactional { String value(); }
// ILIC 의 OCP 적용
// 현재: JPA 사용
// → Spring Boot 가 JpaTransactionManager 자동 등록
// 미래 가능성:
// 1. 멀티 DB (메인 + 로그 분리)
// → 2개 TM
// 2. JDBC + JPA 혼합
// → 두 TM
// 3. 분산 트랜잭션 (XA)
// → JtaTransactionManager
// 어떤 변경이든 애플리케이션 코드:
@Service
public class ShipmentService {
@Autowired PlatformTransactionManager tm; // 그대로
@Transactional // 또는 어노테이션 (Phase 7)
public void process() { ... }
}
// → 인터페이스 의존 = 변경 안전
class PlatformTransactionManager {}
PlatformTransactionManager tm;
@interface Service {}
@interface Autowired {}
@interface Transactional {}
인터페이스 의존 (OCP) 의 가치는?
답:
1. OCP:
구현체 교체:
다중 TM:
가치:
TransactionDefinition:
트랜잭션의 "설정 / 정의":
- propagation (전파)
- isolation (격리)
- timeout
- readOnly
- name (이름, 디버깅용)
getTransaction 의 입력
package org.springframework.transaction;
public interface TransactionDefinition {
// 전파 (propagation)
int PROPAGATION_REQUIRED = 0; // 기본
int PROPAGATION_SUPPORTS = 1;
int PROPAGATION_MANDATORY = 2;
int PROPAGATION_REQUIRES_NEW = 3;
int PROPAGATION_NOT_SUPPORTED = 4;
int PROPAGATION_NEVER = 5;
int PROPAGATION_NESTED = 6;
// 격리 (isolation)
int ISOLATION_DEFAULT = -1;
int ISOLATION_READ_UNCOMMITTED = 1;
int ISOLATION_READ_COMMITTED = 2;
int ISOLATION_REPEATABLE_READ = 4;
int ISOLATION_SERIALIZABLE = 8;
// 메서드들
int getPropagationBehavior();
int getIsolationLevel();
int getTimeout();
boolean isReadOnly();
String getName();
}
// 기본 구현체
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
// 옵션 설정
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
def.setTimeout(30); // 초
def.setReadOnly(true);
def.setName("processShipment");
class TransactionDefinition {
static int PROPAGATION_REQUIRED = 0;
static int ISOLATION_READ_COMMITTED = 2;
}
class DefaultTransactionDefinition extends TransactionDefinition {
void setPropagationBehavior(int i) {}
void setIsolationLevel(int i) {}
void setTimeout(int t) {}
void setReadOnly(boolean b) {}
void setName(String s) {}
}
TransactionStatus:
트랜잭션의 "현재 상태":
- 신규 / 기존
- rollback 표시 가능
- 메타 정보
getTransaction 의 반환
commit / rollback 의 입력
package org.springframework.transaction;
public interface TransactionStatus extends TransactionExecution, SavepointManager, Flushable {
// 신규 트랜잭션 여부
boolean isNewTransaction();
// rollback only 표시 (commit 시도 시 rollback)
void setRollbackOnly();
boolean isRollbackOnly();
// 완료 여부
boolean isCompleted();
// SavePoint 생성 (NESTED)
Object createSavepoint();
void rollbackToSavepoint(Object savepoint);
void releaseSavepoint(Object savepoint);
}
// 전체 사용 예시
@Service
public class ShipmentService {
@Autowired PlatformTransactionManager tm;
public void process(Long id) {
// 1. Definition
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
def.setTimeout(30);
def.setReadOnly(false);
// 2. 시작
TransactionStatus status = tm.getTransaction(def);
try {
// 3. 비즈니스
Shipment s = repo.findById(id).orElseThrow();
if (!s.canProcess()) {
status.setRollbackOnly(); // ← rollback 예약
// 또는 throw
} else {
s.process();
}
// 4. 커밋 (rollback only 면 commit 시도해도 rollback)
tm.commit(status);
} catch (Exception e) {
tm.rollback(status);
throw e;
}
}
}
class Shipment {
boolean canProcess() { return false; }
void process() {}
}
ShipmentRepository repo;
interface ShipmentRepository { java.util.Optional<Shipment> findById(Long id); }
class PlatformTransactionManager {
TransactionStatus getTransaction(TransactionDefinition d) { return null; }
void commit(TransactionStatus s) {}
void rollback(TransactionStatus s) {}
}
PlatformTransactionManager tm;
class TransactionStatus { void setRollbackOnly() {} }
class TransactionDefinition { static int ISOLATION_READ_COMMITTED = 2; }
class DefaultTransactionDefinition extends TransactionDefinition {
void setIsolationLevel(int i) {}
void setTimeout(int t) {}
void setReadOnly(boolean b) {}
}
@interface Service {}
@interface Autowired {}
// ILIC 의 활용 (수동, 자동화 전)
@Service
public class ShipmentService {
@Autowired PlatformTransactionManager tm;
public List<Shipment> findAll() {
// 읽기 전용 트랜잭션
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setReadOnly(true);
def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
def.setName("findAll");
TransactionStatus status = tm.getTransaction(def);
try {
List<Shipment> result = repo.findAll();
tm.commit(status);
return result;
} catch (Exception e) {
tm.rollback(status);
throw e;
}
}
}
// → 명시적 트랜잭션 설정
// → @Transactional (Phase 7) 로 더 간단
class Shipment {}
ShipmentRepository repo;
interface ShipmentRepository { java.util.List<Shipment> findAll(); }
class PlatformTransactionManager {
TransactionStatus getTransaction(TransactionDefinition d) { return null; }
void commit(TransactionStatus s) {}
void rollback(TransactionStatus s) {}
}
PlatformTransactionManager tm;
class TransactionStatus {}
class TransactionDefinition { static int ISOLATION_READ_COMMITTED = 2; }
class DefaultTransactionDefinition extends TransactionDefinition {
void setReadOnly(boolean b) {}
void setIsolationLevel(int i) {}
void setName(String s) {}
}
TransactionStatus / TransactionDefinition 은?
답:
1. TransactionDefinition:
TransactionStatus:
DefaultTransactionDefinition:
사용:
TransactionTemplate:
PlatformTransactionManager 위의 추상화:
- 람다 (Callback) 로 비즈니스 전달
- try/catch/finally 자동
- 6주차 JdbcTemplate 와 같은 정신
→ 수동 vs 어노테이션 중간
// TransactionTemplate 사용
@Service
public class ShipmentService {
@Autowired TransactionTemplate transactionTemplate;
@Autowired ShipmentRepository repo;
public Shipment process(Long id) {
return transactionTemplate.execute(status -> {
// 비즈니스만!
Shipment s = repo.findById(id).orElseThrow();
s.markAsShipped();
return s;
});
// 자동:
// - 트랜잭션 시작
// - 메서드 실행
// - 정상 → commit
// - 예외 → rollback
}
// void 일 경우
public void update(Long id) {
transactionTemplate.executeWithoutResult(status -> {
// 비즈니스
});
}
}
class Shipment { void markAsShipped() {} }
ShipmentRepository repo;
interface ShipmentRepository { java.util.Optional<Shipment> findById(Long id); }
class TransactionTemplate {
<T> T execute(java.util.function.Function<TransactionStatus, T> f) { return null; }
void executeWithoutResult(java.util.function.Consumer<TransactionStatus> c) {}
}
TransactionTemplate transactionTemplate;
class TransactionStatus {}
// TransactionTemplate 의 동작 (개념)
public <T> T execute(TransactionCallback<T> action) {
TransactionStatus status = transactionManager.getTransaction(this);
T result;
try {
result = action.doInTransaction(status);
} catch (Exception e) {
// 롤백
transactionManager.rollback(status);
throw e;
}
transactionManager.commit(status);
return result;
}
// → 5주차 템플릿+전략 패턴
// → 변하지 않는 부분 (트랜잭션 관리)
// → 변하는 부분 (Callback)
class TransactionCallback<T> { T doInTransaction(TransactionStatus s) { return null; } }
class PlatformTransactionManager {
TransactionStatus getTransaction(Object def) { return null; }
void commit(TransactionStatus s) {}
void rollback(TransactionStatus s) {}
}
class TransactionStatus {}
PlatformTransactionManager transactionManager;
5주차 패턴 적용:
- 템플릿+전략:
- 템플릿: TransactionTemplate (변하지 않음)
- 전략: 람다 (변함)
- 6주차 JdbcTemplate 와 같은 정신:
- 자원 / 트랜잭션 자동
- 비즈니스만
→ "5주차 패턴 += 적용"
// TransactionTemplate 빈 설정
@Configuration
public class TransactionConfig {
@Bean
public TransactionTemplate transactionTemplate(
PlatformTransactionManager tm) {
TransactionTemplate template = new TransactionTemplate(tm);
template.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
template.setTimeout(30);
return template;
}
}
class TransactionTemplate {
TransactionTemplate(PlatformTransactionManager tm) {}
void setIsolationLevel(int i) {}
void setTimeout(int t) {}
}
class PlatformTransactionManager {}
class TransactionDefinition { static int ISOLATION_READ_COMMITTED = 2; }
@interface Configuration {}
@interface Bean {}
TransactionTemplate vs @Transactional:
TransactionTemplate:
- 람다 (Callback)
- 명시적
- 메서드 안 일부에 한정 가능
@Transactional:
- 어노테이션 1줄
- 자동
- 메서드 전체
실무 선택:
- 90% @Transactional (간결)
- 10% TransactionTemplate (세밀 제어)
// ILIC 의 활용 (가끔)
@Service
public class ShipmentBatchService {
@Autowired TransactionTemplate transactionTemplate;
public void processBatch(List<Long> ids) {
for (Long id : ids) {
// 개별 트랜잭션 (실패해도 다른 거 계속)
try {
transactionTemplate.executeWithoutResult(status -> {
Shipment s = repo.findById(id).orElseThrow();
s.process();
});
} catch (Exception e) {
log.error("Failed processing {}", id, e);
// 다음 거 계속
}
}
}
}
// 이런 케이스에 TransactionTemplate
// 메서드 전체가 트랜잭션 아닐 때
// 일반: @Transactional 표준 (Phase 7)
class Shipment { void process() {} }
ShipmentRepository repo;
interface ShipmentRepository { java.util.Optional<Shipment> findById(Long id); }
class TransactionTemplate {
void executeWithoutResult(java.util.function.Consumer<TransactionStatus> c) {}
}
TransactionTemplate transactionTemplate;
class TransactionStatus {}
org.slf4j.Logger log;
@interface Service {}
@interface Autowired {}
TransactionTemplate 의 활용은?
답:
1. TransactionTemplate:
패턴:
vs @Transactional:
실무:
3가지 구현체 (Phase 6.2):
1. DataSourceTransactionManager:
- JDBC / JdbcTemplate
- 6주차 학습 활용
2. HibernateTransactionManager:
- Hibernate 직접
- 옛 스타일
3. JpaTransactionManager:
- JPA / Spring Data JPA
- 현대 표준
선택 기준:
사용 기술 → 구현체:
JdbcTemplate 만 사용:
→ DataSourceTransactionManager
Hibernate 직접 (JPA X):
→ HibernateTransactionManager
(드묾)
JPA / Spring Data JPA:
→ JpaTransactionManager
Spring Boot:
- 자동 선택
- 의존성에 따라
6주차 ↔ 7주차:
6주차 (DataSource):
- DataSource 인터페이스
- HikariDataSource 구현
7주차 (Transaction Manager):
- PlatformTransactionManager 인터페이스
- 3가지 구현체
같은 구조:
- Application
↓ 인터페이스
구현체
→ 5주차 디자인 패턴 일관 적용
Spring Boot 의 자동:
spring-boot-starter-data-jpa:
- JPA + Hibernate
- JpaTransactionManager 자동
spring-boot-starter-jdbc:
- JDBC + JdbcTemplate
- DataSourceTransactionManager 자동
→ 의존성만으로 결정
| Q | 핵심 답변 |
|---|---|
| PlatformTransactionManager? | Spring 트랜잭션 인터페이스 |
| 3 메서드? | getTransaction/commit/rollback |
| DIP / OCP? | 인터페이스 의존 |
| 6주차 DataSource 와? | 같은 사상 |
| TransactionDefinition? | 트랜잭션 설정 |
| TransactionStatus? | 트랜잭션 상태 |
| TransactionTemplate? | 람다 자동화 |
| 3 구현체? | DS/Hibernate/JPA TM |
| Spring Boot? | 자동 선택 |
| @Transactional? | 위에 어노테이션 (Phase 7) |
답:
답:
답:
답:
답:
1. PlatformTransactionManager = Spring 트랜잭션 추상화
2. 인터페이스 의존의 가치
3. 추상화의 단계
이번 Unit에서 인터페이스를 봤다면, 다음은 3가지 구현체 상세.
🎯 Phase 6 — PlatformTransactionManager
✅ Unit 6.1 인터페이스 추상화 ← 여기
⏭ Unit 6.2 3가지 구현체
⏭ Unit 6.3 사용 전후 비교
🗂️ Part A — 데이터 모델링과 ORM (완주)
✅ Phase 1-4 (16)
🔄 Part B — 트랜잭션 추상화의 진화
✅ Phase 5 (2)
🎯 Phase 6 (1/3)
총: 19/24 Unit (79%)
🎯 Phase 6 시작 — Spring 의 트랜잭션 추상화