커넥션 풀(DBCP) 개요

DB와 연결하기 위해 Connection 객체를 생성하는 과정은 다음과 같다.

//1. Driver 로딩 (통역사 역할을 하는 Driver 클래스 로딩)
Class.forName("oracle.jdbc.driver.OracleDriver");
//2. DB 연결=> DriverManager.getConnection()을 이용
String url = "jdbc:oracle:thin:@localhost:1521:XE";
String user = "scott", pwd = "tiger";
Connection con = DriverManager.getConnection(url, user, pwd);

 

자바에서 DB에 직접 연결해서 처리하는 경우 드라이버(Driver)를 로드하고 커넥션(Connection) 객체를 받아와야 한다. 그러면 매번 사용자가 요청을 할 때마다 드라이버를 로드하고 커넥션 객체를 생성하여 연결하고 종료하기 때문에 매우 비효율적이다.

이러한 문제를 해결하기 위해 애플리케이션 로딩 시점에 Connection 객체를 미리 생성하고, 애플리케이션에서 DB에 연결이 필요할 경우 미리 준비된 Connection 객체를 사용하여 애플리케이션의 성능을 향상하는 커넥션 풀(Connection Pool)이 등장하게 된다.

 


커넥션 풀(DBCP)이란?

 

출처: https://shuu.tistory.com/130

  • 웹 컨테이너(WAS)가 실행되면서 DB와 미리 connection(연결)을 해놓은 객체들을 pool에 저장해두었다가 클라이언트 요청이 오면 connection을 빌려주고, 처리가 끝나면 다시 connection을 반납 받아 pool에 저장하는 방식
  • 애플리케이션을 시작하는 시점에 커넥션 풀은 필요한 만큼 커넥션을 미리 생성하여 보관한다.
  • 서비스의 특징과 스펙에 따라 생성되는 Connection 객체의 개수는 다르지만 일반적으로 기본값으로 10개를 생성한다.

커넥션 풀(DBCP) 특징

  1. 웹 컨테이너(WAS)가 실행되면서 connection 객체를 미리 pool에 생성해 둔다.
  2. HTTP 요청에 따라 pool에서 connection 객체를 가져다 쓰고 반환한다.
  3. 이와 같은 방식으로 물리적인 데이터베이스 connection(연결) 부하를 줄이고 연결 관리한다.
  4. pool에 미리 connection이 생성되어 있기 때문에 connection을 생성하는 데 드는 요청마다 연결 시간이 소비되지 않는다.
  5. 커넥션을 계속해서 재사용하기 때문에 생성되는 커넥션 수를 제한적으로 설정한다.

 


커넥션 풀(DBCP) 사용을 위한 세팅

1. 톰캣의 server.xml 수정

C:\Java\apache-tomcat-9.0.64\conf\server.xml의 <GlobalNamingResources>태그 사이에 세팅

1
2
3
4
5
<Resource name="jdbc/myoracle" auth="Container"
type="javax.sql.DataSource" driverClassName="oracle.jdbc.driver.OracleDriver"
url="jdbc:oracle:thin:@127.0.0.1:1521:xe"
username="scott" password="tiger" maxActive="20" maxIdle="10"
maxWait="-1"/>
cs

 

2. 톰캣의 context.xml 수정

<Context reloadable="true"> 태그 사이에 아래부분 세팅

1
2
<ResourceLink global="jdbc/myoracle" name="jdbc/myoracle"
type="org.apache.tomcat.dbcp.dbcp2.BasicDataSource"/>
cs

 

3. MyWeb/Web-INF/web.xml 수정

<web-app> 태그사이에 아래 부분 세팅

1
2
3
4
5
6
<resource-ref> 
<description>Oracle Datasource example</description> 
<res-ref-name>jdbc/myoracle</res-ref-name> 
<res-type>javax.sql.DataSource</res-type> 
<res-auth>Container</res-auth> 
</resource-ref>
cs

 

4. JavaSource 상에서 다음과 같이 참조

1
2
3
4
5
6
7
8
// InitialContext() 객체를 생성 => 이름으로 객체를 찾을 수 있도록 도와준다.
Context initContext = new InitialContext();
// InitialContext() 객체의 lookup 메서드를 사용하여 DataSource 객체를 구한다.
Context envContext = (Context)initContext.lookup("java:/comp/env");
//톰캣을 먼저 찾음 => 반환타입 Object
//톰캣을 찾을 때는 java:/comp/env로 찾는다.
DataSource ds = (DataSource)envContext.lookup("jdbc/myoracle");
//server.xml에 등록했던 이름 'myoracle'을 찾는다.
Connection con = ds.getConnection(); //DataSource 통해서 커넥션
 
