JSP 페이지를 실행할 때마다 커넥션을 생성해서 사용하게 되면 커넥션을 생성하고 닫는데 시간이 소모되기 때문에 동시 접속자 수가 많은 웹 사이트의 경우 전체 성능을 떨어뜨리는 원인이 된다. 성능문제를 해결하기 위해 사용하는 일반적인 방식으로 커넥션 풀 기법이 있는데, 이 글에서는 자카르타 프로젝트의 DBCP API를 이용하여 커넥션 풀을 사용하는 방법에 대해 살펴보도록 하겠다.
1. 커넥션 풀이란?
-- 커넥션 풀 기법이란, 데이터베이스와 연결된 커넥션을 미리 만들어서 풀(pool) 속에 저장해 두고 있다가 필요할 때에 커넥션을 풀에서 가져다 쓰고, 다시 풀에 반환하는 기법을 말한다.
[그림 1] 커넥션 풀 기법
풀 속에 데이터베이스와 연결된 커넥션을 미리 생성해 놓고 있다가, 커넥션이 필요할 경우 풀 속에 미리 생성되어 있는 커넥션을 가져다가 사용하고 다 사용한 커넥션은 다시 풀에 반환한다. 풀에 반환된 커넥션은 다음에 다시 사용된다.
◆ 커넥션 풀의 특징
-- 풀 속에 미리 커넥션이 생성되어 있기 때문에 커넥션을 생성하는데 드는 연결 시간이 소비되지 않는다.
-- 커넥션을 계속해서 재사용하기 때문에 생성되는 커넥션 수가 많지 않다.
커넥션을 생성하고 닫는데 필요한 시간이 소모되지 않기 때문에 그 만큼 어플리케이션의 실행 속도가 빨라지며, 또한 한번에 생성될 수 있는 커넥션 수를 제어하기 때문에 동시 접속자 수가 몰려도 웹 어플리케이션이 쉽게 다운되지 않는다. 커넥션 풀을 사용하면 전체적인 웹 어플리케이션의 성능 및 처리량이 높아지기 때문에 많은 웹 어플리케이션에서 커넥션 풀을 기본으로 사용하고 있다.
2. DBCP API의 사용 방법
자카르타 프로젝트의 DBCP API를 사용할 때에는 다음과 같은 과정을 거치면 된다.
① DBCP 관련 Jar 파일 및 JDBC 드라이버 Jar 파일 설치하기
② 커넥션 풀 관련 설정 파일 초기화하기
③ 커넥션 풀 관련 드라이버 로딩하기
④ 커넥션 풀로부터 커넥션 사용하기
이 네 가지 절차에 대해서 차례대로 살펴보도록 하자.
2.1 필요한 Jar 파일 복사
DBCP API를 사용하기 위해서는 다음과 같은 라이브러리가 필요하다.
- DBCP API 관련 Jar 파일 DBCP 1.2.2 Download
- DBCP API가 사용하는 자카르타 Pool API의 Jar 파일 Pool 1.3 Download
- Pool API가 사용하는 자카르타 Collection API의 Jar 파일 Collections 3.2 Download
이들 라이브러리의 최신 버전은 http://jakarta.apache.org/site/binindex.cgi 에서 다운로드 받을 수 있다.
파일의 압축을 풀면 다음과 같은 Jar 파일들을 발견할 수 있는데, 이들 Jar 파일들을 사용하면 된다.
- common-dbcp-1.2.2.jar
- common-pool-1.3.jar
- common-collections-3.2.jar
이 파일들을 WEB-INFlib 폴더에 복사해 넣는다.
2.2 설정 파일 작성하기
DBCP를 사용하는 방법에는 소스 코드 상에서 커넥션 풀을 설정하는 방법과 설정 파일을 통해서 커넥션 풀을 설정하는 방법 두 가지 존재하는데 여기서는 설정 파일을 이용한 커넥션 풀 설정 방법에 대해서 살펴보도록 하겠다.
DBCP Pool API에서 사용되는 커넥션 풀 설정 파일의 기본 골격은 다음과 같다.
[참고 1] WEB-INFclassespool1.jocl
---------------------------------------------------------------------------------------------------------------------------
01 <object class = "org.apache.common.dbcp.Poolable ConnectionFactory"
02 xmlns = "http://apache.org/xml/xmlsn/jakarta/commons/jocl">
03
04 // DBMS와 연결할 때 사용할 JDBC URL 및 사용자 계정, 암호
05 <object class = "org.apache.commons.dbcp.DriverManagerConnectionFactory">
06 <string value = "jdbc:mysql://localhost:3306/myRoot?.." />
07 <string value = "jspexam" />
08 <string value = "jspex" />
09 </object>
10
11 // 커넥션 풀과 관련된 추가 설정 정보 지정
12 <object class = "org.apache.commons.pool.implGenericObjectPool">
13 <object class = "org.apache.commons.pool.PoolableObjectFactory" null="true" />
14 </object>
15
16 <object class = "org.apache.commons.pool.impl.GenericKeyedObjectPoolFactory" null="true" />
17
18 // 커넥션이 유효한지의 여부를 검사할 때 사용할 쿼리. 쿼리를 지정하고 싶은 경우에는
19 // <string value = "SELECT count(*) FROM member" /> 와 같은 코드를 입력해 주면 된다.
20 <string null="true" />
21
22 // 커넥션을 읽기 전용으로 생성할지의 여부를 지정한다.
23 // insert, update, delete 작업이 있다면 false로 지정해 주어야 한다.
24 <boolean value="false" />
25
26 // 커넥션을 자동 커밋 모드로 설정할 경우 true를, 그렇지 않을 경우 false를 지정한다. 일반적으로 true를 사용한다.
27 <boolean value="true" />
28 </object>
---------------------------------------------------------------------------------------------------------------------------
[참고1] 설정 파일에서 나머지 부분은 그대로 입력하고 라인 05~09 부분만 알맞게 변경하면 된다.
05 <object class = "org.apache.commons.dbcp.DriverManagerConnectionFactory">
06 <string value = "jdbc:mysql://localhost:3306/myRoot?.." />
07 <string value = "jspexam" />
08 <string value = "jspex" />
09 </object>
위 코드에는 세 개의 <string> 태그가 사용되는데, 이들 태그는 각각 순서대로 JDBC URF, 데이터베이스 사용자 계정, 암호를 나타낸다. JDBC URL 부분의 값이 길어서 생략해서 표시했는데 다음과 같이 사용할 수 있다.
jdbc:mysql://localhost:3306/myRoot?useUnicode=true&characterEncoding=euc-kr
*** NOTE
DBCP 커넥션 풀 설정 파일은 XML 문서로 처리된다. XML 문서에서는 엠퍼샌드 기호('&')를 표시할 때 &를 사용해야 하기 때문에 JDBC URL 입력 부분에 useUnicode=true&characterEncoding 대신 useUnicode=true&char...를 사용하였다.
하나의 설정 파일은 하나의 커넥션 풀에 해당한다. 새로운 커넥션 풀을 생성하고 싶다면 [참고 1]과 같은 파일을 하나 새롭게 생성하면 된다.
2.3 설정 파일의 위치
DBCP API는 클래스 패스로부터 설정 파일을 읽어 온다. 따라서 앞서 작성한 커넥션 풀 설정 파일은 클래스 패스에 위치해 있어야 한다. 웹 어플리케이션에서 DBCP API와 관련된 설정 파일의 위치로 가장 좋은 곳은 WEB-INFclasses 폴더이다.
2.4 커넥션 풀 초기화하기
DBCP API를 통해서 커넥션 풀을 사용하기 위해서는 커넥션 풀과 관련된 JDBC 드라이버를 로딩해 주어야 한다. DBCP API를 사용할 때에 로딩해 주어야 할 JDBC 드라이버는 다음과 같다.
- org.apache.commons.dbcp.PoolingDriver -- DBCP API의 JDBC 드라이버
- DBMS에 연결될 때 사용될 JDBC 드라이버
DBCP API를 사용할 때에는 웹 어플리케이션 시작할 때 위에서 언급한 두 가지 형태의 JDBC 드라이버를 로딩하도록 하면 편리하다.
DBCP API와 관련된 JDBC 드라이버를 로딩하는 코드는 다음 [참고 2]와 같다.
[참고 2] WEB-INFjdbcdriverDBCPInit.java
---------------------------------------------------------------------------------------------------------------------------
01 package jdbcdriver;
02
03 import javax.servlet.http.HttpServlet;
04 import javax.servlet.ServletConfig;
05 import javax.servlet.ServletException;
06 import java.util.StringTockenizer;
07
08 public class DBCPInit extends HttpServlet {
09
10 public void init (ServletConfig config) throws ServletException {
11 try {
12 // DBMS와 연결할 때 사용될 JDBC 드라이버 로딩
13 String drivers = config.getInitParameter("jdbcdriver");
14 StringTockenizer st = new StringTokenizer(drivers, ",");
15 while (st.hasMoreTokens()) {
16 String jdbcDriver = st.nextToken();
17 Class.forName(jdbcDriver);
18 }
19
20 // DBCP API에서 풀 기능을 제공하기 위해 사용되는 PoolingDriver 로딩
21 Class.forName("org.apache.commons.dbcp.PoolingDriver");
22
23 // 톰캣 5.0.19에서는 주석을 그대로 두어도 올바르게 실행되지만 톰캣 5.0.2x 버전부터는
24 // 주석을 없애고 SAX 파서를 지정해 주어야 올바르게 실행된다.
25 // System.setProperty("org.xml.sax.driver", "org.apache.crimson.parser.XMLReaderImpl");
26 } catch (Exception ex) {
27 throw new ServletException(ex);
28 }
29 }
30 }
---------------------------------------------------------------------------------------------------------------------------
[컴파일]
C:>cd jakarta-tomcat-5.0.19webappsmyRootWEB-INF
C:..WEB-INF> set PATH=c:j2sdk1.4.2_04bin;%PATH%
C:..WEB-INF> set CLASSPATH=c:jakarta-tomcat-5.0.19commonlibservlet-api.jar;c:jakarta-tomcat-5.0.19commonlibjsp-api.jar;classes
C:..WEB-INF> javac -d classes jdbcdriverDBCPInit.java
컴파일에 성공하면 WEB-INFclassesjdbcdriver 폴더에 DBCPInit.class 파일이 생성될 것이다.
WEB-INFweb.xml 파일에 DBCPInit 서블릿 클래스에 대한 설정 정보를 추가함으로써 웹 어플리케이션이 시작될 때 DBCPInit 서블릿 클래스가 시작될 수 있도록 할 수 있다. 예를 들면, 아래와 같은 코드를 web.xml 파일에 추가해 주면 된다.
---------------------------------------------------------------------------------------------------------------------------
<servlet>
<servlet-name>DBCPInit</servlet-name>
<servlet-class>jdbcdriver.DBCPInit</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>jdbcdriver</param-name>
<param-value>com.mysql.jdbc.Driver</param-value>
<init-param>
</servlet>
---------------------------------------------------------------------------------------------------------------------------
위와 같이 코드를 추가해 주면 웹 어플리케이션이 시작할 때 DBCPInit 서블릿 클래스가 자동으로 시작되고 init() 메소드가 호출된다.
2.5 커넥션 사용하기
커넥션 풀을 위한 JDBC 드라이버 및 DBMS에 연결할 때 사용할 JDBC 드라이버를 로딩하면 커넥션 풀로부터 커넥션을 가져와 사용할 수 있다. 커넥션 풀로부터 커넥션을 가져오는 코드는 별반 다르지 않으며, 다음과 같은 형태의 코드를 사용하면 된다.