누군가가 동일한 책을 보고 아래와 같이 책내용을 그래로 쳐놨길래 스크랩 했다.
[커넥션 풀 기법]
커넥션 풀 기법에서는 위 그림과 같이 풀 속에 데이터베이스와 연결된 커넥션을 미리생성해놓고 있는다. 데이터베이스 커넥션이 필요할 경우, 커넥션을 새로 생성하는 것이 아니라 풀 속에 미리 생성되어 있는 커넥션을 가져다가 사용하게 된다. 다 사용한 커넥션은 다시 풀에 반환한다. 풀에 반환된 커넥션은 다음에 다시 사용된다.
커넥션 풀의 특징은 다음과 같다.
커넥션을 생성하고 닫는 데 필요한 시간이 소모되지 않기 때문에 그 만큼 어플리케이션의 실행 속도가 빨라지며, 또한 한번에 생성될 수 있는 커넥션 수를 제어하기 때문에 동시 접속자수가 몰려도 웹 어플리케이션이 쉽게 다운되지 않는다.
커넥션 풀을 사용하면 전체적인 웹 어플리케이션의 성능 및 처리량이 높아지기 때문에 많은 웹 어플리케이션에서 커넥션 풀을 기본으로 사용하고 있다.
DBCP API의 사용방법
자카르타 프로젝트의 DBCP API를 사용할 때에는 다음과 같은 과정을 거치면 된다.
이 네 가지 절차에 대해서 차례대로 살펴보도록 하자.
필요한 Jar 파일 복사
DBCP API를 사용하기 위해서는 다음과 같은 라이브러리가 필요하다.
이들 라이브러리의 최신 버전은 http://jakarta.apache.org/site/binindex.cgi 에서 다운로드 받을 수 있으며, 이 글에서는 다음 버전을 사용하여 예제를 작성하였다.
이들 파일의 압축을 풀면 다음과 같은 Jar 파일들을 발견할 수 있는데, 이들 Jar 파일들을 사용하면 된다.
예제로 제공되는 파일에는 pool\WEB-INF\lib 폴더에는 이미 이들 Jar 파일들이 포함되어 있으므로 별도로 복사하지 않더라도 DBCP를 사용하는 본 장의 예제들을 실행할 수 있게 된다.
커넥션 풀 설정 파일 작성하기
DBCP를 사용하는 방법에는 소스 코드 상에서 커넥션 풀을 설정하는 방법과 설정 파일을 통해서 커넥션 풀을 설정하는 방법 두가지 존재하는데 본 장에서는 설정 파일을 이용한 커넥션 풀 설정 방법에 대해서 살펴보도록 하겠다.
DBCP Pool API에서 사용되는 커넥션 풀 설정 파일의 기본 골격은 아래 코드와 같다.
파일명: pool\WEB-INF\classes\pool1.jocl <object class="org.apache.commons.dbcp.PoolableConnectionFactory"
xmlns="http://apache.org/xml/xmlns/jakarta/commons/jocl">
<object class="org.apache.commons.dbcp.DriverManagerConnectionFactory">
<string value="jdbc:mysql://localhost:3306/shop?useUnicode=true&characterEncoding=euckr" />
<string value="tsum" />
<string value="tsum" />
</object>
<object class="org.apache.commons.pool.impl.GenericObjectPool">
<object class="org.apache.commons.pool.PoolableObjectFactory" null="true" />
<int value="10" />
<byte value="1" />
<long value="10000" />
<int value="10" />
<int value="3" />
<boolean value="true" />
<boolean value="true" />
<long value="600000" />
<int value="5" />
<long value="3600000" />
<boolean value="true" />
</object>
<object class="org.apache.commons.pool.impl.GenericKeyedObjectPoolFactory" null="true" />
<string null="true" />
<boolean value="false" />
<boolean value="true" />
</object>
위 코드에서 나머지 부분은 그대로 입력하고 다음 부분만 알맞게 변경하면 된다.
<object class="org.apache.commons.dbcp.DriverManagerConnectionFactory"> <string value="jdbc:mysql://localhost:3306/..." /> <string value="jspexam" /> <string value="jspex" /> </object>
위 코드에는 세 개의 <string> 태그가 사용되는데, 이들 태그는 각각 순서대로 JDBC URL, 데이터베이스 사용자 계정, 암호를 나타낸다.
설정 파일의 위치
DBCP API는 클래스패스로부터 설정 파일을 읽어온다. 따라서 앞서 작성한 커넥션 풀 설정 파일은 클래스패스에 위치해 있어야 한다. 웹 어플리케이션에서 DBCP API와 관련된 설정 파일의 위치로 가장 좋은 곳은 WEB-INF\classes 폴더이다. 본 글의 예제에서 사용하는 커넥션 풀 설정 파일은 모두 WEB-INF\classes 폴더에 위치시켰다.
커넥션 풀 초기화
DBCP API를 통해서 커넥션 풀을 사용하기 위해서는 커넥션 풀과 관련된 JDBC 드라이버를 로딩해주어야 한다. DBCP API를 사용할 때에 로딩해주어야 할 JDBC 드라이버는 다음과 같다.
웹 어플리케이션 시작할 때 위에서 언급한 두 가지 형태의 JDBC 드라이버를 로딩하도록 하면 편리할 것이다. 웹 어플리케이션이 시작할 때 자동으로 시작되는 JDBC 드라이버를 로딩하도록 구현한 서블릿 클래스는 다음 코드와 같다.
파일명: pool\WEB-INF\src\madvirus.jdbcdriver\DBCPInit.java package madvirus.jdbcdriver; import javax.servlet.http.HttpServlet; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import java.util.StringTokenizer; public class DBCPInit extends HttpServlet { public void init(ServletConfig config) throws ServletException { try { String drivers = config.getInitParameter("jdbcdriver"); StringTokenizer st = new StringTokenizer(drivers, ","); while (st.hasMoreTokens()) { String jdbcDriver = st.nextToken(); Class.forName(jdbcDriver); } Class.forName("org.apache.commons.dbcp.PoolingDriver"); System.setProperty("org.xml.sax.drvier", "org.apache.crimson.parser.XMLReaderImpl"); } catch(Exception ex) { throw new ServletException(ex); } } }
DBCPInit 서블릿은 "jdbcdriver" 초기화 파라미터로부터 로딩할 JDBC 드라이버를 입력받아 JDBC 드라이버를 차례대로 로딩한다. 그런 후, DBCP API의 JDBC 드라이버인 PoolingDriver 을 로딩한다. 마지막으로 설정 파일을 분석할 때 사용할 XML 파서를 지정한다. 위 코드는 Sun 사에서 배포한 JDK 1.4를 기준으로 XML 파서를 지정하였는데, 만약 다른 XML 파서를 사용한다면 알맞게 변경해주어야 한다.
WEB-INF\web.xml 파일에 DBCPInit 서블릿 클래스에 대한 설정 정보를 추가함으로써 웹 어플리케이션이 시작될 때 DBCPInit 서블릿 클래스가 시작될 수 있도록 할 수 있다. 예를 들면, 아래와 같은 코드를 web.xml 파일에 추가해주면 된다.
<servlet> <servlet-name>DBCPInit</servlet-name> <servlet-class>madvirus.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>
위와 같이 코드를 web.xml 파일에 추가해주면 웹 어플리케이션이 시작할 때 DBCPInit 서블릿 클래스가 자동으로 시작되고 init() 메소드가 호출된다.
커넥션 풀로부터 커넥션 사용하기
커넥션 풀을 위한 JDBC 드라이버 및 DBMS에 연결할 때 사용할 JDBC 드라이버를 로딩하면 커넥션 풀로부터 커넥션을 가져와 사용할 수 있다. 커넥션 풀로부터 커넥션을 가져오는 코드는 별반 다르지 않으며, 다음과 같은 형태의 코드를 사용하면 된다.
Connection conn = null; .... try { String jdbcDriver = "jdbc:apache:commons:dbcp:/pool1"; conn = DriverManager.getConnection(jdbcDriver); ... } finally { ... if (conn != null) try { conn.close(); } catch(SQLException ex) {} }
위 코드를 보면 DBCP API 기반의 커넥션 풀을 사용한다고 해서 특별히 코드가 달라지는 부분이 없다는 것을 알 수 있다. 일반 경우와 마찬가지로 DriverManager.getConnection() 메소드를 사용해서 커넥션을 구해오고, 커넥션을 다 사용하면 close() 메소드를 사용하여 사용한 커넥션을 닫는다. 차이점이라면 JDBC URL이 다음과 같은 형태를 띈다는 점이다.
jdbc:apache:commons:dbcp:/[풀이름]
[풀이름]은 여러 개의 커넥션 풀 중에서 사용할 커넥션 풀의 이름을 나타내는 것으로서 커넥션 풀 설정 파일에서 확장자를 제외한 나머지 이름을 [풀이름]으로 사용한다. 예를 들어, 앞서 작성했었던 pool1.jocl 파일이 설정한 커넥션 풀을 사용하고 싶다면 다음과 같은 JDBC URL을 사용한다.
jdbc:apache:commons:dbcp:/pool1
실제로 커넥션 풀을 사용하는 완전한 예제는 다음 코드와 같다. (아래 코드를 여러분의 환경에 알맞게 변형시켜서 실행하기 바란다.)
파일명: pool\usePool1.jsp <%@ page contentType = "text/html; charset=euc-kr" %> <%@ page import = "java.sql.DriverManager" %> <%@ page import = "java.sql.Connection" %> <%@ page import = "java.sql.Statement" %> <%@ page import = "java.sql.ResultSet" %> <%@ page import = "java.sql.SQLException" %> <html> <head><title>회원 목록</title></head> <body> MEMBMER 테이블의 내용 <table width="100%" border="1"> <tr> <td>이름</td><td>아이디</td><td>이메일</td> </tr> <% Connection conn = null; Statement stmt = null; ResultSet rs = null; try { String jdbcDriver = "jdbc:apache:commons:dbcp:/pool1"; String query = "select * from MEMBER order by MEMBERID"; conn = DriverManager.getConnection(jdbcDriver); stmt = conn.createStatement(); rs = stmt.executeQuery(query); while(rs.next()) { %> <tr> <td><%= rs.getString("NAME") %></td> <td><%= rs.getString("MEMBERID") %></td> <td><%= rs.getString("EMAIL") %></td> </tr> <% } } finally { if (rs != null) try { rs.close(); } catch(SQLException ex) {} if (stmt != null) try { stmt.close(); } catch(SQLException ex) {} if (conn != null) try { conn.close(); } catch(SQLException ex) {} } %> </table> </body> </html>
위 코드에서 커넥션 풀에서 구한 Connection의 close() 메소드를 호출하면, 커넥션이 닫히는 것이 아니라 커넥션 풀로 반환된다. 이렇게 커넥션 풀에 커넥션을 반환하는 메소드를 close()로 지정한 이유는 기존의 코드를 최소한으로 변경하는 범위 내에서 커넥션 풀을 사용할 수 있도록 하기 위함이다. 물론, JDBC 프로그래밍의 코딩 형태를 동일하게 유지하기 위한 것도 close() 메소드를 사용하는 이유이다.
커넥션 풀 속성 지정하기
앞에서 살펴본 커넥션 풀 설정 파일인 pool1.jocl은 커넥션 풀과 관련된 속성을 지정하지 않고 있다. DBCP의 커넥션 풀은 최대 커넥션 개수, 최소 유휴 커넥션 개수, 최대 유휴 커넥션 개수, 유휴 커넥션 검사 여부 등의 속성을 지정할 수 있다. pool1.jocl을 보면 다음과 같은 코드가 있는데,
<object class="org.apache.commons.pool.impl.GenericObjectPool"> <object class="org.apache.commons.pool.PoolableObjectFactory" null="true" /> </object>
이 코드에 커넥션 풀과 관련된 속성 정보를 추가하면 된다. 예를 들면, 아래 코드와 같이 커넥션 풀 속성 정보를 추가하면 된다.
파일명: pool\WEB-INF\classes\pool2.jocl <object class="org.apache.commons.dbcp.PoolableConnectionFactory" xmlns="http://apache.org/xml/xmlns/jakarta/commons/jocl"> <object class="org.apache.commons.dbcp.DriverManagerConnectionFactory"> <string value="jdbc:mysql://localhost:3306/chap11?..." /> <string value="jspexam" /> <string value="jspex" /> </object> <object class="org.apache.commons.pool.impl.GenericObjectPool"> <object class="org.apache.commons.pool.PoolableObjectFactory" null="true" /> <int value="10" /> <!-- maxActive --> <byte value="1" /> <!-- whenExhaustedAction --> <long value="10000" /> <!-- maxWait --> <int value="10" /> <!-- maxIdle --> <int value="3" /> <!-- minIdle --> <boolean value="true" /> <!-- testOnBorrow --> <boolean value="true" /> <!-- testOnReturn --> <long value="600000" /> <!-- timeBetweenEvctionRunsMillis --> <int value="5" /> <!-- numTestsPerEvictionRun --> <long value="3600000" /> <!-- minEvictableIdleTimeMillis --> <boolean value="true" /> <!-- testWhileIdle --> </object> <object class="org.apache.commons.pool.impl.GenericKeyedObjectPoolFactory" null="true" /> <string null="true" /> <boolean value="false" /> <boolean value="true" /> </object>
굵게 표시한 부분이 커넥션 풀의 속성과 관련된 부분인데, 각 속성의 값이 무엇을 의미하는 지 우측에 주석으로 표시하였다. 각 속성이 의미하는 것은 다음표와 같다.
|
몇몇 속성은 성능에 중요한 영향을 미치기 때문에 웹 어플리케이션의 사용량에 따라서 알맞게 지정해주어야 하는데, 다음과 같이 고려해서 각 속성의 값을 지정하는 것이 좋다.
JNDI를 이용한 db 프로그래밍(java) 완변 샘플 (1) | 2009.11.12 |
---|---|
java properties ResourceBundle 사용하기 (0) | 2009.11.12 |
jndi (0) | 2009.11.04 |
Tomcat 5 JNDI DataSource를 통한 DB 커넥션 풀 사용 (0) | 2009.11.04 |
Io exception: NL Exception was generated (ibatis 설정) (0) | 2009.10.29 |