글 작성자: beaniejoy

안녕하세요~ 이번 시간에는 Connection Pool에 대해서 정리해보고자 합니다. 저번에 Java 카테고리에 JDBC에 대해서 정리하면서 
DAO와 DTO의 개념과 왜 사용하는지에 대해서 알아보았습니다.
(이에 대한 내용은 [Java] JDBC - DAO와 DTO에 대한 내용 링크를 참고하세요!~)

DAO, DTO에 이어서 Connection Pool의 개념과 왜 나오게 되었는지 정리해보도록 하겠습니다.

 

[Java] JDBC - DAO와 DTO에 대한 내용

지난번에는 JDBC 연결과 함께 기본적인 SQL문을 날리는 방법에 대해서 정리해보았습니다. 지난 시간에 이어서 이번에는 JDBC를 더욱 효율적으로 작동하게 만드는 DAO와 DTO에 대해서 정리해보고자

beaniejoy.tistory.com

 

📌 1. Connection Pool은 또 뭐람?

저는 DAO, DTO에 대해서 겨우 이해했는데 또 새로운 개념이 바로 등장해서 아주 혼란스러웠습니다. 지난 시간에 mariaDB Driver를 메모리에 불러와서 실컷 Connection 시키고 PreparedStatement 객체를 이용해서 SQL 쿼리를 DB에 보내고 그 결과값을 받아서 처리해주는 과정을 익혔습니다. 또한 왜 DAO를 singleton으로 만들어서 쿼리를 DB에 보내야 하는지도 배웠습니다. 여기까지는 좋았습니다.

하지만 아직도 해결해야할 과제가 있습니다. 바로 DB와 Connection할 때입니다. DB에 JDBC를 통해 쿼리문을 보내려 할 때마다 Connection을 해서 보내고 결과값을 받아왔습니다. 그런데 다음과 같은 상황에서는 이런 방식이 상당히 비효율적입니다.

 

1-1 서비스해주는 Server와 DB간에 거리가 상당히 먼 경우

 제가 을지로에서 서울 소재의 어떤 서버에 접속했다고 생각해봅시다. 그 때 해당 서버는 DB에서 제가 원하는 데이터들을 가져와서 서비스 해줘야 할 것입니다. 그런데 그 데이터를 담고 있는 DB가 캐나다 토론토에 위치하고 있다면 어떨까요. 요청을 보내고 결과값을 받아오는 동안 12초에서 10분이 걸린다면 서비스를 받고자 하는 저는 그 시간동안 기다려야 할 것입니다.  

 

1-2 - 여러 클라이언트로부터 동시 요청 수가 많아져 DB의 수용범위를 벗어날 때 

 어떤 사이트의 서버에 접속하려는 동시 접속자 수가 많아져 이들의 요청을 서비스해주어야 할 때에도 문제가 발생할 수 있습니다. DB는 한 번에 처리할 수 있는 수가 정해져 있습니다. 그 범위를 벗어나면 에러가 발생하는데 이에 대한 대처도 필요해 보입니다.

 

1-3 여러 문제를 해결해 줄 Connection Pool의 등장

 DB에 데이터를 가져오기 위해 쿼리문을 보낼 때마다 Connection 객체를 생성한다는 것은 상당히 비효율적이라는 것은 알았습니다. 그에 대한 해결책이 있을까요? Connection Pool은 이러한 문제점을 극복하고자 등장했습니다. 하나의 Pool을 만들어서 미리 생성한 여러 Connection 객체들을 담아두고 클라이언트 요청이 들어올 때마다 하나씩 빌려주고 다시 돌려받는 형식이라면 DB에 요청할 때마다 Connection 객체를 생성하지 않아도 됩니다.  미리 생성된 Connection은 ArrayList형태로 담아두었다가 요청이 들어오면 빌려주고 반환하기 전까지 빌린 Connection을 사용하게 됩니다.

 또한 동시접속자 수가 갑자기 급증하더라도 에러가 발생하지 않고 커넥션 풀에 남아있는 커넥션이 없을 경우 접속하려는 클라이언트는 대기상태로 전환됩니다. 다른 클라이언트가 사용을 마치고 반환하면 대기상태가 풀리겠죠? 커넥션 풀은 이와 같이 위의 2가지 문제를 해결해주는 멋진 해결책이라고 할 수 있습니다.

 

📌 2. Connection Pool 이용방법

커넥션 풀에 대해서 알아봤으니 사용하는 방법에 대해서 알아보겠습니다. 우선 커넥션 풀을 사용하기 위한 환경설정이 필요합니다. 

 

2-1 Tomcat dbcp jar파일 설정

Tomcat 4.x 버전까지는 commons-dbcp-xx.jar, commons-collections-xx.jar, commons-pool-xx.jar 세 개의 jar 파일을 받아서 적용해야 했지만 그 이상의 버전에서는 tomcat-dbcp.jar로 통합되어 기본적으로 제공해줍니다. 그래서 tomcat v9.0을 사용하는 저로써는 따로 설정할 필요가 없습니다!

 

2-2 mariadb jdbc 적용

지난번 DAO, DTO를 가지고 jdbc 사용했을 때에도 mariadb-java-client-2.4.4.jar 파일이 필요했습니다. 이번에도 똑같이 web project에 적용해야합니다. WEB-INF/lib 안에 저장하면 됩니다.

 

2-3 context.xml 설정하기 

META-INF 디렉토리 안에 context.xml을 설정해줘야 합니다. context.xml을 통해 Connection할 DB에 대한 정보를 받아 Connection Pool에 담을 Connection을 연결하기 때문에 context.xml 파일 안에 DB 접근에 대한 정보들을 담아야 합니다.

<?xml version="1.0" encoding="UTF-8"?>
<Context>
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    <Resource 
    name="jdbc/hb" 
    auth="Container"
    type="javax.sql.DataSource" 
    driverClassName="org.mariadb.jdbc.Driver"
    url="jdbc:mariadb://localhost/hb?autoReconnect=true"
    username="hb"
    password="hb" 
    maxActive="7" 
    maxIdle="4"
    maxWait="3000" 
    testOnBorrow="true" 
    testOnReturn="false"
    validationQuery="SELECT 1"/>
</Context>
 
  • name : [jdbc/"접근할 database 이름"]
  • url : 접근할 database 주소
  • username : 해당 DB에 접근 권한이 있는 username
  • password : 해당 username의 비밀번호

 

2-4 Connection Pool을 만들어주는 Class 생성

public class ConnLocator {
    public static Connection getConnection() throws SQLException{
        DataSource ds = null;
        Connection con = null;
        
        try {
            Context context = new InitialContext();
            // java:comp/env 는 무조건 고정
            // jdbc/hb는 context.xml의 name과 반드시 같아야 한다.
            ds = (DataSource) context.lookup("java:comp/env/jdbc/hb");
            con = ds.getConnection();
        } catch (NamingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        return con;
    }
}
 

사실 DataSource에서 DriverManager와 Connection Pool을 지원하기 때문에 DataSource를 이용하면 Connection Pool을 따로 만들 필요가 없습니다. DataSource를 이용하기만 하면 됩니다!~

 이제는 쿼리를 보낼 때 Connection Pool을 생성해주는 Class의 메서드를 이용하기만 하면 됩니다. 끝!~

 

틀린 내용이나 부연 설명이 필요한 부분 있으시면 언제든 코멘트 부탁드립니다!~