티스토리 뷰

JDBC 드라이버 한번만 로딩하기

JDBC드라이버는 한번 로딩하면 계속해서 재사용 가능하기 때문에 사용할때마다 로딩할 필요가 없다.

웹 어플리케이션 실행시 한번만 실행하는것이 좋다.

 

가장 좋은 시점은 웹 컨테이너가 시작될 때 로딩하는것이 좋다.

HttpServlet을 상속받은 클래스에서 init 메서드를 사용하면 서블릿이 초기화할 때 한번만 실행된다.

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

public class MySQLDriverLoader extends HttpServlet{
	
	@Override
	public void init(ServletConfig config) throws ServletException {
		try {
			Class.forName("com.mysql.jdbc.Driver");
		} catch (Exception e) {
			throw new ServletException(e);
		}
	}
}

 

웹 어플리케이션이 실행될때 자동으로 실행되도록 서블릿 클래스를 등록해주어야 한다.

web.xml

	<servlet>
		<servlet-name>mysqlDriverLoader</servlet-name>
		<servlet-class>jdbc.MySQLDriverLoader</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

 

커넥션 풀(Connection pool)

JDBC드라이버를 한번만 로딩하긴 했지만 데이터베이스를 사용할 때 마다 커텍션을 생성했다가 삭제하는것을 반복한다. 이는 사용자가 많을때 성능저하로 이어지며 이를 해결하기 위해 커넥션 풀이라는 방법을 사용한다.

 

커넥션 풀이란 데이터베이스에 연결된 커넥션을 미리 생성해두고 풀에 저장해 두었다가 필요할때 꺼내서 사용하고 다시 풀에 반환하는 과정을 반복하는 기법을 말한다.

 

커넥션 풀에는 여러가지 방법이 존재하는데 여기서는 DBCP API를 이용해서 커넥션 풀을 만든다.

 

준비물

DBCP jar 파일이 필요하다.

Commons DBCP API

mvnrepository.com/artifact/org.apache.commons/commons-dbcp2

Commons Pool API

mvnrepository.com/artifact/org.apache.commons/commons-pool2

Common Loggin API

mvnrepository.com/artifact/commons-logging/commons-logging

나는 mvnrepository 에서 검색해서 받았다.

 

코드

import java.sql.DriverManager;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

import org.apache.commons.dbcp2.ConnectionFactory;
import org.apache.commons.dbcp2.DriverManagerConnectionFactory;
import org.apache.commons.dbcp2.PoolableConnection;
import org.apache.commons.dbcp2.PoolableConnectionFactory;
import org.apache.commons.dbcp2.PoolingDriver;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

public class DBCPInit  extends HttpServlet{
	
	@Override
	public void init() throws ServletException {
		loadJDBCDriver();
		initConnectionPool();
	}
	
	private void loadJDBCDriver() {
		/* 커넥션 풀이 내부에서 사용할 JDBC 드라이버 로딩 */
		try {
			Class.forName("com.mysql.jdbc.Driver");
		} catch (Exception e) {
			throw new RuntimeException("fail to load JDBC Driver", e);
		}
	}
	
	private void initConnectionPool() {
		try {
			String jdbcUrl = "jdbc:mysql://localhost:3306/db";
			String dbUser = "id";
			String dbPass = "pw";
			
			/* 커넥션 풀이 새로운 커넥션을 생성할때 필요한 Connection Factory를 생성 */
			ConnectionFactory connFactory = new DriverManagerConnectionFactory(jdbcUrl, dbUser, dbPass);
			PoolableConnectionFactory poolableConnFactory = new PoolableConnectionFactory(connFactory, null);
			poolableConnFactory.setValidationQuery("select 1");
			
			GenericObjectPoolConfig<PoolableConnection> poolConfig = new GenericObjectPoolConfig<PoolableConnection>();
			poolConfig.setTimeBetweenEvictionRunsMillis(1000L * 60L * 5L);
			poolConfig.setTestWhileIdle(true);
			poolConfig.setMinIdle(4);
			poolConfig.setMaxTotal(50);
			
			GenericObjectPool<PoolableConnection> connectionPool = new GenericObjectPool<>(poolableConnFactory, poolConfig);
			
			
			poolableConnFactory.setPool(connectionPool);
			
			Class.forName("org.apache.commons.dbcp2.PoolingDriver");
			PoolingDriver driver = (PoolingDriver) DriverManager.getDriver("jdbc:apache:commons:dbcp:");
			driver.registerPool("pool", connectionPool);
		} catch(Exception e) {
			throw new RuntimeException(e);
		}
	}
}

위 코드는를 요약하면 다음과 같다.

  1. 실제 커넥션을 사용할 ConnectionFactory를 생성
  2. 커넥션 풀로 사용할 PoolableConnection을 생성하는 PoolableConnectionFactory를 생성
  3. 커넥션 풀의 정보를 설정
  4. 커넥션 풀을 사용할 JDBC 드라이버를 등록

마찬가지로 web.xml에 설정한다.

...
	 <servlet>
	 	<servlet-name>DBCPInit</servlet-name>
	 	<servlet-class>jdbc.DBCPInit</servlet-class>
	 	<load-on-startup>1</load-on-startup>
	 </servlet>
...

 

커넥션 풀에서 커넥션 사용하기

DBCP가 제공하는 PoolingDriver를 통해 커넥션 풀에서 커넥션을 가져온다. 이때 다음과 같은 형식의 JDBC URL을 사용한다.

jdbc:apache:commons:dbcp:풀이름

 

	Connection conn = null;
	Statement stmt = null;
	ResultSet rs = null;
	
	try {
		String jdbcDriver = "jdbc:apache:commons:dbcp:pool";
		
		String query = "SELECT * FROM actor";
		conn = DriverManager.getConnection(jdbcDriver);
		stmt = conn.createStatement();
		rs = stmt.executeQuery(query);
		
		while(rs.next()) {
			rs.getString("first_name");
		}
	} catch(Exception e) {
		if(rs != null) rs.close();
		if(stmt != null) stmt.close();
		if(conn != null) conn.close();
	}

 

jdbcDriver의 마지막 pool 부분은 풀을 생성할 때

Class.forName("org.apache.commons.dbcp2.PoolingDriver");
PoolingDriver driver = (PoolingDriver) DriverManager.getDriver("jdbc:apache:commons:dbcp:");
driver.registerPool("pool", connectionPool);

이 부분에서 지정할 수 있다.

 

기존의 Connection과 사용법은 크게 다르지 않지만 conn.close()를 했을때 Connection을 종료하는것이 아닌 Pool에 반환하게된다.

'JSP &Servlet' 카테고리의 다른 글

Servlet Filter  (0) 2021.05.15
Servlet MVC 패턴 구현과정  (0) 2021.05.05
JSP JSTL(JSP Standard Tag Library)  (0) 2021.04.28
표현언어(Expression Language EL)  (0) 2021.04.28
JSP 에러처리  (0) 2021.04.27
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/01   »
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
글 보관함