Back-end/JSP

JSP) DB 커넥션 풀(Connection Pool)

luana_eun 2022. 3. 14. 20:17
728x90

1. 커넥션 풀

JDBC를 통해 DB와 연결할때

DriveManager클래스의 getConnection()메서드를 통해 연결 정보 객체(Conection)을 가져와서 사용한다. 

이 Connection을 매번 가져오는게 아니고, 미리 가져와서 저장하여

필요할때 가져가서 쓰고 작업이 끝아면 반환하며 사용할때 사용하는게 커넥션 풀이다. 

즉, 커넥션 풀은 커넥션 정보를 저장하는 것을 의미한다. 

 

DB환경설정과 연결정보 등을 xml이나 속성관리 파일에 정의해두고 그 정보를 사용한다. 

웹을 만들때 커넥션 풀 사용은 필수다. 안쓰면 서버 무조건 나간다..ㅎㅎ

 

 

 

2. 커넥션 풀 사용 이유

사용자가 웹 사이트를 요청할때마다 Connection객체를 새로 만들면 메모리 소모가 많아 매우 비효율적이다. 

커넥션 풀을 생성해서 그 안에 미리 만들어 놓으면 가져다 쓰는거니까 만드는 시간이 줄어든다. 

또한 커넥션 풀 객체의 개수를 지정할 수 있어서 한번에 많은 사용자가 몰리더라도 서버가 부하되는것을 방지할 수 있다. 

 

 

 

3. 커넥션 풀 동작 방식

파일에 커넥션 정보를 미리 정의. → 이때 총 커넥션 개수도 지정한다. 

DB요청 하나 당 커넥션 객체 1개씩 할당. 

웹 컨테이너를 실행하면 커넥션(connection) 객체를 미리 풀(pool)에 생성.

 

1) 웹 브라우저 요청

2) 커넥션 객체 개수제한이 있으므로 남은게 있는지 체크

3-1 ) 있는 경우

     4) Pool에 저장된 커넥션 객체 할당.

     5) 객체 사용

     6) 사용 다 하면 반환. => 자원 해제가 아닌 다시 Pool에 저장되는것!

 

3-2 ) 없는 경우 (만약 커넥션 풀이 총 10개인데 동시에 10명이 사용중이라 남은게 없는 경우)

     4) 커넥션이 반환될때까지 기다린다. (대기상태)

         언제까지 기다릴까? => 커넥션 풀 maxWait속성을 지정한 시간동안. 

     5) 계속 기다려도 반환되지 않으면 임시 커넥션 객체 생성.
         임시 커넥션은 다쓰고 반환하면 pool에 들어가는게 아니라 사라진다. 

 

 

 

 

4. 커넥션 풀을 사용하기 위한 라이브러리 설치

커넥션 풀을 사용하기 위해 라이브러리는 총 3개가 필요하다. 

commons-dbcp, commons-pool, commons-collections 예전에는 3개를 다 설치해야했지만,

Tomcat 6버전부터 3개를 통합해서 tomcat-dbcp.jar 하나로 합쳤다. 

 

방법 1) 톰캣에서 제공하는 tomcat-dbcp.jar 찾아서 설치. 

톰캣이 설치된 경로로 이동한다. 

나는 C:\Program Files\Apache Software Foundation\Tomcat 8.5\lib 이경로에 있음!

 

톰캣이 있는 경로에서 tomcat-dbcp.jar파일을 찾아

프로젝트의 WEB-INF/lib 폴더에 복사 붙여넣기 한다. 

 

 

 

 

방법 2) 라이브러리 3개 직접 설치

collections : https://commons.apache.org/proper/commons-collections/download_collections.cgi

dbcp :  https://commons.apache.org/proper/commons-dbcp/download_dbcp.cgi

Pool : https://commons.apache.org/proper/commons-pool/download_pool.cgi

 

 

위 3개의 zip파일을 다운받고 압축을 풀어서

.jar파일을 프로젝트의 WEB-INF/lib에 복붙한다.

 

 

 

 

 

 

 

5. 커넥션 풀 객체(연결정보) 정의

프로젝트의 META-INF/context.xml 파일에 <Resource>태그로 적는다. 

(xml파일은 html처럼 태그형태로 정보를 저장)

<Context>
  <Resource 
	name="디비에 접근하기위한 이름" 
	auth="컨테이너 자원 관리자 설정-Application/Container" 
	type="리소스를 사용할때 실제로 사용되는 클래스 타입"
		<!-- 이 xml이 실제코드로 변환되서 실행할때 무슨 클래스 타입으로 할건지 결정 -->
	driverClassName="드라이브 클래스 주소" 
	username="아이디"
	password="비번" 
	url="DB 주소" 
	maxActive="동시 사용가능한 최대 개수"
	maxIdle = "커넥션 풀에 저장할 수 있는 최대 개수"
	maxWait="가져갈 커넥션이 없을 때 대기 시간(ms)"
  />
</Context>
<Context>
	<Resource 
		name="jdbc/mydb" 
		auth="Container" 
		type="javax.sql.DataSource" 
		username="root" 
		password="1234" 
		driverClassName="com.mysql.cj.jdbc.Driver" 
		url="jdbc:mysql://localhost:3306/jspdb" 
		maxActive="500" 
	/>
</Context>

 

 

 

6. JNDI(Java Naming and Directory Interface)

외부 객체 명명 서비스 및 외부 객체가 있는 디렉터리 접근 API.

커넥션 풀은 자바가 제공하는게 아닌, 톰캣에서 제공하는 API이다.

따라서 톰캣에서 커넥션 풀을 찾기 위해 JNDI가 필요한 것이다. 

 

명명 서비스라는것은 위의 리소스 정보를 가져가기 위해서 어떤 이름으로 가져가겠다고 지정하는것이다.

(출석을 부를때 내 이름으로 호출되는것처럼 이름을 지정. 위의 context.ml에 name=""으로 지정한게 이름을 지은것이다)

이 지정한 이름은 java/comp/env/ 뒤에 붙게된다. 

 

JNDI의 InitialContext()를 통해 프로젝트 초기화( 톰캣과 연결) 하고

          lookup('주소') 를 통해 해당 주소로 톰캣으로부터 커넥션풀 정보를 찾아 Object형식으로 반환한다. 

 

 

 

6. 커넥션 풀을 사용한 DB연결 메서드 작성 : getConnect()

private Connection getConnect() {
  try {
	// 프로젝트(CTX)정보 초기화
	Context initCTX = new InitialContext(); // 업캐스팅
			
	DataSource ds = (DataSource) initCTX.lookup("java:comp/env/jdbc/mydb");
	con = ds.getConnection();
			
  } catch (NamingException e) {
	e.printStackTrace();
  } catch (SQLException e) {
	e.printStackTrace();
  }
  return con;
}

 

Context initCTX = new InitialContext();

     프로젝트 정보를 초기화하고 정보를 가져온다. 

initCTX.lookup()

     괄호 안의 주소로 톰캣에서 데이터들을 가져온다. 주소는 context.xml에서 지정한 name.

 

      lookup()은 지정한 name으로 찾아서 Object형태로 반환하는데,

      context.xml에서 type="javax.sql.DataSource"

      타입을 DataSource로 사용하기로 해놨기때문에 (DataSource)로 다운캐스팅한다. 

      => DB정보를 외부 XML파일(context.xml)로부터 가져와서 사용!!

ds.getConnection()

     커넥션 사용전, DriveManager.getConnection() 하듯이

     DataSource에서 커넥션 정보를 가져온다. 

 

 

 


7. 커넥션 풀 사용전과 후 비교

 

 

728x90