데이터베이스 커넥션을 매번 획득
TCP/IP
커넥션을 연결한다. 물론 이과정에서 3 way handshake 같은 TCP/IP
연결을 위한 네트워크 동작이 발생한다TCP/IP
커넥션이 연결되면 ID,PW와 기타 부가정보를 DB에 전달한다에플리케이션을 시작하는 시점에 커넥션 풀은 필요한 만큼 커넥션을 미리 확보해서 풀에 보관한다. 보통 얼마나 보관할지는 서비스의 특징과 서버 스펙에 따라 달라진다.
커넥션 풀에 들어있는 커넥션은 TCP/IP로 DB와 커넥션이 연결되어있는 상태이기 때문에 언제든지 즉시 SQL을 DB에 전달 할 수 있다.
커넥션을 모두 사용하고 나면 커넥션을 종료하는 것이 아닌 다음에 다시 사용할 수 있도록 해당 커넥션을 그대로 커넥션풀에 반환하면 된다. 이때 주의해야 할점은 커넥션을 종료하는 것이 아니라 살아있는 상태로 커넥션 풀에 반환해야 한다는 것이다.
커넥션을 얻는 방법은 JDBC DriverManager
를 직접 사용하거나, 커넥션 풀을 사용하는 등 다양한 방법이 존재한다.
하지만 DriverManager
로 커넥션을 획득하다가 커넥션 풀을 사용하는 방법으로 변경하려면 어떻게 해야할까?
예를 들어서 애플리케이션 로직에서 DriverManager
를 사용해서 커넥션을 획득하다가 HikariCP
같은 커넥 션 풀을 사용하도록 변경하면 커넥션을 획득하는 애플리케이션 코드도 함께 변경해야 한다. 의존관계가
DriverManager
에서 HikariCP
로 변경되기 때문이다. 물론 둘의 사용법도 조금씩 다를 것이다.
커넥션을 획득하는 방법을 추상화
javax.sql.DataSource
라는 인터페이스를 제공한다DataSource
는 커넥션을 획득하는 방법을 추상화하는 인터페이스이다DriverManager로 커넥션 획득
@Slf4j
public class ConnectionTest {
@Test
void driverManager() throws SQLException {
Connection con1 = DriverManager.getConnection(URL, USERNAME,PASSWORD);
Connection con2 = DriverManager.getConnection(URL, USERNAME,PASSWORD);
log.info("connection={}, class={}", con1, con1.getClass());
log.info("connection={}, class={}", con2, con2.getClass());
}
}
DriverManagerDataSource 활용
@Test
void dataSourceDriverManager() throws SQLException {
DriverManagerDataSource dataSource =
new DriverManagerDataSource(URL,USERNAME, PASSWORD);
useDataSource(dataSource);
}
private void useDataSource(DataSource dataSource) throws SQLException {
Connection con1 = dataSource.getConnection();
Connection con2 = dataSource.getConnection();
log.info("connection={}, class={}", con1, con1.getClass());
log.info("connection={}, class={}", con2, con2.getClass());
}
}
기존 코드와 비슷하지만 DriverManagerDataSource
는 DataSource
를 통해서 커넥션을 획득할 수 있다
필요한 데이터를 DataSource
가 만들어지는 시점에 미리 다 넣어두게 되면, DataSource
를 사용하는 곳에서는 dataSource.getConnection()
만 호출하면 되므로,
URL
, USERNAME
, PASSWORD
같은 속성들에 의존하지 않아도 된다. 그냥 DataSource
만 주입받아서
getConnection()
만 호출하면 된다.
리포지토리(Repository)는 DataSource
만 의존하고, 이런 속성을 몰라도 된다.
데이터소스 커넥션 풀 추가
@Test
void dataSourceConnectionPool() throws SQLException, InterruptedException {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl(URL);
dataSource.setUsername(USERNAME);
dataSource.setPassword(PASSWORD);
dataSource.setMaximumPoolSize(10);
dataSource.setPoolName("MyPool");
useDataSource(dataSource);
Thread.sleep(1000); //커넥션 풀에서 커넥션 생성 시간 대기
}
MyPool
이라고 지정MemberRepositoryV0 => MemberRepositoryV1
@Slf4j
public class MemberRepositoryV1 {
private final DataSource dataSource;
public MemberRepositoryV1(DataSource dataSource) {
this.dataSource = dataSource;
}
private void close(Connection con, Statement stmt, ResultSet rs) {
JdbcUtils.closeResultSet(rs);
JdbcUtils.closeStatement(stmt);
JdbcUtils.closeConnection(con);
}
private Connection getConnection() throws SQLException {
Connection con = dataSource.getConnection();
log.info("get connection={}, class={}", con, con.getClass());
return con;
}
}
DataSource
의존관계 주입JdbcUtils
편의 메서드 변경
출처: https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-db-1