프로그래밍 공부/Spring

[Spring] DB ConnectionPool이란?

DB Connection

  • DB를 사용하기 위해 DB와 애플리케이션 간 통신을 할 수 있는 수단.
  • DB 드라이버와 DB 연결정보를 담은 URL이 필요하다.

DB 커넥션풀

DB 커넥션 객체를 여러 개 생성하여 풀(Pool)에 담아놓고 필요할 때 꺼내쓰는 방식. 즉, 자주 쓰는 객체를 미리 만들고, 사용한 다음 필요할 때마다 가져간 다음에 반납하는 방식(=Pooling)을 의미한다.

 

간단히 정리하자면 다음과 같다.

  • 여러 개의 DB Connection을 하나의 Pool에 모아놓고 관리
  • DB 커넥션 객체를 여러 개 생성한 뒤 Pool에 담아놓고 필요할 때 불러와서 사용
  • 만약, 빌려줄 수 있는 Connection이 없다면 Connection 객체가 반환할 때 까지 클라이언트는 대기 상태로 전환
  • 사용이 끝난 커넥션 객체는 다른 작업에서 다시 사용할 수 있도록 Pool에 반환

 

싱글 커넥션의 문제

그런데, 굳이 여러개를 생성하지 않고 하나만 생성해서 진행해도 되지 않을까?

이러한 방식을 '싱글 커넥션'이라 하였을 때, 아래의 이미지를 확인해보자.

아래의 그림에서 DAO 1→2→3의 순서로 이루어졌다고 하였을 때, 3에서 롤백이 이루어진다면 DAO 1, 2에서 진행된 내용도 이전 상태로 되돌려지게 된다. 이는 굉장히 치명적인 단점이 된다. 그렇기 때문에 우리는 각각 다른 Connection 연결을 가져야 한다.

 

해결책

1. 매번 SQL 작업을 할 때마다 DB 커넥션 객체를 만든다.

Connection conn = null;
PreparedStatement  pstmt = null;
ResultSet rs = null;

try {
    sql = "SELECT * FROM T_BOARD"

    // 1. 드라이버 연결 DB 커넥션 객체를 얻음
    connection = DriverManager.getConnection(DBURL, DBUSER, DBPASSWORD);

    // 2. 쿼리 수행을 위한 PreparedStatement 객체 생성
    pstmt = conn.createStatement();

    // 3. executeQuery: 쿼리 실행 후
    // ResultSet: DB 레코드 ResultSet에 객체에 담김
    rs = pstmt.executeQuery(sql);
    } catch (Exception e) {
    } finally {
        conn.close();
        pstmt.close();
        rs.close();
    }
}

위의 방식처럼 만들게 되면, 실행 속도가 느려지는 단점이 생긴다.

커넥션을 맺을 때마다 DB 서버가 사용자 인증 및 권한 검사, 요청 처리를 위한 준비 작업까지 진행되기 때문이다.

 

2. DB 커넥션 풀

DB 커넥션 풀은 각 요청에 대해 별도의 커넥션 객체를 사용하기에 다른 작업에 영향을 주지 않으며, 사용한 커넥션 객체는 버리지 않고 풀에 보관되므로 속도에도 영향을 주지 않는다.

자바에서는 기본적으로 DataSource 인터페이스를 사용하여 커넥션풀을 관리하며, Spring에서는 사용자가 직접 관리할 필요 없이 자동화된 기법을 제공한다. 참고로 PSring 2.0 이전에는 tomcat-jdbc, 2.0 이후에는 "org.springframework.boot:spring-boot-starter-jdbc" 내에 HikariCP를 기본 옵션으로 제공하고 있다. (참고 - HikariCP의 장점 → 커넥션 풀의 관리가 잘 되어있다.)

 

참고자료

자바 웹 개발 워크북 - 5.12 DB 커넥션 풀