📌DB Connection Pool
JDBC를 통해 연동하였을 때, 웹 클라이언트에서 요청할 때마다 DB 서버에 연결하기 위해 Connection 객체를 얻어야 한다. SQL 작업을 할 때마다 DB Connection 객체를 생성한다면, 실행 속도가 느려지고 많은 Gabage가 생성될 것이다. 실행 속도가 느려지는 이유는 Connection을 맺을 때마다 DB 서버는 사용자 인증과 권한 검사를 수행하고 요청 처리를 위한 준비 작업을 해야 하기 때문이다.
이런 문제를 해결하기 위해 DB Connection Pool이 등장하였다. DB ConnectionPool을 이용하면, 각 요청에 대해 별도의 Connection 객체를 사용하기 때문에 다른 작업에 영향을 주지 않는다. 또한 사용한 DB Connection 객체는 버리지 않고 Pool에 보관해 두었다가 재사용하기 때문에, Gabage가 생성되지 않고 속도도 빨라진다. 사용자가 웹 사이트에 요청할때 마다 Connection 객체를 생성하여 연결한다면 매우 비효율적일 것이고, 메모리 Connection 객체가 너무 많이 생성되게 된다. 반면 Connection Pool을 사용하게 되면 Pool 속에 미리 Connection이 생성되어있기 때문에 Connection을 생성하는데 드는 연결 비용이 소비되지 않는다.
즉, Connection Pool을 사용한다면 프로그램 효율과 성능이 전체적으로 증가하게 된다.
📌DB ConnectionPool 직접 구현
설명하기에 앞서 DB Connection Pool을 직접 구현하는 것보다 맨 아래에 톰캣(Tomcat)에서 제공되는 Connection Pool을 이용하는 방법으로 하는 것이 좋다.
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.ArrayList;
public class DBConnectionPool {
String url;
String username;
String password;
ArrayList<Connection> connList = new ArrayList<Connection>();
public DBConnectionPool(String driver, String url, String username, String password) throws Exception {
this.url = url;
this.username = username;
this.password = password;
Class.forName(driver);
}
//DB Connection 달라고 요청
public Connection getConnection() throws Exception {
if (connList.size() > 0) {
Connection conn = connList.get(0);
if (conn.isValid(10)) { //DB Connection 객체도 일정 시간이 지나면 서버와의 연결이 끊긴다.
return conn; //때문에 유효성 체크를 한 다음에 반환한다.
}
}
return DriverManager.getConnection(url, username, password);
}
//Connectino 객체를 쓴 후 ConnectionPool에 반환
public void returnConnection(Connection conn) throws Exception {
connList.add(conn);
}
//DB와 연결을 모두 끊는다.
public void closeAll() {
for(Connection conn : connList) {
try{
conn.close();
}catch (Exception e) {}
}
}
}
📌DataSource와 JNDI
JDK 1.4버전부터 포함된 DataSource는 JDBC 확장 API를 정의한 javax.sql 패키지에 들어있다.
javax.sql 패키지는 java.sql패키지의 기능을 보조하기 위해 만든 확장 패키지이다. 서버쪽 데이터 소스에 대한 접근을 쉽게 하고, 다양한 방법으로 데이터를 다룰 수 있는 API를 제공한다. JavaEE에도 기본 패키지로 정의되어 있다.
javax.sql 패키지의 제공 기능
- DriverManager를 대체할 수 있는 DataSource 인터페이스 제공
- Connection 및 Statement 객체의 풀링(Pooling)
- 분산 트랜잭션 처리
- Rowsets의 지원
💡DataSource
DataSource가 DriverManage를 대체할 수 있다 하였는데 DataSource를 썼을 때에 이점에 대해 간략하게 설명하도록 하겠다.
첫째, DataSource는 서버에서 관리하기 때문에 DB나 JDBC 드라이버가 변경되더라도 애플리케이션을 바꿀 필요가 없다. 반면 DriverManage를 사용하는 경우, 웹 애플리케이션에서 관리하기 때문에 DB의 주소가 바뀌거나 JDBC 드라이버가 변경될 경우 웹 애플리케이션도 변경해야 한다.
둘째, DataSource를 사용하면 Connection과 Statement 객체를 풀링(Pooling)할 수 있으며, 분산 트랜잭션을 다룰 수 있다. DataSource는 자체적으로 커넥션풀 기능을 구현하기 때문에 웹 애프리케이션 쪽에서 따로 작업할 것이 없다. 반면 DrivetManager를 사용할 경우, 애플리케이션 개발자가 커넥션풀을 별도로 준비하여야 한다. 위에 DB Connection Pool을 직접 구현한 것도 하나의 예이다.
이렇게 톰캣 서버에 DataSource를 등록해 놓고, JNDI API를 통해 서버 자원에 접근하여 개발 편이성 및 성능을 향상 시킬 수 있다.
💡JNDI
JNDI는 Java Naming and Directory Interface API의 앞 글자로 명명 서비스 및 디렉터리 서비스에 접근하는데 필요한 API이며 애플리케이션은 이 API를 사용하여 서버의 자원을 찾을 수가 있다. 이때 자원이란, DB 서버 같은 다른 시스템과의 연결을 제공하는 객체를 말한다.
📌톰캣(Tomcat)에서 제공되는 Connection Pool를 위한 DBCP API를 사용
※톰캣에는 톰캣 설치 경로/lib 디렉토리에 CP(Connection Pool) 기능을 제공하기 위해 DBCP API를 제공한다.
WebContent \ META-INF 밑에 context.xml 파일을 생성하여 리소스를 정의한다.
4: DB작업을 하는 클래스에서 정의되는 Resource 객체를 얻어갈 때 사용하는 이름이다. 서버 상에 공유할 Resource의 타입을 지정한다.
6: DataSource 객체를 얻어가면 DataSource 객체에 getConnection()이라는 메소드를 사용해서 Connection 객체를 얻어갈 수 있다. 이에 대한 예는 아래에 추가적인 설명을 하도록 하겠다.
7~9: MySQL DB 연결을 할 수 있는 정보를 입력하는 부분이다.
10: DataSource 객체를 생성해주는 Factory 클래스를 지정하는 부분이다. Tomcat 8.5에 탑재되어 있는 라이브러리 경로를 지정했다.
11: MySQL url을 지정한 부분이다.
12: 동시에 반환할 수 잇는 Connection 객체를 설정한 부분이다.
MySQL로 Connection Pool 기능을 사용하기 위해서 하는 설정
C:\Program Files (x86)\MySQL\Connector.J XX 디렉토리에 존재하는 mysql-connector-java-XXX.jar 파일을 tomcat의 라이브러리(lib)에 붙여 넣는다.
사용법
기존
Connection con = null;
String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/testDB";
try {
Class.forName(driver);
con = DriverManager.getConnection(url,아이디,비밀번호);
con.setAutoCommit(false);
System.out.println("연결 성공");
} catch (Exception e) {
System.out.println("연결 실패");
e.printStackTrace();
}
CP(Connection Pool) 적용
Connection con = null;
try {
Context init = new InitialContext(); //톰캣 자체의 컨텍스트 얻어오는 부분
Context env = (Context) init.lookup("java:comp/env"); //Resource 정의에 관한 컨텍스트 얻어오는 부분
DataSource ds = (DataSource) env.lookup("jdbc/MySQLDB"); //컨텍스트에 정의한 DataSource 객체를 얻어오는 부분
//DataSource ds = (DataSource)init.lookup("java:comp/env/jdbc/MySQLDB");
con = ds.getConnection(); //CP에서 Connection 객체를 얻어오는 부분
con.setAutoCommit(false);
System.out.println("연결 성공");
} catch (Exception e) {
System.out.println("연결 실패");
e.printStackTrace();
}
'JSP & Servlet > 개념' 카테고리의 다른 글
[Eclipse] 웹 프로젝트 생성 (dynamic web project) (feat.JSP & Servlet) (0) | 2022.07.27 |
---|---|
필터(Filter) 사용하기 (0) | 2022.07.13 |
데이터 보관소(네 가지 객체 보관소) (0) | 2022.07.11 |
html href 속성을 이용하여 넘길 때 한글 처리 (0) | 2022.07.02 |
JSTL fmt - JSTL의 국제화/형식화 액션 (0) | 2022.06.25 |