개발..너... 2022. 6. 14. 11:58
DBCP(DataBase Connection Pool)란?

 

데이터베이스와 연결된 커넥션을 미리 만들어서 저장해두고있다가 필요할 때 저장된 공간(Pool)에서 가져다 쓰고 반환하는 기법을 말한다. 커넥션 풀을 이용하면 커넥션을 미리 만들어두고 사용하기 때문에 매번 사용자가 요청할 경우 드라이버를 로드하고, 커넥션 객체를 생성해 연결하고 종료하는 비효율적인 작업을 하지 않아도 된다. 즉, 데이터베이스의 부하를 줄일 수 있고 자원을 효율적으로 관리할 수 있다.

 

쉽게말하자면 기존의 DB Conneciton방식은 한사람이 끝나야지 다음사람이 사용할 수 있고 그 사람이 끝나야 그 다음사람이 사용할 수 있는 비효율적인 방법이였으나 이는 매우 비효율적인 방법이기에 DBCP방식을 사용한다.

 

단, Pool공간 역시 무한하지 않는데 만약 Pool안에 10개의 공간이 있다면 10명의 사용자가 동시에 들어갈 수 있고 11번째의 사용자는 10명의 사용자 중 한명이 빠질 때 까지 기다려야한다. 

 

 

JNDI(Java Naming and Directory Interface)란?

 

디렉토리 서비스에서 제공하는 데이터 및 객체를 발견(discover)하고 참고(lookup)하기 위한 자바 API이다. 

DB Pool을 미리 Naming 시켜두는 방법으로서 DB 연결방법 중 하나로서, DB Connection에 대한 정보를 WAS에 넣고 거기에 JNDI로 네이밍을 지어주고 그 네이밍을 호출해서 사용하는 식으로 하여 사용을 하게 된다. 즉, 우리가 저장해놓은 WAS의 데이터베이스 정보에 JNDI를 설정해 놓으면 웹 애플리케이션에 JNDI만 호출하면 간단해진다.

 

 

 

WAS에 JNDI를 설정하는 이유

 

개발을 한 사람과 실제 서버를 운영하는 담당자는 다른 경우가 많기 때문에 소스에 설정되어 있는 것 보단 WAS에서 설정되어 있는 것을 선호한다. 개발자가 아닌 사람들도 해당 상태를 직관적으로 확인할 수 있기 때문이며 Conneciton부분을 java에서 분리시켜야하는 이유이다.

 

또한  WAS에 여러개의 웹 애플리케이션을 올려서 사용하기 때문에 WAS에서 한번에 설정해 주는 것이 자원낭비를 줄일 수 있다.

 

추가적으로 장애가 나거나 성능이 정상적이지 못하면 다른 한 서버가 대신 일을 해 줄 수 있다.

 

정리하자면 운영,관리,최적화 문제 대처에 다양한 이점이 있기 때문에 JNDI를 사용한다.

 

 

 

설정값

 

  • DriverClassName: 각각 DB에 맞는 JDBC driverClass
  • url,username,password: db연결정보
  • initialSize:  최초로 커넥션을 맺을 때 생성되는 커넥션 개수(default : 0)
  • minIdle: 최소한으로 유지할 커넥션 개수(default: 0)
  • maxIdle: 사용한 커넥션을 풀에 반납시 최대로 유지할 개수(default: 8)
  • maxActice: 동시에 사용할 수 있는 최대 커넥션으로 커낵션 개수와 관련된 가장 중요한 성능 요소. maxIdle과 대부분 일치시킨다.(default: 8)
  • maxWait: 커넥션 풀에 연결 가능 커넥션이 없을 경우 반납되는 커넥션을 대기하는 시간

 

연결하기

 

 

*DB-Connection

 

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
package com.koreait.dao;
 
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
 
public class DBConnection {
    
     public static Connection getConnection() {
         Connection conn = null;
         
         try {
             String driver = "oracle.jdbc.driver.OracleDriver";
             String url = "jdbc:oracle:thin:@localhost:1521:xe";
             String user = "wjsp";
             String password = "wjsp";
        
            Class.forName(driver);
            conn = DriverManager.getConnection(url, user, password);
        } catch (ClassNotFoundException e) {
            System.out.println("드라이버 로딩 실패");
            e.printStackTrace();
        } catch (SQLException e) {
            System.out.println("DB 접속 오류");
            e.printStackTrace();
        } catch(Exception e) {
            System.out.println("알 수 없는 오류");
            e.printStackTrace();
        }
          
          return conn;
     }
     
}
 
 
 
 
 
 
cs

 

 

