Spring/Maven Project

Spring에 DataSource (Apache Common DBCP2 - 2.9.0) 적용

carrotweb 2022. 9. 17. 03:04
728x90
반응형

DataSource

A factory for connections to the physical data source that this DataSource object represents. An alternative to the DriverManager facility, a DataSource object is the preferred means of getting a connection. An object that implements the DataSource interface will typically be registered with a naming service based on the Java™ Naming and Directory (JNDI) API.

 

DataSource 객체는 물리적 데이터 소스에 연결을 위한 팩토리입니다. (즉, 데이터베이스 연결 정보로 데이터베이스와 연결하고 관리해 주는 객체입니다.) DriverManager 기능의 대안으로 DataSource 객체는 데이터베이스와의 연결을 얻는데 선호하는 수단입니다. DataSource 인터페이스를 구현하는 객체는 일반적으로 JNDI API를 기반으로 하는 이름 지정 서비스에 등록됩니다.

 

 

DataSource는 데이터베이스에 대한 Standard Connection (표준 연결), Connection Pooling (커넥션 풀), Distributed transaction (분산 트랜잭션)을 지원하기 때문에 DriverManager를 사용하여 개발하는 것보다 좋습니다.

 

그럼 DataSource에서 지원하는 Connection Pooling (커넥션 풀)에 대해 알아보겠습니다.

 

DriverManager를 이용하여 데이터베이스를 연결하고 쿼리하는 되는 문제가 없습니다. 그러나 쿼리할 때마다 데이터베이스 연결과 종료를 매번 해야 합니다. 이는 쿼리를 처리할 때마다 데이터베이스 접속과 종료 시간이 필요하게 됨으로 여러 명이 접속하여 수많은 쿼리를 처리하게 될 경우 데이터베이스 접속 시간으로 인해 시스템 처리가 늘어지게 됩니다.

 

그래서 데이터베이스 접속 시간을 줄이기 위해 미리 데이터베이스여러 개 연결하여 Connection(커넥션)들을 만들어 보관하고 데이터베이스 접속 요청이 들어오면 미리 연결된 Connection을 넘겨 쿼리가 바로 실행되도록 합니다. 그리고 쿼리가 처리되고 데이터베이스와의 접속 종료 요청이 들어오면 종료하지 않고 Connection을 다시 보관합니다. 이렇게 Connection을 관리하는 것을 Connection Pool(커넥션 풀)이라 합니다. (Connection이 보관되는 장소가 Pool입니다.)

 

 

섹션에서 Connection 요청 → Connection Pool에서 Connection 제공 → 섹션에서 사용이 끝난 Connection 반환

 

 

Maven Spring Project에 Apache Commons DBCP 적용하기

 

