JAVA - Connection Pool ( DataSource, HikariCP )

TopOfTheHead·2026년 4월 16일

자바 ( JAVA )

목록 보기
25/28

Connection Pool
DB Connection재사용을 위해 저장 및 관리하는 저장공간
Spring에서 HikariCPConnection Pool로서 기능

Connection Pool어플리케이션 생애주기 간 오직 한 개만 생성되어 관리되어야한다.
Connection Pool중복으로 생성 시 DB Connection 객체 수 가 중복을 통해 과도하게 많아지므로 Connection Pool은 하나로만 관리

Connection PoolDB Connection 객체유휴 상태로 저장 및 필요 시 제공
▶ 제공된 Connection객체.close() 된 경우 Connection Pool로 반납

。저장중인 DB Connection 객체유휴시간이 경과된 경우 종료재시작

。보통 10개 안팎Connection을 생성 및 관리
DB Connection 객체 수가 과도하게 많아질수록 DB가 감당이 불가능

  • Connection Pool을 사용하는 이유?
    。매 요청마다 DriverManager.getConnection()을 통해 즉석에서 DB Connection 생성 시 SQL문 실행 시간보다 TCP Transaction에 의한 DB Connection 연결 시간이 더욱 많이 소요되는 단점이 존재
    어플리케이션 구동 동안 다수의 DB 연결이 수행되므로 요청 시 즉석에서 DB Connection을 각각 생성하는 경우 성능에 매우 치명적으로 작용

    주휴 : 어플리케이션 실행 시점에서 일정 갯수의 Connection을 생성하여 Connection Pool에 저장 및 필요 시 즉시 제공함으로써 실행 시간을 단축
    DB Connection 객체재사용을 통해 DB 연결비용을 최소화

  • Connection Pool 당 권장하는 DB Connection 수
    HikariCP 공식문서 상 ( CPU 코어 수 * 2 ) + 유효 디스크 스핀들 수 를 권장
    유효 디스크 스핀들 수 = ( SSD 코어수 * 2 + 1 )

DataSource : javax.sql.DataSource
。특정 DBMS에 대한 DB Connection을 생성 및 관리하는 역할을 수행하여 Connection Pool에 대한 표준을 제공하는 인터페이스
JAVA 어플리케이션DBMS에 접근 시 DataSource를 통해 관리되는 DB Connection을 제공받아서

DB Connection을 관리하는 특성에 의해 최적화된 Connection Pool 기능을 제공할 수 있음.
HikariCPDataSource구현하여 Connection Pool로서 기능
MyBatis에서도 PooledDataSource라는 이름으로 Connection Pool 기능을 제공

  • Spring Boot에서 Connection Pool 활용
    Spring Bootapplication.yml에서 spring.datasource의 설정을 수행하는 경우, 해당 설정값을 기반으로 DataSource 객체가 생성되어 Spring Bean으로 등록
    DataSource 구현체의 경우 Hikari Connection Pool을 기반으로 생성됨.
   datasource:
    url: jdbc:h2:mem:test-db;MODE=MYSQL;
    username: sa
    password:
    driver-class-name: org.h2.Driver


application.ymlDataSource 설정을 기반으로 HikariCP가 생성되어 Spring Bean으로 등록

HikariCP ( Hikari Connection Pool )
Connection Pool을 관리하는 DataSource 구현체 클래스
Spring Boot 등 에서 기본적으로 활용

HikariCP 객체 생성 시 java.sql.Connection과 동일하게 사용자 접속 정보 (= DB URL, 사용자ID, 사용자PW, DB드라이버)를 필요로 함.

  • HikariConfig
    。생성할 HikariCP 객체설정 정보를 저장하는 클래스
    접속정보를 지정

    설정된 후 new HikariDataSource(HikariConfig객체)를 통해 HikariCP 객체 생성

    hikariConfig.setMaximumPoolSize(숫자) : Connection Pool에 저장할 최대 DB Connection 수
    hikariConfig.setMinimumIdle(숫자) : Connection Pool에 저장할 최소 DB Connection 수
    hikariConfig.setIdleTimeout(ms시간) : Connection유휴 유지 시간
    hikariConfig.setMaxLifetime(ms시간) : Connection최대 생존 시간

  • HikariDataSource
    Connection Pool 역할을 수행하는 HikariCP 객체
    HikariConfig의 설정을 기반으로 자동으로 설정된 수 만큼의 Connection을 생성 및 준비

    어플리케이션 생애주기 동안 오직 한개의 객체만 생성되어 활용하도록 설정해야함.

    HikariDataSource객체.getConnection() : 저장하고 있는 DB Connection 객체를 가져와서 제공

