JSP + Servlet | DBCP 데이터베이스 커넥션 풀

파과·2022년 7월 20일
0

JSP + Servlet

목록 보기
23/33

자바에서 오라클을 사용하기 위해서는 접속 요청을 하여 연결된 상태가 되어야 하는데, 이를 커넥션이라고 한다. 웹 페이지에 접속자 수가 많아지면 커넥션을 그만큼 걸어줘야 하기 때문에 서버에 부하가 발생한다. 이를 해결하기 위해 커넥션 풀이 존재한다.

DBCP (DataBase Connection Pool)

DBCP는 접속 인원이 많은 웹 페이지에서 데이터베이스의 효율성과 속도를 높이기 위해 사용한다. DBCP매니저가 어느 정도의 연결을 확보해 놓고 있다가 클라이언트의 요청이 들어오면 연결해주고, 클라이언트 작업이 다 끝나면 연결을 다시 DBCP매니저에게 반환하게 한다.

만약 DB 풀에 열어놓은 연결 개수가 5개라면, 5명의 클라이언트는 항상 동시 접속하여 사용할 수 있고 다른 클라이언트가 연결을 시도하면 접속이 허용될 때까지 기다려야 한다.

🔗 DataSource (생활코딩 참고)
커넥션풀에는 여러개의 Connection 객체가 생성되어 운용되는데, 이를 직접 웹 애플리케이션에서 다루기 힘들기 때문에 DataSource라는 개념을 도입하여 사용합니다.

DataSource에 대해 정의하자면 아래와 같다.
커넥션 풀의 Connection을 관리하기 위한 객체이다.
JNDI Server를 통해서 이용된다.
DataSource 객체를 통해서 필요한 Connection을 획득, 반납 등의 작업을 한다.

DataSource를 이용하려면 다음의 절차를 따릅니다.

  • JNDI Server에서 lookup( ) 메소드를 통해 DataSource 객체를 획득한다.
  • DataSource 객체의 getConnection( ) 메소드를 통해서 Connection Pool에서 Free 상태의 Connection 객체를 획득한다.
  • Connection 객체를 통한 DBMS 작업을 수행한다.
  • 모든 작업이 끝나면 DataSource 객체를 통해서 Connection Pool에 Connection을 반납한다.

[🔗 JNDI란?]

여기서는 아파치 서버에서 제공해주는 소스를 사용한다.


DBCP 설치하기

  1. Dynamic Web Project를 하나 생성한다.
    오라클 드라이버인 ojdbc6.jar (ojdbcX.jar)파일을 해당 프로젝트의 WebContent\WEB-INF\lib 폴더에 복사한다.

  2. DBCP 커넥션 풀은 컨텍스트 패스의 서브 태그로 추가한다. (이클립스에서는 프로젝트를 생성하면 자동으로 추가된다)

  3. https://tomcat.apache.org/tomcat-8.5-doc/jndi-datasource-examples-howto.html
    위 주소에서 JNDI Resources 클릭 - JDBC Data Source 클릭 - 3. Code Your Application's Use Of This Resource에서 아래 코드를 찾아 복사해와서 사용한다.

    Context initCtx = new InitialContext();
    Context envCtx = (Context) initCtx.lookup("java:comp/env");
    DataSource ds = (DataSource)
      envCtx.lookup("jdbc/EmployeeDB");

    Connection conn = ds.getConnection();
    ... use this connection to access the database ...
    conn.close();