1. 메이븐 리포지토리(https://mvnrepository.com)에서 "commons-dbcp2"으로 검색합니다. 검색된 결과 중에 "org.apache.commons >  commons-dbcp2"인 Apache Commons DBCP를 선택합니다.

 

2. "Version"중에서 "2.9.0"를 선택합니다. 그리고 [Maven] 탭을 선택하고 복사합니다.

<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-dbcp2 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-dbcp2</artifactId>
    <version>2.9.0</version>
</dependency>

Commons DBCP 버전이 2.x 이면 JDK 버전은 7 이상, Spring JDBC 버전은 4.1 이상이어야 합니다.

참고로, Commons DBCP 버전이 1.4이면 JDK 버전은 6 이상, Spring 버전은 4 이상이어야 합니다.

 

링크를 클릭하면 바로 받을 수 있습니다.

https://mvnrepository.com/artifact/org.apache.commons/commons-dbcp2/2.9.0

 

3. 메이븐 프로젝트에서 pom.xml 파일을 오픈하고 복사한 내용을 붙여 넣기 하고 저장합니다.

그러면 자동으로 Apache Common DBCP2 라이브러리 파일(JAR)들이 다운로드됩니다.

commons-dbcp2-2.9.0.jar
commons-pool2-2.10.0.jar
commons-logging-1.2.jar

 

 

그럼 DataSource 객체를 사용할 수 있게 Bean 객체로 생성하겠습니다.

 

생성되는 DataSource 객체는 전역에서 사용할 수 있어야 하기 때문에 ContextLoaderListener를 통하여 생성되게 하겠습니다. ContextLoaderListener는 전역에서 사용할 Context를 로드하는 리스너입니다.

 

왜 Servlet의 contextConfigLocation가 아닌 ContextLoaderListener의 contextConfigLocation에 로드해야 할까요?

 

그 이유는 Servlet의 Context는 WebApplicationContext으로 해당 Servlet에서만 사용할 수 있습니다. 그래서 DataSourc 객체를  Servlet의 Context으로 로드하면 다른 Servlet에서는 사용할 수 없습니다. Servlet이 하나면 문제 되지 않습니다.

 

그러나 여러 Servlet으로 구성되어 있다면 DataSourc 객체와 같이 공통으로 사용되는 Context는 전역으로 로드되어야 여러 Servlet에서 사용할 수 있습니다. 그래서 ContextLoaderListener로 Context를 로드하면 RootApplicationContext가 되어 여러 Servlet에서 사용할 수 있게 됩니다.

 

 

Maven Spring Project에 ContextLoaderListener 적용하기

 

1. WEB-INF/web.xml 파일을 클릭하여 오픈하고 <web-app>의 <servlet> 위에 <context-param>와 <listener>를 추가합니다.

  1. <listener>에 Spring의 ContextLoaderListener를 입력합니다.
  2. ContextLoaderListener에서 Context를 가져오게 하기 위해 <listener> 위에  <context-param>를 추가합니다. <context-param>의 <param-name>으로 "contextConfigLocation"가 없으면 기본적으로 /WEB-INF/applicationContext.xml를 로드합니다.
  3. ContextLoaderListener에서 Context을 로드하기 위해 <context-param>의 <param-value>에 경로를 입력합니다.
<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>
		/WEB-INF/config/context-datasource-mariadb.xml
	</param-value>
</context-param>
<listener>
	<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

 

또는 Context가 Java Resource에 있으면 classpath로 경로를 입력합니다.

<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>
		classpath:com/home/study/test1/config/context-datasource-mariadb
	</param-value>
</context-param>
<listener>
	<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

 

 

저는 여러 개의 Context가 Java Resource에 있는 것으로 진행하겠습니다.

여러 개의 Context를 로드하기 위해서 classpath*로 경로를 입력합니다.

classpath에 *가 있으면 여러 개를 파일을 가져오고 *가 없으면 처음 발견된 것만 가져옵니다.

<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>
		classpath*:com/home/study/**/config/context-*.xml
	</param-value>
</context-param>
<listener>
	<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<param-value>에 입력된 경로를 해석하면 com/home/study 폴더 및 하위 폴더에 있는 config 폴더에 파일 명이 "context-"으로 시작하는 .xml 파일들만 가져오게 됩니다.

 

2. Java Resource > src/main/resource > com/home/study/test1/config 폴더를 생성합니다.

  1. src/main/resource에 com 폴더 생성 → com 폴더에 home 폴더 생성 → home 폴더에 study 폴더 생성
  2. 프로젝트를 구분하기 위해서 study 폴더에 test1 폴더 생성  test1 폴더에 config 폴더 생성

 

3. Java Resource > src/main/resource > com/home/study/test1/config 폴더에 context-datasource-mariadb.xml 파일을 생성합니다.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		xmlns:jdbc="http://www.springframework.org/schema/jdbc"
		xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
</beans>

 

4. DataSource 객체를 생성합니다.

  1. DataSource 객체를 생성하기 위해 클래스로 Apache Common DBCP2의 BasicDataSource (org.apache.commons.dbcp2.BasicDataSource)를 입력합니다.
  2. destroy-method 속성에 "close"를 입력합니다. (Spring에서 Application Context(애플리케이션 콘텍스트 - Bean 객체를 생성하고 관리)가 종료될 때 Bean 객체의 destroy-method 속성에 설정된 메서드를 호출해 줍니다. 즉 BasicDataSource 클래스의 close 메서드를 호출해 줍니다.)
  3. driverClassName는 DataSource 객체에 사용할 JDBC Driver로 MariaDB JDBC Driver(org.mariadb.jdbc.Driver)를 입력합니다.
  4. url은 DataSource 객체에서 연결할 데이터베이스의 접속 URL를 입력합니다. (현재 PC에 설치된 MariaDB임으로 host와 port는 "localhost:3306"이고 database는 "study"입니다.)
  5. user는 데이터베이스의 접속 계정을 입력합니다.
  6. password는 데이터베이스의 접속 패스워드를 입력합니다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		xmlns:jdbc="http://www.springframework.org/schema/jdbc"
		xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">

	<bean id="dataSourceMariaDB" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
		<property name="driverClassName" value="org.mariadb.jdbc.Driver" />
		<property name="url" value="jdbc:mariadb://localhost:3306/study" />
		<property name="username" value="root" />
		<property name="password" value="password" />
	</bean>
</beans>

 

 

DataSource 테스트 하기

 

1. @Autowired와 @Qualifier Annotation(어노테이션)을 추가하여 DataSource 객체를 가져옵니다.

  1. @Qualifier에 생성된 DataSource 객체의 ID인 "dataSourceMariaDB"를 입력하면 스프링 컨테이너가 ID가 "dataSourceMariaDB"인 Bean 객체를 찾습니다.
  2. @Autowired Annotation(어노테이션)으로 선언된 dataSource 변수에 찾은 Bean 객체를 주입하게 됩니다.

 

2. 선언된 dataSource 변수를 사용하여 MariaDB의 Connection를 가져오고 close 하게 코딩합니다.

@Autowired
@Qualifier("dataSourceMariaDB")
DataSource dataSource;

@RequestMapping("/index")
public String mainIndex(HttpServletRequest request, HttpServletResponse response, ModelMap model) {
	Connection connection = null;
	try {
		connection = dataSource.getConnection();
		System.out.println("마리아디비에 연결됨");
	} catch (SQLException e) {
		e.printStackTrace();
		System.out.println("마리아디비 드라이버가 로딩되지 않음");
	} finally {
		if (null != connection) {
			try {
				connection.close();
				System.out.println("마리아디비에서 연결을 종료함");
			} catch (SQLException e) {
				e.printStackTrace();
				System.out.println("마리아디비에서 연결을 종료하지 못함");
			}
		}
	}
}

위의 코드는 테스트를 위한 코드입니다. 테스트 후 코드는 삭제하시면 됩니다.

 

이제 DriverManager가 아닌 DataSource로 데이터베이스와 연결되고 Connection Pool로 사용할 수 있게 되었습니다.

 

이어서, MyBatis-Spring로 Spring에서 MyBatis를 사용할 수 있게 처리하겠습니다.

728x90
반응형