*Content.xml

 

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
<?xml version="1.0" encoding="UTF-8"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at
 
      http://www.apache.org/licenses/LICENSE-2.0
 
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
--><!-- The contents of this file will be loaded for each web application --><Context>
 
    <!-- Default set of monitored resources. If one of these changes, the    -->
    <!-- web application will be reloaded.                                   -->
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
 
    <!-- Uncomment this to disable session persistence across Tomcat restarts -->
    <!--
    <Manager pathname="" />
    -->
       <Resource 
       name="jdbc/oracle"
       auth="Container"
       type="javax.sql.DataSource"
       driverClassName="oracle.jdbc.driver.OracleDriver"
       url="jdbc:oracle:thin:@localhost:1521:xe"
       username="wjsp"
       password="wjsp"
       maxActive="20"
       maxIdle="20"
       maxWait="-1"
    />
</Context>
cs

 

 

*dbcp_test.jsp

 

 

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
<%@page import="java.util.Date"%>
<%@page import="java.sql.ResultSet"%>
<%@page import="java.sql.PreparedStatement"%>
<%@page import="java.sql.Connection"%>
<%@page import="javax.sql.DataSource"%>
<%@page import="javax.naming.InitialContext"%>
<%@page import="javax.naming.Context"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <%
        //dbcp를 이용하는 방법
        Context context = new InitialContext();
        DataSource dataSource = (DataSource)context.lookup("java:comp/env/jdbc/oracle");
        Connection conn = dataSource.getConnection();
        
        String sql = "select sysdate from dual";
        
        PreparedStatement pstm = conn.prepareStatement(sql);
        ResultSet rs = pstm.executeQuery();
        Date date = null;
        
        if( rs.next() ){
            date = rs.getDate(1);
        }
        
    %>
    <%=date %>
<%--     <%=conn %> --%>
</body>
</html>
 
cs

 

 

*Member.Dao.java

 

 

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package com.koreait.dao;
 
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
 
import com.koreait.beans.MemberBean;
 
public class MemberDAO {
    
    Context context;
    DataSource dataSource;
    
    Connection conn;
    PreparedStatement pstm;
    ResultSet rs;
    
    public boolean join(MemberBean member) {
        String sql = "INSERT INTO TBL_MEMBER VALUES ( ?, ?, ?, ?, ? )";
        int result = 0;
        
        try {
    /*        conn = DBConnection.getConnection();*/
            
            context = new InitialContext();
            dataSource = (DataSource) context.lookup("java:comp/env/jdbc/oracle");
            conn = dataSource.getConnection();
                
            pstm = conn.prepareStatement(sql);
            pstm.setString(1, member.getUserid());
            pstm.setString(2, member.getUserpw());
            pstm.setString(3, member.getUsername());
            pstm.setString(4, member.getUsergender());
            pstm.setString(5, member.getUserphone());
            
            result =  pstm.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (NamingException e) {
            e.printStackTrace();
        }
        
        if( result != 0 ) {
            // 성공
            return true;
        } else {
            // 실패
            return false;
        }
    }
 
    
}
cs

point1)

 

DBCP로 연결하는 것은 개발자가 아닌 사람들과의 협업을 위하여 코드를 java파일이 아닌 WAS 서버로 분리시키는 것이 핵심이다. 그렇기에 원래 DBConnection.java파일 하나만을 사용한 것을 dbcp_test.jsp와 Context.xml 로 나누고 DBConneciton파일이 없어졌으니 로그인 메서드 등이 있는 Member.java파일을 수정해나가는 식으로 진행한다.

 

point2)

Content.xml를 보면 DBConneciton의 try안에 String으로 할당된 driver나 url등의 정보들이 <Resource>형태로 정리되어는 것을 확인할 수 있다. 

 

 

단, Content.xml은 maxActive, maxIdle, maxWait를 추가로 기재해줌으로서 커넥션에 대한 구체적 정보를 나타내준다.

 

context.xml은 Servers파일의 하위폴더에 저장해준다.

 

point3)

 

 

dbcp_test.jsp에서 키워드를 분석해보면 

Context context = new InitialContext( ) ; -> Context에 설정한 리소스를 찾는다.

java:comp/env/oracle: java:comp/env/본인이 지정한 이름으로 하나의 형식이니 암기한다.

Connection conn = dataSource.getConnection(): DataSource를 통해 Connection을 얻어온다.

 

위의 3줄이 DBCP를 사용하기 위한 가장 기본설정이며 이 3줄이 기본 세팅이라고 생각한다.

 

point4)

 

 

데이터베이스와 연결되어있는지 확인하는 방법이다. sql문 쿼리문을 작성하고 DB를 출력하는 코드를 작성하여 정상연결되었는지 체크한다.

 

point5)

 

빨간색: 기존 Member.Dao/ 파란색: 변경된 Member.Dao이다.

DBCP를 사용함으로서 빨간색 주석처리된 부분을 삭제하였고 파란부분을 추가로 입력함으로서 DBConnection.java가 삭제됨으로 인해 발생되는 오류를 잡아주었다.