[ 소개 ]
- Tomcat 은 Jakarta EE 에서 제공하는것과 호환되는 방식으로 각 WEB_Application 에 JNDI InitialContext 구현 인스턴스를 제공한다.
- Jakarta EE 표준은 리소스를 참조/정의하기위해 /WEB-INF/web.xml 파일에 표준 설정을 제공한다.
- JNDI 용 API 프로그래밍에 대한 자세한 정보와 Tomcat 에서 에뮬레이트 해서 서비스를 지원하는 Jakarta EE 에 대한 기능을 보려면 다음을 참고한다.
1. Java Naming and Directory Interface (included in JDK 1.4 onwards)
2. Jakarta EE Platform Specification (in particular, see Chapter 5 on Naming)
PS.
- Java EE 가 이클립스 재단으로 이관된 이후 Jakarta EE 로 명칭이 변경되었다.
[ 용어 ]
- WEB_Application Deploy Descriptor : /WEB-INF/web.xml 파일
[ web.xml 구성 ]
- 아래의 Element 는 WEB_Application 의 /WEB-INF/web.xml 에서 사용이 가능하다.
1. <env-entry>
엔트리 환경은 Application 동작을 구성하는데 사용할 수 있는 단일값 매개변수 이다.
2. <resource-ref>
리소스 참조는 일반적으로 JDBC DataSource, Jakarta Mail Session 또는 Tomcat 에 구성된 커스텀 Object Factory와 같은 리소스에 대한 Object Factory 이다.
3. <resource-env-ref>
리소스 환경 참조는 Servlet 2.4 에 추가된 resource-ref 의 새로운 변형 설정으로, 인증정보가 필요하지 않은 리소스에 대해 더 간단히 구성이 가능하다.
- Tomcat 이 리소스를 생성하는데 사용할 Resource Factory 를 식별할 수 있고, 추가 구성정보가 필요하지 않다면 /WEB-INF/web.xml 을 사용하여 리소스를 생성한다.
- Tomcat 은 web.xml 에서 지정할 수 없는 JNDI 리소스에 대한 여러 Tomcat 전용 옵션을 제공한다.
여기에는 WEB_Application 이 중지될 때 JNDI 리소스를 더 빠르게 정리할 수 있는 closeMethod 와 모든 JNDI lookup 에 대해 리소스의 새 인스턴스를 생성할 지 여부를 제어하는 singleton 이 포함된다.
이러한 구성 옵션을 사용하려면 WEB_Application 의 <Context> 요소 또는 $CATALINA_BASE/conf/server.xml 파일의 <GlobalNamingResources> 요소에 기술하면 된다.
[ context.xml 구성 ]
- Tomcat 이 적절한 Resource Factory 를 식별할 수 없거나 추가 구성정보가 필요한경우, Tomcat 이 리소스를 생성하기전에 추가 관련 설정을 지정해야 한다.
Tomcat 의 Resource 설정은 $CATALINA_BASE/conf/server.xml 파일의 <Context> 요소에 입력하거나 각 WEB_Application 별 Context XML 파일(META-INF/context.xml)에 지정한다.
- Tomcat 의 Resource 설정은 <Context> 요소 안에 아래의 요소를 사용하여 구성한다.
1. <Environment>
- JNDI InitialContext 를 통해 WEB_Application 에 노출할 스칼라 환경 항목의 이름과 값을 구성한다. (WEB_Application Deploy Descriptor 에 <env-entry> 요소를 포함하는 것과 동일함)
2. <Resource>
- Application 에서 사용할 수 있는 Resource 의 이름과 데이터 유형을 구성한다. (WEB_Application Deploy Descriptor 에 <resource-ref> 요소를 포함하는 것과 동일함)
3. <ResourceLink>
- 글로벌 JNDI Context 에 정의된 Resource 에 대한 링크를 추가한다. Resource Link 를 사용하여 <Server> 요소 하위의 <GlobalNamingResources> 요소에 정의된 Resource 에 대해 접근 권한을 부여한다.
4. <Transaction>
- java:comp/UserTransaction 에서 사용할 수 있는 UserTransaction 객체의 인스턴스를 인스턴스화 하기위한 Resource Factory 를 추가한다.
- 이러한 요소는 <Context> 요소 내부에 중첩될 수 있으며 해당 WEB_Application 에만 연관된다.
- Resource 가 <Context> 요소에 정의되어 있는 경우 해당 Resource 를 /WEB-INF/web.xml 파일에 정의할 필요는 없지만, WEB_Application 의 Resource 요구사항을 문서화 하기위해 /WEB-INF/web.xml 에 항목을 기술하는 것을 권장한다.
- /WEB-INF/web.xml 파일 내부의 <env-entry> 요소와 WEB_Application 의 <Context> 요소 내부에 있는 <Environment> 요소와 동일한 Resource 이름이 정의된 경우 <Environment override="true"> 속성이 정의되어 있다면 <Environment> 요소가 우선권을 갖는다.
[ Global 구성 ]
- Tomcat 은 각 <Server> 항목의 Global Resource namespace 별로 관리를 하며, $CATALINA_BASE/conf/server.xml 파일의 <GlobalNamingResources> 요소로 구성한다. 또한 각 WEB_Application 의 Context 안에 <ResourceLink> 를 사용하여 Resource 를 노출시킬 수 있다.
- Resource 가 <ResourceLink> 를 사용하여 정의된경우 해당 리소스를 /WEB-INF/web.xml 에 정의할 필요는 없지만 해당 WEB_Application 의 리소스 요구사항을 문서화 하기위해 /WEB-INF/web.xml 에 항목을 기술하는것을 권장한다.
[ Resource 사용 ]
- InitialContext 는 WEB_Application 이 처음 배포될 때 구성되며, WEB_Application 컴포넌트에서 사용할 수 있다. (읽기 전용 접근)
- JDBC DataSource 의 경우 JNDI namespace 의 java:comp/env 부분에 위치한 Resource 와 항목들의 모든 설정은 일반적으로 아래와 같이 Resource 에 접근한다.
[ Tomcat 표준 Resource Factory ]
- 톰캣은 WEB_Application 에 서비스를 제공할 수 있는 표준 Resource Factory 들이 포함되어 있고, WEB_Application 이나 web.xml 을 수정하지 않고 <Context> 요소를 통해 유연하게 수정이 가능하다.
- 아래의 각 하위 섹션에서는 표준 Resource Factory 들의 구성 및 사용법에 대해 자세히 설명한다.
- Tomcat 에서 커스텀 리소스 팩토리 클래스를 생성/설치/구성 및 사용하는 방법에 대한 자세한 내용은 아래 [커스텀 Resource Factory 추가하기] 항목을 참조한다.
- 참고
1) 표준 Resource Factory 중 JDBC Data Source, User Transaction 팩토리만 다른 플랫폼에서 사용 가능하도록 의무화 되어있으며, 해당 플랫폼이 Jakarta EE 사양을 구현하는 경우에만 필요하다.
2) 다른 모든 표준 Resource Factory 와 사용자가 직접 작성한 커스텀 Resource Factory 는 Tomcat 에만 해당되며, 다른 컨테이너에서 사용할 수 있다고 생각하면 안된다.
1. 일반 JavaBean 리소스
0) 소개
- 해당 Resource Factory 는 (인수가 0개인 생성자가 있고 setFoo() 명명 패턴의 속성 설정자가 있는) 표준 JavaBeans 명명규칙을 준수하는 모든 Java 클래스의 객체를 생성하는데 사용할 수 있다.
- Factory 의 singleton 속성이 false 로 설정된 경우 이 항목에 대한 lookup() 이 수행될 때마다 해당 Bean 클래스가 새로운 인스턴스를 매번 생성한다.
- 이 기능을 사용하는데 필요한 단계는 아래의 설명 참조
1) JavaBean Class 생성
- Resource Factory 를 조회할 때마다 인스턴스화 되는 JavaBean 클래스를 생성한다. 이 예제는 com.mycompany.MyBean 이라는 클래스를 생성한다고 가정한다.
2) 리소스 요구사항 선언
- 다음으로 WEB_Application 배포설명자(/WEB-INF/web.xml) 을 수정하여 해당 Bean 의 새로운 인스턴스를 요청할 JNDI 이름을 선언한다. 가장 간단한 방법은 다음과 같이 <resource-env-ref> 요소를 사용하는 것이다.
경고: WEB_Application 배포설명자(Deployment_Descriptor)에 대한 DTD에서 요구하는 Element 순서를 반드시 준수해야 한다. (Servlet Spec 참조)
3) 해당 리소스 사용을 위한 Application 코드
- 해당 리소스 환경을 참조하기 위한 일반적인 사용방법은 다음과 같다.
4) Tomcat 의 Resource Factory 설정
- WEB_Application 에서 사용하기위해 <Context> 요소에 아래와 같이 Tomat 에 Resource Factory 를 설정할 수 있다.
- (bean/MyBeanFactory) Resource 이름은 WEB_Application 의 배포설명자(/WEB-INF/web.xml)에 지정된 값과 일치해야 한다.
- 새로운 Bean 을 리턴하기전에 bar 속성에 대해서 setBar(23) 을 호출하여 초기화 한다.
- (초기화 가능하지만) foo 속성은 초기화 하지 않기 때문에 Bean 생성자가 설정한 기본값을 가지고 있다.
- Bean 의 속성이 String 인경우, BeanFactory 는 setter 를 호출하여 속성을 설정한다.
- Bean 의 속성이 (int 나 Integer 와 같이) Primitive 또는 Primitive Wrapper 인경우 BeanFactory 는 적절한 Primitive 또는 Primitive Wrapper 로 변환 후 setter 를 호출한다.
- 일부 Bean 에서는 String 에서 자동으로 변환할 수 없는 유형의 프로퍼티가 있는데 Bean 에서 동일한 이름의 문자열의 setter 가 있는 경우 BeanFactory 는 해당 setter 를 사용하려고 시도한다.
- BeanFactory 가 값을 사용할 수 없거나 적절한 변환을 수행할 수 없는경우 NamingException 과 함께 속성의 설정에 실패한다.
- 이전 Tomcat 릴리즈에서 사용하던 forceString 속성은 보안강화를 위해 제거되었다.
2. 메모리 (UserDatabase)사용자 데이터베이스 리소스
0) 소개
- 사용자 데이터베이스 리소스는 일반적으로 사용자 데이터베이스 Realm(영역) 에서 사용할 수 있도록 전역 Resource 로 구성되며, Tomcat 은 (보통 tomcat-users.xml 사용) XML 파일로 사용자 데이터베이스 리소스를 생성하는 UserDatabaseFactory 가 포함되어 있다.
- 전역 사용자 데이터베이스 리소스 설정하는데 필요한 단계는 아래 내용 참조.
1) XML 파일 생성/수정
- XML 파일은 일반적으로 $CATALINA_BASE/conf/tomcat-users.xml 파일에 위치하며, 해당 위치가 강제가 아니고 다른곳에 둘수 있지만 $CATALINA_BASE/conf 위치에 두는 것을 권장한다. 내용은 아래 참조.
2) Resource 선언
- 다음으로 $CATALINA_BASE/conf/server.xml 의 XML 파일을 기반으로 사용자 데이터베이스 리소스를 생성할 수 있다. 아래와 같아야 한다.
- pathname 속성은 URL / 절대경로 / 상대경로 설정이 가능하다. 상대경로는 $CATALINA_BASE 를 기준으로 한다.
- readonly 속성의 기본값은 true 이며, XML 이 쓰기권한이 있으면 Tomcat 이 기동될 때 (파일이) 생성된다.
- 경고: 파일이 생성되면 Tomcat 을 실행중인 OS user 에 대한 기본 파일 권한이 상속된다. 설치에 대해서 해당 권한이 보안에 문제가 없는지 확인을 해라.
- Realm 에서 참조되는 경우 (UserDatabase) 사용자 데이터베이스는 기본적으로 pathname 파일의 마지막 변경시간을 모니터링 하다가 변경된경우 다시 로드를 한다. 해당 기능을 비활성화 하려면 watchSource 속성을 false 설정하면 된다.
3) Realm 설정
Realm 구성 문서에 설명한대로 이 리소스를 사용하도록 UserDatabase Realm 을 구성한다.
3. DataSource (UserDatabase)사용자 데이터베이스 리소스
0) 소개
- Tomcat 은 DataSource Resource 를 백엔드로 사용하는 (UserDatabase)사용자 데이터베이스도 포함한다. 백엔드 리소스는 이를 사용할 데이터베이스와 동일한 JNDI Context 에서 선언해야 한다.
- 전역 사용자 데이터베이스 리소스 설정하는데 필요한 단계는 아래 내용 참조.
1) Database 스키마
- 사용자 데이터베이스의 DB스키마는 유연하다.
- 사용자(username, password)에 대한 테이블과 각 사용자에 대한 (role) 역할이 있는 테이블이 있는 DataSourceRealm 에서 사용하는 스키마와 똑같을수 있고, 전체 UserDatabase 기능을 지원하려면 그룹에 대한 추가 테이블을 포함해야 하고, user/group/role 에 대한 참조무결성과 호환되어야 한다.
- 그룹과 참조무결성을 갖춘 전체 기능의 스키마는 아래와 같다.
- 그룹을 사용할 수 없는 최소 스키마는 아래와 같다. (DataSourceRealm 과 동일)
2) 리소스 선언
- 다음으로 DataSource 와 해당 스키마를 기반으로 UserDatabase Resource 를 생성할 수 있도록 $CATALINA_BASE/conf/server.xml 을 수정한다. 아래와 같아야 한다.
- dataSourceName 속성은 UserDatabase 의 백엔드가 될 DataSource 의 JNDI 이름이다.
- 이 리소스는 UserDatabase 의 JNDI Context 와 동일한곳에 선언해야 하며 자세한 지침은 아래 5. JDBC Data Source 내용 참고
- readonly 속성의 기본값은 true 이며, DB에 쓰기 권한이 있는경우 Tomcat Management 를 통해 변경사항을 DB에 save 기능을 이용해 저장하여 UserDatabase 를 유지할 수 있다.
- 또는 백엔드 DB를 직접 변경할수도 있다.
3) 리소스 설정
속성 | 설명 |
---|---|
dataSourceName | UserDatabase 의 JNDI JDBC DataSource 이름 |
groupNameCol | groups / group roles / user groups 테이블에서 그룹 이름이 포함된 컬럼 이름 |
groupRoleTable | groupNameCol 과 roleNameCol 속성 이름으로 된 컬럼이 있는 group roles 테이블 이름 |
groupTable | groupNameCol 속성의 이름으로된 컬럼이 있는 groups 테이블 이름 |
readonly | 기본값: true save 메소드를 사용하여 UserDatabase 를 DataSource 에 유지할수 있는 기능 |
roleAndGroupDescriptionCol | 설명이 포함된 roles / groups 테이블의 컬럼 이름 |
roleNameCol | roles / user roles / group roles 테이블에서 사용자에 할당된 role 컬럼 이름 이 속성은 대부분의 구성에서 필수이며, 생략할 수 있는 예외 케이스를 보려면 Realm 항목에 연관된 allRolesMode 속성을 참조 |
roleTable | roleNameCol 속성 이름의 컬럼이 있는 roles 테이블 이름 |
userCredCol | users 테이블에서 (password 와 같이) 사용자 자격증명에 사용하는 컬럼의 이름 만약 <CredentialHandler> 컴포넌트가 지정된 password 는 해당 컴포넌트에서 지정된 알고리즘으로 인코딩 된것으로 간주하며, 그렇지 않은경우 평문으로 간주한다. |
userGroupTable | userNameCol 과 groupNameCol 속성 이름의 컬럼을 가지고 있는 user groups 테이블 이름 |
userNameCol | users / user groups / user roles 테이블에서 사용하는 사용자의 username 컬럼 이름 |
userFullNameCol | users 테이블에서 사용자의 전체이름이 있는 컬럼의 이름 |
userRoleTable | userNameCol 과 roleNameCol 속성 이름의 컬럼을 가지고 있는 user roles 테이블 이름 이 속성은 대부분의 구성에서 필수이며, 생략할 수 있는 예외 케이스를 보려면 Realm 항목에 연관된 allRolesMode 속성을 참조 |
userTable | userNameCol 과 userCredCol 속성 이름의 컬럼을 가지고 있는 users 테이블 이름 |
4) Realm 설정
Realm 구성 문서에 설명한대로 이 리소스를 사용하도록 UserDatabase Realm 을 구성한다.
4. Jakarta Mail Session
0) 소개
- 많은 WEB_Application 에서 이메일 발송은 필수 기능이 되어버렸다. Jakarta Mail API 를 사용하면 이 프로세스가 비교적 간단하지만 클라이언트 Application 이 알아야할 많은 구성정보가 필요하다. (메시지 전송에 사용할 SMTP 호스트명 포함)
- Tomcat 에는 jakarta.mail.Session 세션 인스턴스를 생성하는 표준 Resource Factory 가 포함되어 있으며 SMTP 서버 연결 구성이 이미 되어있다.
- 이러한 방식으로 Application 은 이메일 구성환경의 변경으로 부터 완전히 격리되어 필요할 때마다 미리 구성된 세션을 요청하고 전달받기만 하면 된다.
- 이를 위해 필요한 사항은 아래에 설명되어 있다.
1) 리소스 요구사항 선언
- 가장 먼저 할일은 WEB_Application 의 배포설명자(/WEB-INF/web.xml)에 미리 구성된 세션을 조회할 JNDI 이름을 선언하는 것이다.
- 관례에 따라 이러한 모든 이름은 mail subcontext 로 지정한다. (제공하는 모든 Resource Factory 들의 root 인 표준 java:comp/env 이름 context 의 상대적 기준)
- 경고: WEB_Application 배포설명자에 대한 DTD 에서 요구하는 순서를 반드시 준수해야 한다. Servlet 스펙 문서 참고
2) 해당 리소스를 사용하기위한 Application 코드
- 해당 Resource 의 참조는 일반적으로 아래와 같다.
- Application 은 /WEB-INF/web.xml 에 선언한 것과 동일한 Resource 참조 이름을 사용하며, 아래에 설명한것과 같이 WEB_Application 의 <Context> 요소에 구성된 Resource Factory 와 일치한다.
3) Tomcat Resource Factory 설정
- Tomat 의 Resource Factory 를 구성하려면 WEB_Application 의 <Context> 요소에 아래와 같이 <Resource> 요소를 추가한다.
- (위에 mail/Session 설정한 것과 같이) 해당 리소스 name 은 /WEB-INF/web.xml 에 기술한 값과 동일해야 하고, mail.smtp.host 파라미터에 네트워크에서 SMTP 서비스를 제공하도록 값을 지정한다.
- 추가 Resource 의 attribute / value 는 properties / values 로 변환되어 java.util.Properties Collection 의 일부로 jakarta.mail.Session.getInstance(java.util.Properties) 로 전달된다.
- Jakarta Mail 스펙의 부록 A 에 정의된 속성 외에도 개별 (메일)제공업체는 추가 속성을 지원할 수도 있다.
- Resource 가 password 속성과 mail.smtp.user 또는 mail.user 속성으로 구성된 경우, Tomcat Resource Factory 는 mail session 에 jakarta.mail.Authenticator 를 추가하여 구성한다.
4) Jakarta Mail API 설치
- 배포 패키지를 풀고 jakarta.mail-api-2.1.0.jar 파일을 $CATALINA_HOME/lib 에 두면 Tomcat 이 Mail Session Resource 를 초기화 할 때 사용한다.
- 참고: 이 jar 파일을 $CATALINA_HOME/lib 디렉토리와 WEB_Application 의 lib 디렉토리 둘다 넣으면 오류가 발생하므로 $CATALINA_HOME/lib 디렉토리에만 넣어야 한다.
5) Jakarta Mail 스펙 호환 구현체 설치
- 구현체의 압축을 풀고 jar 파일을 $CATALINA_HOME/lib 에 넣는다.
- 참고: 다른 구현체도 가능할 수 있다.
- PS: 이 글의 작성시점에 호환 구현체는 Angus Mail 2.0.2 만 보여진다.
6) Tomcat 재기동
- 추가한 jar 를 Tomcat 에서 사용하려면 Tomcat 인스턴스가 재기동 되어야 한다.
7) 예제 Application
- Tomcat 에 포함된 /examples Application 에는 해당 Resource Factory 를 활용하는 예제가 들어있다. "JSP Examples" 링크를 통해 접근할 수 있고, 실제 Mail Message 를 보내는 서블릿 코드는 /WEB-INF/classes/SendMailServlet.java 에 있다.
- 경고: 기본 구성은 SMTP 서버가 localhost 의 25 포트를 사용하고 있다고 가정한다. 그렇지 않은경우 WEB_Application 의 <Context> 요소를 편집하고 mail.smtp.host 파라미터의 값을 네트워크에 있는 SMTP 서버의 host 이름으로 수정한다.
1004lucifer
5. JDBC Data Source
0) 소개
- 많은 WEB_Application 은 해당 Application 에 필요한 기능을 지원하기 위해 JDBC 드라이버를 통해 데이터베이스에 접근해야 한다.
- Jakarta EE 플랫폼 스펙에서는 이를 위해 Jakarta EE Application 서버가 DataSource 구현(JDBC 연결을 위한 Connection Pool)을 제공하도록 요구한다.
- Tomcat 은 정확히 동일한 지원을 제공하므로 이 서비스를 사용하여 Tomcat 에서 개발하는 데이터베이스 기반 Applicaion 은 모든 Jakarta EE 서버에서 변경없이 동작된다.
- JDBC 에 대한 자세한 내용은 다음을 참고
1. http://www.oracle.com/technetwork/java/javase/jdbc/index.html - Java 데이터베이스 연결에 대한 정보를 제공하는 홈페이지
2. http://java.sun.com/j2se/1.3/docs/guide/jdbc/spec2/jdbc2.1.frame.html - JDBC 2.1 스펙
3. http://java.sun.com/products/jdbc/jdbc20.stdext.pdf - JDBC 2.0 표준 확장 API (javax.sql.DataSource API 포함). 이 패키지는 "JDBC Optional Package" 로 알려짐
4. https://jakarta.ee/specifications/platform/9/ - Jakarta EE 플랫폼 스펙 (모든 Jakarta EE 플랫폼이 Application 에 제공해야 하는 JDBC 기능을 다룬다)
- 참고: Tomcat 의 기본 DataSource 는 Common 프로젝트의 DBCP_2 Connection Pool 을 기반으로 되어있다. 하지만 아래 [커스텀 Resource Factory 추가하기] 설명대로 커스텀 Resource Factory 를 직접 작성하여 javax.sql.DataSource 를 구현하는 다른 Connection Pool 을 사용할 수 있다.
1) JDBC Driver 설치
- JDBC DataSource JNDI Resource Factory 를 사용하려면 적절한 JDBC 드라이버를 Tomcat 내부 클래스와 WEB_Application 에 모두 제공해야 한다.
- 이 작업은 JDBC Driver JAR 파일을 $CATALINA_HOME/lib 디렉토리에 설치하여 손쉽게 Resource Factory 와 Application 모두에서 드라이버를 사용할 수 있게 할 수 있다.
2) 리소스 요구사항 선언
- 다음으로 WEB_Application 배포설명자(/WEB-INF/web.xml) 을 수정하여 미리 구성된 DataSource 를 조회할 JNDI 이름을 선언한다.
- 관례에 따라 이러한 모든 이름은 jdbc subcontext 로 지정한다. (제공하는 모든 Resource Factory 들의 root 인 표준 java:comp/env 이름 context 의 상대적 기준)
- 일반적인 web.xml 항목은 아래와 같다.
- 경고: WEB_Application 배포설명자에 대한 DTD 에서 요구하는 순서를 반드시 준수해야 한다. Servlet 스펙 문서 참고
3) 해당 Resource 를 사용하기 위한 Application 코드
- 해당 Resource 의 참조는 일반적으로 아래와 같다.
- Application 은 /WEB-INF/web.xml 에 선언한 것과 동일한 Resource 참조 이름을 사용하며, 아래에 설명한것과 같이 WEB_Application 의 <Context> 요소에 구성된 Resource Factory 와 일치한다.
4) Tomcat Resource Factory 설정
- WEB_Application 에서 사용하기위해 <Context> 요소에 아래와 같이 Tomat 에 Resource Factory 를 설정할 수 있다.
- (jdbc/EmployeeDB) Resource 이름은 WEB_Application 의 배포설명자(/WEB-INF/web.xml)에 지정된 값과 일치해야 한다.
- 이 예제에서는 HypersonicSQL 데이터베이스 JDBC Driver 를 사용한다고 가정하며, driverClassName 과 driverName 은 실제 사용하는 데이터베이스 JDBC Driver 와 Connection URL 과 일치해야 한다.
- Tomcat 의 표준 DataSource Resource Factory (org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory) 에 대한 속성은 아래와 같다.
1. driverClassName - 사용할 JDBC Driver 의 FQCN (Class 전체경로) 이름
2. username - JDBC Driver에 전달할 데이터베이스 사용자 이름
3. password - JDBC Driver 에 전달할 데이터베이스 비밀번호
4. url - JDBC Driver 에 전달할 URL (이전 버전과의 호환성을 위해 driverName 도 인식됨)
5. initialSize - Pool 초기화 중 생성할 Connection (기본값: 0)
6. maxTotal - Pool 에서 동시에 할당할 수 있는 최대 Connection (기본값: 8)
7. minIdle - Pool 에서 동시에 유휴상태로 있는 최소 Connection (기본값: 0)
8. maxIdle - Pool 에서 동시에 유휴상태로 있는 최대 Connection (기본값: 8)
9. maxWaitMilis - (사용 가능한 Connection 이 없을 때) Pool 에서 Exception 반환전까지 대기할 수 있는 최대 밀리초 시간 (기본값: -1, 무한)
- 일부 추가 속성은 연결 유효성 검사를 처리한다.
1. validationQuery - Pool 에서 Application 에게 Connection 을 반환하기 전에 유효성을 검사할 SQL 쿼리문. 값 셋팅 시 최소한 1개의 row 를 반환하는 SELECT 문 쿼리 이어야 한다.
2. validationQueryTimeout - validationQuery 의 응답 대기 (초) 시간 (기본값: -1, 무한)
3. testOnBorrow - Pool 에서 Connection 을 빌릴 때마다 검증해야 하는지 여부 (기본값: true)
4. testOnReturn - Connection 이 Pool 로 반환될 때마다 검증해야 하는지 여부 (기본값: fasle)
- Evictor Thread 옵션은 장시간 유휴 상태인 Connection 을 제거하여 Pool 을 줄이는 역할을 한다.
- Evictor 는 minIdle 을 따르지 않기에, maxIdle 속성에 따라 Pool 만 줄이려는 경우 Evictor Thread 를 활성화 할 필요가 없다.
- Evictor 는 기본적으로 비활성화 되어있으며, 아래 석성을 사용하여 구성할 수 있다.
1. timeBetweenEvictionRunsMillis - Evictor 의 연속 실행 사이의 (밀리초) 시간 (기본값: -1, 비활성화)
2. numTestsPerEvictionRun - Evictor 가 동작할 때마다 유휴 상태를 검사할 Connection 개수 (기본값: 3)
3. minEvictableIdleTimeMillis - Evictor 가 Pool 에서 Connection 을 제거할 수 있는 유휴 (밀리초) 시간 (기본값: 30*60*1000, 30분)
4. testWhileIdle - Connection 이 Pool 에서 유휴 상태일 때 validationQuery 를 사용하여 Evictor Thread 에 의해 검증되어야 하는지 여부 (기본값: false)
- 또 다른 옵션은 (abandoned) 버려진 Connection 을 제거하는 기능이다.
- Application 이 오랜시간 Connection 을 반환하지 않으면 해당 Connection 은 버려진 것으로 본다 (called abandoned)
- Pool 은 이러한 Connection 을 자동으로 Close 시키고 Pool 에서 제거하며, Application 의 Connection Leak 에 대한 해결방안이다.
- abandoned 기능은 기본적으로 비활성이며, 아래 속성을 구성하여 사용할 수 있다.
1. removeAbandonedOnBorrow - Pool 에서 Connection 을 가져올 때 버려진 Connection 을 제거할지 여부 (기본값: false)
2. removeAbandonedOnMaintenance - Pool 유지관리 중 버려진 Connection 을 제거할 지 여부 (기본값: false)
3. removeAbandonedTimeout - Pool 에서 가져온 Connection 이 버려진 것으로 간주하는 (초) 시간 (기본값: 300)
4. logAbandoned - Application 코드에서 버려진 Statement 나 Connection 에 대한 로그를 추적할지 여부, 심각한 오버헤드가 추가됨 (기본값: false)
- PS (작성자 의견)
1. abandoned 기능 사용 시 300초 넘게 수행되는 쿼리가 있는 경우 removeAbandonedTimeout 에 의해서 Connection 이 abandon 체크가 되므로 이슈 발생 확률 있음, 사용 권장하지 않음
2. 트랜잭션 사용시 하나의 커넥션으로 여러 쿼리를 수행 후 Commit 을 수행해야 하는데 300초 넘어가는 쿼리가 있으면 해당 커넥션이 종료되어 다음 쿼리를 수행할 수 없어 Exception 이 발생한다.
3. 요즘에는 JPA 나 MyBatis 프레임워크를 사용하기에 예전처럼 Connection Leak 이 발생할 확률이 낮다.
- 마지막으로 Pool 동작을 더욱 미세하게 조정할 수 있는 속성이 있다.
1. defaultAutoCommit - Pool 에서 생성된 Connection 의 auto-commit 상태 (기본값: true)
2. defaultReadOnly - Pool 에서 생성한 Connection 의 read-only 상태 (기본값: false)
3. defaultTransactionIsolation - 기본 트랜잭션의 격리 상태 : NONE, READ_COMMITTED, READ_UNCOMMITED, REPEATABLE_READ, SERIALIZABLE (기본값: 설정없음)
4. PoolPreparedStatements - PreparedStatements, CallableStatements 을 Pool 관리 할지 여부 (기본값: false)
5. maxOpenPreparedStatements - Statement Pool 에서 동시에 할당할 수 있는 최대 오픈 Statements 개수 (기본값: -1, 무제한)
6. defaultCatalog - 기본 catalina 이름 (기본값: 설정없음)
7. ConnectionInitSqls - Connection 이 생성된 후 한번만 수행되는 SQL statements(구문), 여러개의 구문은 세미콜론(;) 으로 구분 (기본값: 설정없음)
8. connectionProperties - Connection 생성 시 Driver 에 전달할 드라이버별 속성값, 각 속성은 name=value 로 지정되며, 여러개의 속성은 세미콜론(;) 으로 구분 (기본값: 설정없음)
9. accessToUnderlyingConnectionAllowed - (기본연결) Underlying Connection 에 대한 접근 허용 여부 (기본값: false)
- 더 자세한 사항은 Commons DBCP 2 문서를 참조
[ 커스텀 Resource Factory 추가하기 ]
- 표준 Resource Factory 가 요구사항을 충족하지 않는경우, 자체적인 Factory 를 작성하여 Tomcat 에 통합한 다음 WEB_Application 의 <Context> 요소에서 해당 Factory 의 사용을 설정할 수 있다.
- 아래 예제에서는 위의 1. 일반 JavaBean 리소스 예제의 com.mycompany.MyBean 빈을 생성하는 방법을 알고 있다고 가정한다.
1. Resource Factory Class 작성
- javax.naming.spi.ObjectFactory 인터페이스 JNDI 서비스 공급자를 구현하는 Class를 작성해야 한다.
- (Factory 가 singleton="false" 로 구성되었다고 가정할 때) WEB_Application 이 해당 Factory 에 바인딩된 컨텍스트 항목에서 lookup() 을 호출 할 때마다 아래 argument 를 사용하여 getObjectInstance() 메소드가 호출된다. (singleton 의 기본값은 true)
1. Object obj
- (null 일 수 있음) 객체를 만들 때 사용할 수 있는 위치 또는 참조 정보가 포함된 객체.
- Tomcat 의 경우 obj 는 항상 Factory Class 의 클래스 이름과 반환할 객체를 생성할 때 사용할 구성 Properties (WEB_Application 의 경우엔 <Context>) 를 포함하는 javax.naming.Reference 타입의 객체이다.
2. Name name - 해당 Factory 의 nameCtx 에 상대적 바인딩 이름, 미설정 시 null
3. Context nameCtx - name 파라미터에 기술한 상대적인 Context, 기본 초기 상대적인 Context name 은 null 이다.
4. Hashtable environment - (null 일 수 있음) 이 객체를 만드는데 사용되는 환경, Tomcat Object Factory 에서 일반적으로 무시된다.
- MyBean 인스턴스를 생성하는 Resource Factory 를 만드려면 아래와 같이 만들 수 있다.
- 이 예제에서 이 Resource 를 구성하는 <Resource> 요소에 포함된 파라미터를 기반으로 com.mycompany.MyBean 클래스의 새 인스턴스를 무조건 생성하고 해당 속성을 채우고 있다. (아래 4) Tomcat Resource Factory 설정 참고)
- factory 파라미터는 구성중인 Bean 의 속성이 아닌 Factory Class 자체의 이름을 지정하는데 사용하므로 factory 라는 이름의 파라미터는 건너뛰어야 한다. (이 경우 com.mycompany.MyBeanFactory)
- ObjectFactory 에대한 자세한 내용은 JNDI Service Provider Interface 스펙 참고
- 이 Class 는 $CATALINA_HOME/lib 디렉토리에 있는 모든 JAR 파일이 포함된 ClassPath 로 컴파일 해야 한다.
- 완료되면 Factory Class와 해당 Bean Class 또는 JAR 파일을 $CATALINA_HOME/lib 에 위치해야 한다.
- 이렇게하면 필요한 Class 파일을 Catalina 내부 Resource 와 WEB_Application 에서 모두 사용할 수 있다.
2. 리소스 요구사항 선언
- 다음으로, WEB_Application 배포설명자(/WEB-INF/web.xml) 을 수정하여 해당 Bean 의 새로운 인스턴스를 요청할 JNDI 이름을 선언한다.
- 아래와 같이 <resource-env-ref> 요소를 사용하여 쉽게 설정 가능하다.
- 경고: WEB_Application 배포설명자에 대한 DTD 에서 요구하는 순서를 반드시 준수해야 한다. Servlet 스펙 문서 참고
3) 해당 Resource 를 사용하기 위한 Application 코드
- 해당 Resource 환경 참조의 일반적인 사용은 다음과 같다.
4) Tomcat Resource Factory 설정
- WEB_Application 에서 사용하기위해 <Context> 요소에 아래와 같이 Tomat 에 Resource Factory 를 설정할 수 있다.
- (bean/MyBeanFactory) Resource 이름은 WEB_Application 의 배포설명자(/WEB-INF/web.xml)에 지정된 값과 일치해야 한다.
- 새로운 Bean 을 리턴하기전에 bar 속성에 대해서 setBar(23) 을 호출하여 초기화 한다.
- (초기화 가능하지만) foo 속성은 초기화 하지 않기 때문에 Bean 생성자가 설정한 기본값을 가지고 있다.
- 또한 Application 개발자의 관점에서 Resource 환경 참조의 선언과 새로운 인스턴스를 요청하는데 사용된 코드는 1. 일반 JavaBean 리소스 예제에 사용된 접근 방식과 동일하다는 점에 유의해야 한다.
- 이는 JNDI 리소스를 사용하여 기능을 캡슐화 하는 이점 중 하나를 보여준다.
- 호환되는 API 를 유지하는 한 Resource 를 사용하여 Application 을 수정하지 않도고 기본 구현을 변경할 수 있다.
참고
- https://tomcat.apache.org/tomcat-11.0-doc/jndi-resources-howto.html
댓글
댓글 쓰기