본문 바로가기
Spring

[dbcp2] connection pool 설정

by ghan2 2024. 4. 18.

커넥션 풀을 설정해주지 않아서 데이터베이스 서버의 접속이 제한됐던 적이 있다.

connection pool을 사용하면 DB Connection 수를 제한할 수 있어서 과도한 접속으로 인한 서버 자원 고갈을 예방할 수 있다

DB Connection

- DB를 사용하기 위해 DB와 애플리케이션 간 통신을 할 수 있는 수단
- DB Connection은 Database Driver와 Database 연결 정보를 담은 URL이 필요함
- Java의 DB Connection은 JDBC를 주로 이용하는데, URL 타입을 사용함

JDBC의 실행구조

  1. DB 벤더에 맞는 드라이버 로드
  2. DB 서버의 IP, ID, PW 등을 DriverManager 클래스의 getConnection() 메소드를 사용하여 Connection 객체 생성
  3. Connection에서 PreparedStatement 객체를 받음
  4. executeQuery를 수행하고 ResultSet 객체를 받아 데이터를 처리
  5. 사용하였던 ResultSet, PreparedStatement, Connection을 close

* 이 때, getConnection()은 자바 프로그램과 실제 데이터베이스를 네트워크 상으로 연결해준다. 연결에 성공하면 DB와의 연결 상태를 Connection 객체로 표현하여 반환한다.-> 이 과정이 가장 부하가 많이 걸리는 작업이다.

 

Connection Pool

  • 웹 컨테이너(WAS)가 실행되면서 일정량의 Connection 객체를 미리 만들어서 pool에 저장했다가, 클라이언트 요청이 오면 Connection 객체를 빌려주고 해당 객체의 임무가 완료되면 다시 Connection 객체를 반납 받아서 pool에 저장하는 프로그래밍 기법이다.
  • Container 구동 시 일정 수의 Connection 객체를 생성하게 되며 클라이언트의 요청에 의해 애플리케이션이 DBMS 작업을 수행해야 하면, Connection Pool에서 Connection 객체를 받아와 작업을 진행한다. 이후 작업이 끝나면 Connetion Pool에 Connection 객체를 반납한다.

Connection Pool 장점

  • DB 접속 설정 객체를 미리 만들어 연결하여 메모리 상에 등록해 놓기 때문에 불필요한 작업(커넥션 생성, 삭제)이 사라지므로 클라이언트가 빠르게 DB에 접속이 가능하다.
  • DB Connection 수를 제한할 수 있어서 과도한 접속으로 인한 서버 자원 고갈 방지가 가능하다.
  • DB 접속 모듈을 공통화하여 DB 서버의 환경이 바뀔 경우 쉬운 유지 보수가 가능하다.
  • 연결이 끝난 Connection을 재사용함으로써 새로 객체를 만드는 비용을 줄일 수 있다.

Connection Pool 유의사항

동시 접속자가 많을 경우

너무 많은 DB 접근이 발생할 경우에는 커넥션은 한정되어 있기 때문에 쓸 수 있는 커넥션이 발납될 때까지 기다려야 한다. 너무 많은 커넥션을 생성할 시에는 커넥션 또한 객체이므로 많은 메모리를 차지하게 되고, 프로그램의 성능을 떨어뜨리는 원인이 된다.

즉, WAS에서 커넥션 풀을 크게 설정하면 메모리 소모가 큰 대신 많은 사용자가 대기 시간이 줄어 들고, 반대로 커넥션 풀을 작게 설정하면 그 만큼 대기 시간이 길어진다. 따라서 사용량에 따라 적정량의 커넥션 객체를 생성해 두어야 한다.

 

* connection의 주체는 thread이다. 

[Spring] Connection Pool 설정

1. maven dependency

<dependency>
	<groupId>org.apache.commons</groupId>
	<artifactId>commons-dbcp2</artifactId>
	<version>2.8.0</version>
</dependency>

2. DataSourceConfig 설정

@Slf4j
@Configuration
@RequiredArgsConstructor
public class DataSourceConfig {

    private final DbProperties dbProperties;
    private final KeyManager keyManager;

    @Bean
    public DataSource dataSource() {
        BasicDataSource basicDataSource = new BasicDataSource();

        basicDataSource.setDriverClassName(keyManager.keyStore(dbProperties.getDriver()));
        basicDataSource.setUrl(keyManager.keyStore(dbProperties.getUrl()));
        basicDataSource.setUsername(keyManager.keyStore(dbProperties.getUsername()));
        basicDataSource.setPassword(keyManager.keyStore(dbProperties.getPassword()));

        basicDataSource.setInitialSize(dbProperties.getInitialSize());
        basicDataSource.setMaxTotal(dbProperties.getMaxTotal());
        basicDataSource.setMaxIdle(dbProperties.getMaxIdle());
        basicDataSource.setMinIdle(dbProperties.getMinIdle());

        basicDataSource.setTestOnBorrow(true);
        basicDataSource.setValidationQuery("SELECT 1");

        basicDataSource.setMaxWaitMillis(dbProperties.getMaxWait());
        return basicDataSource;
    }

}

3. DbProperties 설정

@Getter
@Setter
@ConfigurationProperties(prefix = "leather.mysql")
public class DbProperties {

    private String driver;

    private String url;

    private String username;

    private String password;

    private Integer initialSize;

    private Integer maxTotal;

    private Integer maxIdle;

    private Integer minIdle;

    private Long maxWait;

}

- application.properties 설정

3. key manager 설정