Connection Pool & DataSource

박병욱·7일 전

Spring DB

목록 보기
2/2
post-thumbnail

🏊‍♂️ 커넥션 풀

원래 DB와의 커넥션을 만들 때는 DB 드라이버가 TCP/IP 연결을 만들고, DB 인증 및 권한을 확인해야 했다. 또 세션을 생성하고, 커넥션 객체를 다시 애플리케이션 로직에 반환하는 등 매우 복잡하고 번거로운 과정을 거쳐야 했다.

그래서 미리 커넥션을 여러 개 만들어 두고 재사용 하자는 아이디어가 바로 커넥션 풀(Connection Pool)이다. 애플리케이션이 시작하는 시점에 필요한 만큼의 커넥션을 미리 풀에 보관하는 것이다.

위 그림과 같이 커넥션 풀에 존재하는 커넥션들은 이미 TCP/IP로 연결되어 있는 상태이기 때문에 필요할 때 그냥 꺼내서 SQL 쿼리를 DB에 날리면 된다. 이제는 DB 드라이버를 통해 새로운 커넥션을 획득하는 것이 아닌, 이미 생성되어 있는 커넥션을 객체 참조로 그냥 가져다 쓰기만 하면 된다는 것이다.

커넥션 풀은 HikariCP라는 오픈소스를 사용하도록 하자. 스프링 부트 2.0 부터는 기본적으로 커넥션 풀로 HikariCP를 제공하고 있다. 성능과 사용의 편리함 측면에서 아주 탁월하다. 아래 벤치마킹을 보다시피 다른 프레임워크보다 성능이 월등하다.

 

🔗 DataSource?

말했다시피 기존의 DriverManagergetConnection() 메서드를 통해 커넥션을 얻으려 하면, 굉장히 번거로운 과정을 거쳐야 했다. 그래서 커넥션을 얻는 방법을 DataSource라는 인터페이스로 추상화했다. 커넥션을 획득할 수 있는 여러 방법이 있고, 각각의 방법을 사용하기 위해 애플리케이션 코드를 수정하지 않고 그냥 DataSource 인터페이스에 의존하고 구현체만 갈아 끼우면 된다.

이제 기존의 DriverManager를 사용해서 커넥션을 획득했던 방식과 스프링이 제공하는 DriverManagerDataSource과 커넥션 풀을 사용해서 커넥션을 획득하는 방식을 비교해보자.

 

🎏 DriverManager VS DriverManagerDataSource

// 1. DriverManager 사용
@Test
void driverManager() throws SQLException {
    Connection connection1 = DriverManager.getConnection(URL, USERNAME, PASSWORD);
    Connection connection2 = DriverManager.getConnection(URL, USERNAME, PASSWORD);
    log.info("connection: {}, class={}", connection1, connection1.getClass());
    log.info("connection: {}, class={}", connection2, connection2.getClass());
}

// 2. DriverManagerDataSource 사용
@Test
void dataSourceDriverManager() throws SQLException {
    DriverManagerDataSource dataSource = new DriverManagerDataSource(URL, USERNAME, PASSWORD);
    useDataSource(dataSource);
}

private void useDataSource(DataSource dataSource) throws SQLException {
    Connection connection1 = dataSource.getConnection();
    Connection connection2 = dataSource.getConnection();
    log.info("connection: {}, class={}", connection1, connection1.getClass());
    log.info("connection: {}, class={}", connection2, connection2.getClass());
}

DriverManager를 사용하면 커넥션을 획득할 때마다 파라미터를 계속 넘겨줘야 하지만, DataSource를 사용하는 방식은 처음 객체를 생성할 때만 파라미터를 넘기고, 이후에는 그냥 getConnection() 메서드만 호출하면 된다.

 

🌊 커넥션 풀 활용

@Test
void dataSourceConnectionPool() throws SQLException, InterruptedException {
    // 커넥션 풀링
    HikariDataSource dataSource = new HikariDataSource();
    dataSource.setJdbcUrl(URL);
    dataSource.setUsername(USERNAME);
    dataSource.setPassword(PASSWORD);
    dataSource.setMaximumPoolSize(10);
    dataSource.setPoolName("MyFirstConnectionPool");

    useDataSource(dataSource);
    Thread.sleep(1000);  // 커넥션 풀에서 커넥션이 생성되기까지 대기
}

여기서는 HikariCP 커넥션 풀을 사용했다. 보다시피 HikariDataSource도 내부적으로는 DataSource를 구현하고 있다.

profile
도메인을 이해하는 백엔드 개발자(feat. OOP)

0개의 댓글