코드 설명

  • Context initCtx = new InitialContext();
    커넥션 풀에 접근하려면 JNDI 서비스를 사용해야 합니다. JNDI는 서버에서 관리하고 있는 리소스에 대한 정보를 알고 있고 특정 리소스를 찾아서 사용할 수있도록 객체를 반환해주는 역할을 합니다. JNDI 서버역할을 하는 객체를 생성합니다. 리소스가 로컬에 있을 때는 단순히 InitialContext 객체만 생성하면 됩니다.
  • Context envCtx = (Context) initCtx.lookup("java:comp/env");
    DataSource ds = (DataSource) envCtx.lookup("jdbc/EmployeeDB");
    우리가 찾으려는 리소스의 이름은 "jdbc/myoracle" 이고 WAS인 톰캣에서 리소스를 관리하는 가상의 디렉터리는 "java:comp/env"입니다. 그래서 lookup( ) 메소드의 최종인자 값은 "java:comp/env/jdbc/myoracle"이 됩니다.
    lookup( ) 메소드가 반환하는 객체의 타입은 Object 이기 때문에 원래 리소스 타입으로 변환해줍니다. 앞에서 server.xml 파일에 커넥션 풀을 설정할 때 리소스의 타입을 DataSource로 등록했습니다. 즉, 원래 DataSource로 타입을 변환합니다.
  • Connection conn = ds.getConnection();
    ds 변수는 DataSource 입니다. DataSource 객체의 getConnection( )는 커넥션 풀에 준비된 Connection 객체를 빌려오는 메소드 입니다. 빌려오는 Connection을 conn에 담습니다.
  • conn.close();
    이후에는 기존의 JDBC프로그래밍과 같습니다. 하지만 리소스를 반납할 때 약간의 차이가 있습니다. Connection 객체을 반납할 때 리소스를 제거하는 것이 아니라 빌려온 Connection 객체를 다음 사용자가 사용할 수있도록 커넥션 풀에 그대로 반납합니다. 리소스를 반납하지 않고 코드를 종료해버리면 Connection 객체가 정상적으로 반납되지 않아 커넥션 풀에 구멍이 납니다.
  1. 아래 코드 담은 context.xml 파일을 만들어 WebContent\META-INF 폴더에 저장
<Context>
   <Resource name = "jdbc/OracleDB"
             auth = "Container"
             type = "javax.sql.DataSource"
             username = "scott"
             password = "tiger"
             driverClassName = "oracle.jdbc.driver.OracleDriver"
             factory = "org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory"
             url = "jdbc:oracle:thin:@localhost:1521:orcl"
             maxTotal = "500"
             maxIdle = "100"
   />
</Context>
  • username과 password에 사용하는 계정의 이름과 비밀번호를 작성한다.
  • type은 DataSource를 통해 객체에 이름을 등록해 사용할 수 있다.
  • maxIdle은 풀에서 동시에 유휴 상태로 둘 수 있는 최대 커넥션 개수
  • maxTotal는 풀에서 동시에 할당(사용)할 수 있는 최대 커넥션 개수 *maxActive가 maxTotal로 이름이 바뀌었다.




아래 코드를 dbcpConnTest.jsp로 만들어 테스트해보자.

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

<%!
	Connection conn = null;
	PreparedStatement pstmt = null;

	String sql = "insert into product values(?, ?, ?, ?, ?, ?)";
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
DB 커넥션 풀 연결 테스트용 파일<br>
<%
		
		try {
			//책과 다른 부분
			//괄호부분에 context.xml에 설정한 name을 추가함으로써 디비 정보 노출 없이 초기화할수 있다고 하였읍니다
			Context init = new InitialContext();
			DataSource ds = (DataSource)init.lookup("java:comp/env/jdbc/OracleDB");
			conn = ds.getConnection();
			out.println("DBCP 연결 성공");

		} catch (Exception e) {
			e.printStackTrace();
		} finally {

			try {
				if (conn != null)
					conn.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}//finally의 끝
	%>
</body>
</html>

코드 설명

  • new InitialContext 객체를 생성한다.
  • Context 객체의 lookup메소드로 DBCP에서 지정한 이름을 찾는다. 찾으면 DataSource형으로 되돌리도록 한다.
  • 해당 DataSource 객체로 getConnection 메소드를 호출해 커넥션 객체를 얻어낸다.



DB 연결 안 될 때 확인하기

  • 확인하기
  1. commit 했는지
  2. meta-inf에 context.xml 만들었는지
  3. 서버 껐다 켰는지, add/remove 했는지
  4. 테이블이름 제대로 바꿨는지
  5. web-inf에 ojdbcX.jar 복사했는지
  • 해보기
  1. xml파일 삭제했다가 다시 생성하기
  2. 톰캣 서버 껐다가 다시 켜기
  3. 서버 Add and Remove에서 이전 프로젝트 다 Remove하고 현재 사용하는 프로젝트만 넣기



jstl 사용시

아래 링크에서 jakarta-taglibs-standard-1.1.2.zip 파일을 다운로드해 프로젝트 폴더의 WebContent\WEB-INF\libjstl.jarstandard.jar파일을 복사한다.
https://tomcat.apache.org/download-taglibs.cgi
다음 코드를 상단에 붙여넣기한다.

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

0개의 댓글