데이터베이스 커넥션을 획득할 때는 다음과 같은 과정을 거치게 된다.
TCP/IP
커넥션을 연결하는데, 이 과정에서 3 way handshake
같은 네트워크 동작이 발생하게 된다. -> 많은 리소스가 들게 된다.TCP/IP
커넥션이 연결되면, ID / PW 같은 정보를 데이터베이스에 전달한다.커넥션을 새로 만드는 과정은 복잡하고 시간도 많이 소모된다.
데이터베이스 뿐만 아니라 애플리케이션 서버에서도
TCP/IP
커넥션을 생성하기위한 리소스를 매번 사용하게 되고
그 결과 좋지 않은 유저경험을 주게 된다.
위와 같은 문제를 해결하기 위해 커넥션을 미리 생성해두고 재사용 하는 Connection Pool 이라는 방법이다.
애플리케이션이 시작하는 시점에서 미리 필요한 만큼의 커넥션을 미리 확보해서 풀에 보관한다.
서버 스펙에 따라 다르겠지만 기본값은 보통 10개이다.
커넥션 풀에 들어있는 커넥션 들은 애플리케이션 실행 시점에 이미 데이터베이스와 TCP/IP
연결이 완료된 상태이기 때문에 언제든지 TCP/IP
연결 과정을 생략하고 데이터베이스와 통신할 수 있다.
HikariCP
가 있다.DataSource는 커넥션을 획득하는 방법을 추상화 하는 인터페이스 이다.
public interface DataSource {
Connection getConnection() throws SQLException;
}
DataSource
인터페이스를 이미 구현해 뒀기 때문에HikariCP 커넥션 풀
에게 의존 하는것이 아닌 DataSource
인터페이스 에게만 의존하면 된다.public void dataSourceDriverManager() throws SQLException {
DriverManagerDataSource dataSource = new DriverManagerDataSource(URL,USERNAME, PASSWORD);
useDataSource(dataSource);
}
private void useDataSource(DataSource dataSource) throws SQLException {
Connection con1 = dataSource.getConnection();
log.info("connection={}, class={}", con, con.getClass());
}
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);
}
설정과 사용의 분리
- 설정 : DataSource 를 만들고 필요한 속성들을 사용해서
URL , USERNAME , PASSWORD 같은 부분을 입력하는 것을 말한다.
이렇게 설정과 관련된 속성들은 한 곳에 있는 것이 향후 변경에 더 유연하게 대처할 수 있다.- 사용 : 설정은 신경쓰지 않고, DataSource 의 getConnection() 만 호출해서 사용하면 된다.
public class MemberRepository {
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;
}