안녕세계
[Spring] DataSource와 PlatformTransactionManager 본문
[Spring] DataSource와 PlatformTransactionManager
Junhong Kim 2025. 5. 2. 12:59DriverManager
DriverManager는 JDBC API(Java Database Connectivity API)에서 제공하는 클래스로 데이터베이스와 연결을 직접 생성하고 관리하는 역할을 합니다. (JDBC API에 포함되어있어 별도 설정이 불필요)
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/mydb",
"username",
"password"
);
DriverManager는 구체적인 클래스 기반의 API를 통해 데이터베이스와 직접 상호작용합니다. DB 연결 요청 시 매번 새로운 Connection이 생성되고 직접 관리해야합니다. 매 요청마다 새로운 Connection을 하기 때문에 오버헤드가 증가하고, 다수의 요청이나 동시 접근이 발생할 경우 관리가 어렵습니다.
DataSource
DataSource는 JDBC API의 일부로 포함된 인터페이스이며, 데이터베이스와의 Connection을 얻기 위한 표준적인 방법을 제공합니다. JDBC의 표준 인터페이스로 Connection Pooling 등의 다양한 Connection 관리 전략을 구현할 수 있습니다. DataSource 인터페이스를 구현한 다양한 Connection Pool(예: HikariCP)을 활용할 수 있습니다.
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
dataSource.setUsername("username");
dataSource.setPassword("password");
Connection conn = dataSource.getConnection();
DataSource는 인터페이스 기반으로 구현체에 따라 다양한 방식(풀링, 분산, 로깅 등)의 Connection 관리가 가능합니다. Connection Pool을 이용하여 성능을 개선할 수 있으며, Connection 생성 로직이 추상화 되어 있어 DB 벤더에 독립적인 사용이 가능합니다. 일반적으로 Spring 환경에서는 DriverManager를 직접 쓰기보다는 DataSource를 통해 Connection을 획득합니다.
// 예: 내부적으로 DriverManager를 사용하는 DataSource
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/mydb");
dataSource.setUsername("user");
dataSource.setPassword("password");
return dataSource;
}
// 예: 내부적으로 HikariCP를 사용하는 DataSource
@Bean
public DataSource dataSource() {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
dataSource.setUsername("user");
dataSource.setPassword("password");
dataSource.setMaximumPoolSize(20); // 커넥션 풀 크기
return dataSource;
}

PlatformTransactionManager
PlatformTransactionManager는 Spring 프레임워크의 인터페이스로, 트랜잭션의 생성, commit, rollback을 관리하는 역할을 수행합니다. DriverManager 또는 DataSource를 통해 생성된 데이터베이스 Connection에 대한 트랜잭션 관리를 추상화한 인터페이스입니다. 트랜잭션 관리의 추상화를 통해 DB 종속성 없이 통일된 방식으로 트랜잭션을 관리합니다. 비즈니스 로직에서 발생하는 예외에 따라 커밋과 롤백을 결정합니다. Spring에서 제공하는 선언적 트랜잭션 관리(@Transactional)에서 내부적으로 사용됩니다.
주요 구현체로는 DataSourceTransactionManager와 JpaTransactionManager 등이 있습니다. DataSourceTransactionManager는 순수 JDBC를 사용하는 환경에서 사용되며, DataSource를 통해 제공된 Connection을 기반으로 트랜잭션을 처리합니다.
// 순수 JDBC 기반의 트랜잭션 관리
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
JpaTransactionManager는 트랜잭션 관리 시, 매 트랜잭션마다 새로운 EntityManager를 생성 및 관리해야 하므로 반드시 EntityManagerFactory를 필요로 합니다. JpaTransactionManager는 직접적으로 DataSource를 주입받아 사용하지 않습니다.
대신 EntityManagerFactory 를 통해 간접적으로 데이터베이스 연결을 관리합니다.
// JPA 기반의 트랜잭션 관리 (EntityManager 관리)
@Configuration
@EnableTransactionManagement
public class JpaConfig {
// (1) DataSource 설정
@Bean
public DataSource dataSource() {
HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
ds.setUsername("username");
ds.setPassword("password");
return ds;
}
// (2) EntityManagerFactory 설정 (DataSource를 사용)
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
emf.setDataSource(dataSource); // 여기에서 DataSource 사용
emf.setPackagesToScan("com.example.entity");
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
emf.setJpaVendorAdapter(vendorAdapter);
return emf;
}
// (3) JpaTransactionManager 설정 (EntityManagerFactory 사용, DataSource X)
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
return new JpaTransactionManager(emf); // 🔥 EntityManagerFactory만 받음
}
}
JpaTransactionManager는 EntityManagerFactory에서 트랜잭션마다 새로운 EntityManager를 생성합니다. EntityManager가 DB 연결을 통해 트랜잭션 작업을 수행합니다. EntityManagerFactory는 DB와의 연결을 위해 내부적으로 DataSource를 반드시 필요합니다.

요약
DataSource
- 데이터베이스 Connection을 제공 및 관리합니다.
- PlatformTransactionManager가 관리할 데이터베이스 연결을 제공하는 기반이 됩니다.
PlatformTransactionManager
- 트랜잭션의 생성, 커밋, 롤백을 수행하고 관리합니다.
- DataSource가 제공한 데이터베이스 연결(Connection)을 이용하여 실제 트랜잭션을 처리합니다.
DataSource와 PlatformTransactionManager
- Spring은 설정된 DataSource로부터 Connection을 얻어옵니다.
- 비즈니스 로직 실행 시, @Transactional이 붙은 메서드가 호출되면,
PlatformTransactionManager가 DataSource에서 Connection을 획득하여 트랜잭션을 시작합니다. - 비즈니스 로직이 완료되면, 예외 여부에 따라 트랜잭션을 커밋하거나 롤백합니다.
- 사용이 끝난 Connection은 DataSource의 커넥션 풀로 반환됩니다.
다음 코드에서 @Transactional이 붙은 createUser 메서드 호출 시, DataSource가 제공한 Connection을 PlatformTransactionManager가 이용하여 트랜잭션을 관리한다는 것을 의미합니다.
@Configuration
@EnableTransactionManagement
public class AppConfig {
@Bean
public DataSource dataSource() {
HikariDataSource ds = new HikariDataSource();
ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
ds.setUsername("user");
ds.setPassword("password");
return ds;
}
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
@Service
public class UserService {
private final JdbcTemplate jdbcTemplate;
public UserService(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Transactional
public void createUser(String username, String email) {
jdbcTemplate.update("INSERT INTO users (username, email) VALUES (?, ?)", username, email);
}
}
'Server > Spring' 카테고리의 다른 글
| [Spring] Transaction Propagation (0) | 2025.02.15 |
|---|---|
| [Spring] AOP(Aspect Oriented Programming) (0) | 2025.02.02 |
| [Spring] Bean Life Cycle (0) | 2025.01.05 |
| [Spring] @PostPersist와 TransactionPhase.AFTER_COMMIT (0) | 2024.06.30 |
| [Spring] SSE란? (feat. SseEmitter) (0) | 2024.03.03 |