HikariCP를 통해 Connection Pool 생성 및 활용 원리

  • MavenRepository에서 연결할 DBMSDB DriverHikariCP의존성 가져온 후 build.gradle에 설정하기
    주소
    implementation 'com.zaxxer:HikariCP:7.0.2'
    implementation 'com.mysql:mysql-connector-j:9.6.0'
  • Connection Pool 생성 시 필요한 접속정보 정의
    DB URL, 사용자ID, 사용자PW, DB드라이버 경로 정의
 final String JDBC_URL = "jdbc:mysql://localhost:3306/jdbc_shop";
 final String USER = "kf16";
 final String PASSWORD = "wjd747";
 final String DRIVER_CLASS_NAME = "com.mysql.cj.jdbc.Driver";

MySQL 드라이버 ( DBMSJDBC 구현체 )를 사용하도록 External Libraries-MySQL디렉토리-com-mysql-cj-jdbc-Driver디렉토리 경로로 지정

  • HikariConfig : hikariCP 접속 정보세부 설정 정의
    new HikariConfig()를 통해 생성 및 설정
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setJdbcUrl(JDBC_URL);
hikariConfig.setUsername(USER);
hikariConfig.setPassword(PASSWORD);
hikariConfig.setDriverClassName(DRIVER_CLASS_NAME);
hikariConfig.setMaximumPoolSize(10); // Connection Pool에 저장할 최대 DB Connection 수
hikariConfig.setMinimumIdle(5); // Connection Pool에 저장할 최소 DB Connection 수
hikariConfig.setIdleTimeout(600000);        // 유휴 유지 시간: 10분
hikariConfig.setMaxLifetime(1800000);       // 최대 생존 시간: 30분
  • HikariConfig을 활용해 HikariCP 객체 생성
HikariDataSource hikariCP = new HikariDataSource(hikariConfig);

Connection Pool을 단 한번만 생성하여 관리 및 제공하는 Util 역할의 추상클래스 정의하기
Connection Pool어플리케이션 생애주기 간 오직 한 개만 생성되어 관리되므로, 추가적인 Connection Pool의 생성을 차단해야함.

public abstract class ConnectionPoolUtil {
	private static final String JDBC_URL = "jdbc:mysql://localhost:3306/jdbc_shop";
	private static final String USER = "kf16";
	private static final String PASSWORD = "wjd747";
	private static final String DRIVER_CLASS_NAME = "com.mysql.cj.jdbc.Driver";
	private static final HikariDataSource hikariDataSource;
	static {
		HikariConfig hikariConfig = new HikariConfig();
		hikariConfig.setJdbcUrl(JDBC_URL);
		hikariConfig.setUsername(USER);
		hikariConfig.setPassword(PASSWORD);
		hikariConfig.setDriverClassName(DRIVER_CLASS_NAME);
		hikariDataSource = new HikariDataSource(hikariConfig);
	}
	// Connection Pool 반환 메서드
	public static DataSource getDataSource(){
		return hikariDataSource;
	}
    // DB Connection 반환 메서드
	public static Connection getConnection() throws SQLException {
		return hikariDataSource.getConnection();
	}
}
。`HikariDataSource 객체`를 `static 필드`로 관리 및 `static 블록`으로 초기화
      ▶ `어플리케이션 구동` 시점에서 `HEAP 영역` 상의 `추상클래스 프레임`에서 `생애주기` 상 오직 `한번`만 실행되어 초기화

Connection Pool VS 즉석 DB Connection 생성
HikariDataSource 객체에서 DB Connection 객체를 가져온 후 활용 후 반납하는 과정을 50번 반복
IntStream을 통해 반복 수행

try~with문에 의해 DB Connection 객체는 자동으로 close()되어 HikariDataSource로 반납

final int MAX_REPEAT_COUNT = 50;
		// 실행시간 도출
		long start = System.currentTimeMillis();
		IntStream.rangeClosed(1, MAX_REPEAT_COUNT) // 1~ 50까지 배열 생성
			.forEach(
				i -> {
          // try~with 구문을 통해 Util클래스에서 HikariDataSource 객체 가져옴
					try ( Connection conn = ConnectionPoolUtil.getConnection() ) {
						conn.createStatement().execute("select 1"); // 단순 작업 
					} catch (Exception e) {
						throw new RuntimeException(e);
					}
				}
			);
		long end = System.currentTimeMillis() - start;
		// DriverManager 방식( 4500ms )에 비해 매우 짧은 시간이 도출
		System.out.println("%d번 연결 시 %d ms 만큼 시간 소요".formatted(MAX_REPEAT_COUNT, end));

DriveManager에 의해 즉석에서 DB Connection 연결을 생성 후 작업하는 과정을 50번 수행 시 4.5초 경과
HikariCP에서 사전에 준비된 DB Connection을 가져와서 재사용하는 과정을 50번 수행 시 0.330초 경과로 단축

System.currentTimeMillis()
현재 시스템 시간msec으로 제공
완료시점코드 - 시작시점코드 를 통해 해당 코드실행시간을 도출하여 성능 측정이 가능

profile
공부기록 블로그

0개의 댓글