CS study/java

[DataSource]HikariCP DataSource 연동 과정 및 구현체

블랑v 2024. 2. 28. 21:22

 

https://www.javadoc.io/doc/com.zaxxer/HikariCP/latest/com.zaxxer.hikari/com/zaxxer/hikari/package-summary.html

 

com.zaxxer.hikari package summary - HikariCP 5.1.0 javadoc

Latest version of com.zaxxer:HikariCP https://javadoc.io/doc/com.zaxxer/HikariCP Current version 5.1.0 https://javadoc.io/doc/com.zaxxer/HikariCP/5.1.0 package-list path (used for javadoc generation -link option) https://javadoc.io/doc/com.zaxxer/HikariCP/

www.javadoc.io

 

HikariCP를 사용한 DataSource Bean 생성

SpringApplication.run() 호출

이는 일반적으로 Springboot의 ClassPath -cp main에 존재한다.

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;


@EnableScheduling
@SpringBootApplication
public class JdbcServerApplication {
    
    public static void main(String[] args) throws Exception {
        SpringApplication.run(JdbcServerApplication.class, args); //here
    }
}

2. ApplicationContext 생성

SpringApplication.run() 메서드는 ApplicationContext를 생성한다.

SpringApplication 객체가 초기화되면서 다양한 ApplicationContextInitializer 인스턴스들이 실행되고, 이 과정에서 여러 설정과 빈 정의가 로드된다.

3. 자동 구성 활성화: SpringApplication.run() 메서드는 자동 구성을 활성화

자동 구성은 @EnableAutoConfiguration 어노테이션 또는 spring-boot-autoconfigure 모듈에 의해 활성화된다.

-> 이 과정에서 classPath에 존재하는 spring-boot-autoconfigure.jar 파일에 포함된 자동 구성 클래스들을 로드하고 실행

 

4. 자동 구성 실행:

SpringApplication 클래스는 클래스패스에서 자동 구성 클래스들을 찾아 실행

(사실 실행보다는 "적용된다" 또는 "평가되어 적용 조건에 따라 Bean이 등록된다"가 더 정확한 표현이다.)

 

자동 구성 요소는 여러 종류가 존재하며, DataSourceAutoConfiguration은 그 중 하나로, DataSource 관련 자동 구성을 담당한다.

 

DataSourceAutoConfiguration 실행 

DataSourceAutoConfiguration 클래스는 DataSource를 설정하고 구성하기 위한 여러 메서드를 실행한다. 

 

DataSource 설정

DataSourceAutoConfiguration 클래스는 spring.datasource.* 프로퍼티를 참조하여 DataSource를 구성한다.

ex : application.yml 등의 설정 정보 등... 

//흔히 properties에서 등록하는 이런 정보 말이다.
spring.datasource.url=jdbc:mysql://localhost:3306/your_database
spring.datasource.username=your_username
spring.datasource.password=your_password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# HikariCP 설정
spring.datasource.hikari.connection-timeout=20000
spring.datasource.hikari.maximum-pool-size=10

 

이러한 설정 정보를 읽어와서 DataSource를 구성하는 것이다.

이때 클래스패스에 HikariCP가 존재하면, Spring Boot는 HikariCP를 사용하여 DataSource를 설정하게 된다.
기본적으로 아무것도 존재하지 않는다면 마찬가지로 HikariCP를 사용한다.

 

//..생략

@Configuration(
    proxyBeanMethods = false
)
@Conditional({PooledDataSourceCondition.class})
@ConditionalOnMissingBean({DataSource.class, XADataSource.class})
@Import({DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class, DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.OracleUcp.class, DataSourceConfiguration.Generic.class, DataSourceJmxConfiguration.class})
protected static class PooledDataSourceConfiguration {
    protected PooledDataSourceConfiguration() {
    }

    @Bean
    @ConditionalOnMissingBean({JdbcConnectionDetails.class})
    PropertiesJdbcConnectionDetails jdbcConnectionDetails(DataSourceProperties properties) {
        return new PropertiesJdbcConnectionDetails(properties);
    }
}

 

 

빈 등록