if(con!=null) con.close();
//연결을 끊는 것이 아니라, 커넥션 풀에 반납을 하는 개념
cs

 


Model1 방식으로 만들고 있는 중인 웹페이지에 적용

오라클- DBCP 사용 세팅

[경로: src/main/webapp/example/ex09_dbcpOracle.jsp]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="java.sql.*, javax.sql.*, javax.naming.*" %>
<jsp:include page="/inc/top.jsp" />
 
<div class="container">
    <h1>DBCP Test - Oracle</h1>
    <%
    Context ctx = new InitialContext(); //이름으로 객체를 찾을 수 있게 도와주는 InitialContext()
    Context ctxWas = (Context)ctx.lookup("java:comp/env"); //톰캣을 먼저 찾음 => 반환타입 Object
    DataSource ds = (DataSource)ctxWas.lookup("jdbc/myoracle"); //dbcp를 찾는다
    out.println("ds: " + ds+"<br>");
    Connection con = ds.getConnection(); //DataSource 통해서 커넥션
    out.println("con: " + con+"<br>");
    
    if(con!=null) con.close(); //연결을 끊는 것이 아니라, 커넥션 풀에 반납을 하는 개념
    %>    
</div>
 
<jsp:include page="/inc/foot.jsp" />
cs

 

MySQL- DBCP 사용 세팅

[경로: src/main/webapp/example/ex09_dbcpMySQL.jsp]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="java.sql.*, javax.sql.*, javax.naming.*" %>
<jsp:include page="/inc/top.jsp" />
 
<div class="container">
    <h1>DBCP Test - MySQL</h1>
    <%
    Context ctx = new InitialContext(); //이름으로 객체를 찾을 수 있게 도와주는 InitialContext()
    Context ctxWas = (Context)ctx.lookup("java:comp/env"); //톰캣을 먼저 찾음 => 반환타입 Object
    DataSource ds = (DataSource)ctxWas.lookup("jdbc/mysql"); //dbcp 찾는다
    out.println("ds: " + ds+"<br>");
    Connection con = ds.getConnection(); //DataSource 통해서 커넥션
    out.println("con: " + con+"<br>");
    
    if(con!=null) con.close(); //연결을 끊는 것이 아니라, 커넥션 풀에 반납을 하는 개념
    %>    
</div>
 
<jsp:include page="/inc/foot.jsp" />
cs

 

BbsDAO 수정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class BbsDAO {
    //추가
    private DataSource ds;
 
//추가
public BbsDAO() {
        System.out.println("BbsDAO()생성...");
        try {
            Context ctx = new InitialContext();
            ds = (DataSource)ctx.lookup("java:comp/env/jdbc/myoracle");//톰캣과 dbcp를 동시에 찾는다.
        }catch (NamingException e) {
            e.printStackTrace();
        }
    }
 
//게시글 쓰기 (시퀀스-Bbs_seq : 글번호)
    public int insertBbs(BbsVO vo) throws SQLException{
        try {
        //con = DBUtil.getCon(); (기존 방식: 드라이버 로드, db연결)
        //수정
        con = ds.getConnection(); //DataSource 통해서 커넥션
        //oracle sql문 작성
        String sql = "INSERT INTO bbs(no, title, writer, content, wdate)";
        sql += " VALUES(bbs_seq.NEXTVAL, ?, ?, ?, SYSDATE)";
        
        //mysql sql문 작성 ==> 글번호(no) auto_increment
        String sql2 = "INSERT INTO bbs(title, writer, content, wdate)";
        sql2 += " VALUES( ?, ?, ?, curdate())";
        
        ps = con.prepareStatement(sql); //mysql: sql2, oracle: sql
        ps.setString(1, vo.getTitle());
        ps.setString(2, vo.getWriter());
        ps.setString(3, vo.getContent());
        //execute
        int re = ps.executeUpdate();
        return re;
        } finally {
            //자원 반납
            close();
        }
    }
...
cs
  • 기본 생성자에 이름으로 객체를 찾을 수 있도록 해주는 InitialContext() 객체를 생성한다.
  • 기존 코드인 con = DBUtil.getCon()을 con = ds.getConnection로 수정한다. (DataSource를 통해서 커넥션)

연결 확인

ex09_dbcpOracle.jsp와 ex09_dbcpMySQL.jsp 파일을 실행시켜서 연결이 잘 되었는지 확인해보자.

1
2
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="java.sql.*, javax.sql.*, javax.naming.*" %>
cs

java.sql.*, javax.sql.*, javax.naming.*을 임포트해준다.

 

Oracle 연결 성공
MySQL 연결 성공

+ Recent posts