[Spring]Connection Pool과 DataSource

JANG SEONG SU·2023년 10월 30일
0

Sping

목록 보기
8/9

1. Connection Pool(커넥션 풀)

1-1. DB Connection 획득

  1. 어플리케이션 로직은 DB Driver를 통해 Connection을 조회
  2. DB Driver는 TCP/IP로 DB와 커넥션 연결 (이 과정에서 3-way handshake와 같은 동작이 발생한다.)
  3. DB Driver는 USERNAME/URL/PW 와 같은 부가정보를 DB에 전달한다.
  4. DB는 부가 정보를 바탕으로 내부 인증을 완료하고, DB 세션을 생성한다.
  5. DB는 DB Driver에게 커넥션 생성 완료 응답을 전송한다.
  6. DB Driver는 커넥션 객체를 생성해서 클라이언트에게 반환한다.

위 과정처럼 커넥션을 생성하면서 획득하는 과정으 복잡하고 비용도 많이 든다. 만약 웹 서버에서 DB에 접속할 때마다 위와 같은 과정이 일어나면 비효율적이다.

이를 해결하기 위해 Connection Pool의 개념이 나왔다.

1-2. Connection Pool 방식

커넥션 초기화

  • 어플리케이션이 시작하는 시점에 Connection Pool은 필요한 만큼 Connection을 미리 확보해서 Pool에 보관하는 방식
  • Pool에 있는 Connection들은 TCP/IP로 모두 DB와 커넥션이 연결되어 있는 상태이므로, 언제든지 DB에 SQL을 전달할 수 있다.

커넥션 획득

  • 어플리케이션 로직은 DB Driver를 통해 매번 새로운 Connection을 획득하는 것이 아닌, Connection Pool에서 이미 연결되어 있는 커넥션을 꺼내 쓴다.

커넥션 반환

  • Connection 사용 후 종료하는 것이 아닌, 다음에 다시 사용할 수 있도록 Connection Pool에 반환한다.

1-3 참고.

  • 각 어플리케이션마다의 Connection PoolConnection 개수는 서버 스펙, DB 스펙에 따라 다르기 때문에, 성능 테스트를 통해서 결정해야한다.
  • 대표적으로는 commons-DBCP2 tomcat-jdbc pool HicariCP 등이 있고, Spring 2.0 부터는 기본으로 HicariCP를 제공한다.

2. DataSource

위 그림과 같이 DB Connection을 획득하기 위해서는 생성 방식 Connection Pool 방식 등이 있다.

하지만 만약 기존에 DriverManager로 커넥션 생성 방식을 사용하고 있다가, DBCP2HikariCP와 같은 Pool 방식으로 교체한다고 하면, 많은 어플리케이션 코드도 수정되어야 할 것이다.

이러한 문제를 해결하기 위해, DataSource가 등장한다!!

2-1. Connection 획득 방법의 추상화

위 그림과 같이, DBCP2 HikariCP DriverManager 등 Connection 획득 방법을 추상화한다면, 어떤 Connection 획득 방법을 사용하든지 상관 없다. 왜냐하면 우리는 DataSource라는 추상화된 인터페이스에만 의존하면 되기 때문이다.

public interface DataSource  extends CommonDataSource, Wrapper {
    Connection getConnection() throws SQLException;
}
  • 자바는 javax.sql.DataSource라는 인터페이스를 제공
  • DataSource에는 Connection을 반환하는 getConnection()메소드가 존재
  • 즉, 즉, DBCP2 HikariCP에 직접 의존하는 것이 아닌, DataSource 인터페이스에만 의존

2-2. DriverManager와 DriverManagerSource

사실 DriverManagerDataSource 인터페이스를 사용하지 않는다. 그렇다면 어떻게 DriverManager를 사용하는 DataSource의 구현체는 무엇일까?

바로 DriverManagerDataSource를 통해 사용할 수 있도록 DriverManagerSource라는 클래스가 존재한다.

정리하자면, DriverManagerDataSource를 통해서 DriverManager 를 사용하다가 HikariCP를 사용하더라도 애플리케이션 로직은 변경하지 않아도 된다!!

코드

/* DriverManager를 통한 Connection 획득 */
@Test
void driverManager() throws SQLException {
    Connection con1 = DriverManager.getConnection(URL, USERNAME, PASSWORD);
    Connection con2 = DriverManager.getConnection(URL, USERNAME, PASSWORD);
}
/* DriverManagerDataSource를 통한 커넥션 획득 */
@Test
void dataSourceDriverManager() throws SQLException {
    DataSource 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 내부에서 DriverManager사용
  • DriverManagergetConnection()을 통해 커넥션을 획득할 때마다 URL, USERNAME, PASSWORD와 같은 파라미터를 계속 넘겨주어야 한다
  • DriverManagerDataSource는 처음 객체를 생성할 때만 파라미터를 넘겨주고, 커넥션을 획득할 때는 dataSource.getConnection()만 호출

위 코드처럼 DriverManagerDataOusrce사용설정을 분리했다. 이로써 RepositoryDataSource만 의존하고, 사용 설정을 모른 상태로 getConnetion()만 사용하면 된다.


profile
Software Developer Lv.0

0개의 댓글