DataSource가 구성되면 해당 DataSource 빈이 ApplicationContext에 등록된다.

이후에는 이 DataSource를 필요로 하는 다른 빈들이 이를 주입받아 사용할 수 있다.

 

이 과정을 통해 최종적으로 'DataSource Bean' 인스턴스 객체가 생성된다.

이 인스턴스는 Spring 컨테이너에 등록되어 App 전반에서 호출되며 재사용된다.

 

 

DataSource Instance(HikariCP 사용)은 어떻게 동작하는가?

DataSourceAutoConfiguration을 통해 DataSource 인스턴스를 생성하고 이를 Bean에 등록했다.

(클래스패스에 HikariCP가 있으면 HikariCP DataSource를 사용)

 

이것을 실제 어떻게 사용하는 것일까?

 

1. 연결 객체 (HikariProxyConnection)

HikariCP는 내부적으로 java.sql.Connection 인터페이스를 구현한 연결 객체를 관리하며,
이 연결을 통해 SQL 쿼리가 데이터베이스로 전송된다.

 

이는 com.zaxxer.hikari.pool 패키지 내에서 확인할 수 있다.

 

 

 

 

 

 

 

JDBC와 실제 쿼리 작업 과정 정리

1. java.sql.Connection, java.sql.Statement, java.sql.PreparedStatement, java.sql.ResultSet는 모두 JDBC API의 인터페이스이며, 실제 DB로 쿼리문을 보낼때 이 인터페이스의 구현체를 통해 전송과 수신으로 작업을 수행한다.

 

2. Spring(Boot)에서 일반적으로 초기 Application Context와 Bean 등록 과정이 있다. 이 과정에서 특별한 지시사항이 없다면 일반적으로 HikariCP를 사용하여 DataSource 인스턴스를 생성하고, 이를 Bean에 등록한다.

이 Bean은 DB 작업 시(JDBC API를 통해 1번 시행시) 호출되어 사용한다. 

 

3. HikariCP로 이루어진 DataSource 인스턴스는 다음과 같은 JDBC 구현체를 가진다.

'java.sql.Connection, java.sql.Statement, java.sql.PreparedStatement, java.sql.ResultSet' 의 구현체.

이는 하단에 추가적으로 후술한다.

 

 

JDBC 인터페이스 & HikariCP 구현체 사용 용도 정리

HikariCP에서 사용되는 "구현체"는 실제로는 프록시 또는 래퍼 클래스로, 기존 JDBC 인터페이스를 구현하면서 추가적인 기능을 제공하거나 성능을 향상시킨다.

 

그렇기에 실체 클래스 이름에 전부 'Proxy' 가 붙어서 Wrapping하는 것을 확인할 수 있다.

 

1. HikariProxyConnection

java.sql.Connection 인터페이스의 프록시 구현체로, 데이터베이스와의 연결을 나타낸다.

이 클래스는 연결을 관리하고, 필요에 따라 연결을 풀에 반환하는 역할을 한다.

 

2. Statement와 HikariProxyStatement

간단하거나 한 번만 실행되는 SQL 쿼리 실행에 주로 사용된다.

stmt.executeUpdate("UPDATE users SET name = 'John' WHERE id = 1");

 

3. PreparedStatement와 HikariProxyPreparedStatement

HikariProxyPreparedStatement은 HikariCP 커넥션 풀 라이브러리에 내장된 클래스로, PreparedStatement 인터페이스의 프록시(대리) 구현체이다.

 

이 클래스는 Java의 JDBC API를 통해 데이터베이스에 대한 SQL 명령을 사전 컴파일하고, 해당 명령을 매개변수화하여 실행하는 기능을 제공한다. HikariProxyPreparedStatementPreparedStatement의 기능을 확장하거나 추가하지 않지만, HikariCP의 성능 최적화 및 커넥션 관리 기능을 활용하기 위해 사용된다.

 

4. ResultSet와 HikariProxyResultSet 

쿼리 결과를 나타내며, 데이터베이스에서 조회한 데이터를 읽는 데 사용된다.

ResultSet rs = stmt.executeQuery("SELECT * FROM users"); while (rs.next()) { String name = rs.getString("name"); }