클래스 동적 반영
본 장에는 웹 애플리케이션의 개발 속도 향상을 위한 Servlet Auto Reload 기능에 대해 설명한다.
1. 개요
일반적으로 Jakarta EE의 개발 Lifecycle은 다음과 같은 순서를 가지고 있다.
-
편집
-
빌드
-
배치
-
테스트
개발자들이 Jakarta EE 애플리케이션, 특히 웹 애플리케이션을 개발할 때 서블릿 등의 클래스를 수정하는 경우가 많다. 이러한 개발 과정을 신속하게 수행하기 위해 많은 노력들이 진행되어져 왔고, WebLogic 10.3에서는 FastSwap을 이용하여 이러한 재배포 과정을 줄이기 위한 기능을 제공하고 있다.
Java EE 5에서는 운영 중에 클래스 로더를 내리거나 인스턴스를 종료하지 않고도 클래스를 재정의하는 기능이 소개되었지만 선언된 필드와 메소드의 변경은 불가능한 제약사항을 가지고 있었다.
JEUS 6까지는 클래스를 수정한 뒤 수정된 클래스를 적용하려면 애플리케이션을 redeploy를 하거나, Auto Reload 기능을 통해서 주기적 체크 또는 요청에 따라 클래스 로더를 새로 생성하여 기존의 클래스 로더와 교체해야 했다. 그러나 redeploy할 경우 애플리케이션의 크기가 크면 상당한 시간이 걸리는 작업이고, Auto Reload 기능 또한 클래스 로더를 재작성하기 때문에 redeploy할 때만큼 많은 부하가 걸리고 있다.
이에 따라 JEUS 7부터는 기존의 클래스 로더의 리로딩이 필요한 동적 반영(Auto Reload)을 포함하여, JDK Instrumentation Package를 이용하여 클래스 로더의 리로딩 없이 Java 클래스의 재정의가 가능한 향상된 클래스 동적 반영(Auto Reload) 기능인 JEUS HotSwap 기능을 제공한다. 단, 현재는 웹 애플리케이션의 클래스들만 한정하여 지원한다.
본 장에서 설명하는 JEUS의 Auto Reload(JEUS HotSwap 기능의 활성/비활성) 기능은 운영 상황에서는 원하지 않는 부하를 발생시킬 수 있으므로, 개발 단계에서만 사용할 것을 권장한다. |
2. 기본 설정 및 동작
본 절에서는 JEUS의 Auto Reload 기능의 세부 설정 및 동작 방식을 설명한다.
2.1. 서버 설정
JEUS HotSwap 기능을 사용하려면 JEUS의 서버를 시작하기 전에 시스템 옵션을 설정해야 한다(JEUS HotSwap 기능이 없는 Auto Reload는 서버 시작 시 시스템 옵션 없이 동작한다).
시스템 옵션은 jeus.server.useHotSwapAgent이고, 설정하지 않을 경우 기본값이 false이므로 기능이 동작하지 않는다.
다음은 JEUS 시작 스크립트의 설정 예제이다.
-
startDomainAdminServer 스크립트의 설정 예제
Jeus HotSwap설정 : <startDomainAdminServer>... "${JAVA_HOME}/bin/java" $VM_OPTION $SESSION_MEM -Xbootclasspath/p:"${JEUS_HOME}/lib/system/extension.jar" ... -Djeus.server.useHotSwapAgent=true ... jeus.launcher.Launcher ${BOOT_PARAMETER} ...
-
startManagedServer 스크립트의 설정 예제
Jeus HotSwap 설정 : <startManagedServer>... "${JAVA_HOME}/bin/java" $VM_OPTION $SESSION_MEM -Xbootclasspath/p:"${JEUS_HOME}/lib/system/extension.jar" ... -Djeus.server.useHotSwapAgent=true ... jeus.launcher.ManagedServerLauncher ${BOOT_PARAMETER} ...
Auto Reload 기능을 설정하여 개발을 진행하고, 개발이 완료되면 위에서 설정한 옵션을 제거하여 운영할 때 이 기능을 사용하지 않도록 한다. |
2.2. 애플리케이션 설정
JEUS Auto Reload 기능을 사용하려면 JEUS의 jeus-web-dd.xml에 <auto-reload>를 설정해야 한다. 그리고 JEUS HotSwap 기능을 사용하기 위해서는 <auto-reload> 하위의 <use-jvm-hotswap> 설정을 해야 한다. 이 기능들은 디렉터리 형태(Exploded Directory)인 웹 애플리케이션의 클래스 파일의 변경만 가능하다. 개발 과정에서 변경된 클래스들의 동적 반영을 위한 것이기 때문에 이미 클래스들이 노출된 디렉터리에 한정한다. 즉, 웹 애플리케이션 디렉터리의 WEB-INF/classes 디렉터리 하위에 있는 클래스의 변경만 지원한다. JEUS의 Auto Reload는 처음 애플리케이션이 배포된 후 클래스 수정이 발생한 시점을 기준으로 동작한다.
jeus-web-dd.xml에 <auto-reload>를 다음과 같이 설정하고, Auto Reload의 모니터링 주기는 domain.xml을 사용하여 설정한다. domain.xml을 통한 Auto Reload의 모니터링 주기 설정에 대한 자세한 내용은 모니터링 설정을 참고한다.
<jeus-web-dd xmlns="http://www.tmaxsoft.com/xml/ns/jeus" version="9">
. . .
<auto-reload>
<enable-reload>true</enable-reload>
<use-jvm-hotswap>true</use-jvm-hotswap>
<check-on-demand>true</check-on-demand>
</auto-reload>
. . .
</jeus-web-dd>
세부 동작은 각 설정에 따라 다음과 같이 동작한다.
태그 | 설명 |
---|---|
<enable-reload> |
Auto Reload 기능의 사용여부를 결정한다. <enable-reload>는 true로 설정되어 있어야 한다. |
<use-jvm-hotswap> |
|
<check-on-demand> |
|
2.3. JEUS HotSwap으로 지원 가능한 애플리케이션 및 변환
JEUS HotSwap은 Exploded 디렉터리 내의 POJO(Plain Old Java Object), 웹 애플리케이션 클래스들을 지원한다.
JEUS HotSwap은 다음 타입의 변경을 지원한다.
-
정적 클래스 생성자 추가/제거
-
일반 클래스 생성자 추가/제거
-
정적 메소드 바디 수정
-
일반 메소드 바디 수정
다음은 JEUS HotSwap에서 지원하는 클래스 변환 리스트이다.
-
Java 클래스 Instance (non-astract)
Java Change Type 지원 여부 Notes 메소드 추가/제거
아니오
필드 추가/제거 (1)
아니오
메소드 바디 수정 (2)
예
생성자 추가/제거 (3)
예
필드 수정자(filed modifier) (4)
아니오
-
Static 클래스
Java Change Type 지원 여부 Notes 메소드 추가/제거
아니오
메소드 바디 수정
예
-
Abstract Java 클래스
Java Change Type 지원 여부 Notes abstract 메소드 추가/제거
아니오
Java 클래스 Instance의 1-4 변환
예
-
final Java 클래스
Java Change Type 지원 여부 Notes Java 클래스 Instance의 1-4 변환
예
-
final Java 메소드
Java Change Type 지원 여부 Notes Java 클래스 Instance의 1-4 변환
예
-
final Java 필드
Java Change Type 지원 여부 Notes Java 클래스 Instance의 1-4 변환
예
-
Enum
Java Change Type 지원 여부 Notes 상수 추가/제거
아니오
메소드 추가/제거
아니오
-
익명 내부 클래스
Java Change Type 지원 여부 Notes 필드 추가/제거
유효하지 않음
Java 언어에서 제공되지 않는다.
메소드 추가/제거
아니오
-
정적 내부 클래스
Java Change Type 지원 여부 Notes Java 클래스 Instance의 1-4 변환
예
-
일반 내부 클래스
Java Change Type 지원 여부 Notes Java 클래스 Instance의 1-4 변환
예
-
Java 인터페이스
Java Change Type 지원 여부 Notes 메소드 추가
아니오
-
Java Reflection
Java Change Type 지원 여부 Notes 존재하는 필드/메소드 접근
예
새로운 메소드 접근
아니오
새로운 메소드는 Reflection을 이용하면 보이지 않는다.
새로운 필드 접근
아니오
새로운 필드는 Reflection을 이용하면 보이지 않는다.
-
Annotations on Classes
Java Change Type 지원 여부 Notes 메소드, 속성 Annotion 추가/제거
아니오
-
Annotation 타입
Java Change Type 지원 여부 Notes 메소드, 속성 Annotion 추가/제거
아니오
-
Exception 클래스
Java Change Type 지원 여부 Notes Java 클래스 Instance의 1-4 변환
예
-
EJB 인터페이스
Java Change Type 지원 여부 Notes 메소드 추가/제거
아니오
Reflection과 연관되어 있는 EJB 인터페이스의 변환은 지원되지 않는다.
-
EJB 3.0 Session/MDB, 구현 클래스
Java Change Type 지원 여부 Notes 메소드, 필드 추가/제거
아니오
EJB에 의해 참조되는 클래스 중 지원되는 클래스에 한해 변환이 지원된다.
-
EJB 2.X Entity Bean
Java Change Type 지원 여부 Notes 메소드, 필드 추가/제거
아니오
EJB에 의해 참조되는 클래스 중 지원되는 클래스에 한해 변환이 지원된다.
-
EJB Interceptors
Java Change Type 지원 여부 Notes 메소드, 필드 추가/제거
아니오
EJB에 의해 참조되는 클래스 중 지원되는 클래스에 한해 변환이 지원된다.
2.4. JEUS HotSwap 제약 사항
JEUS HotSwap으로 지원되는 변환과 불가능한 변환이 있다. 지원이 불가능한 변환이 있는 경우 JDK에서 UnsupportedOperationException이 발생하고, JEUS는 이를 받아서 다음와 같은 로그를 남긴다. 이 경우 애플리케이션의 동적 재정의는 반영되지 않지만 JEUS의 Auto Reloading 동작은 계속된다.
Retransforming all modified classes in the servlet context [AAA] failed.
지원이 불가능한 변환들을 정리하면 다음과 같다.
-
Java Reflection 결과는 새롭게 변경된 필드와 메소드를 포함하지 못한다. 따라서 수정된 클래스의 API의 Reflection을 사용하는 경우 예상치 못한 동작이 나타날 수 있다.
-
이미 존재하는 클래스의 계층 변경은 지원되지 않는다. 예를 들어 클래스의 인터페이스를 구현한 리스트의 변경이나 클래스의 superclass를 변경하는 경우는 지원되지 않는다.
-
Java Annotation의 추가 및 제거는 지원되지 않는다. 이는 위에 언급한 Reflection의 이유 때문이다.
-
EJB 인터페이스의 메소드에 대한 추가 및 제거는 지원되지 않는다. EJB 편집은 변경에 대한 Reflect가 필요하기 때문이다.
-
Enums의 상수를 추가하거나 제거하는 경우는 지원되지 않는다.
-
finalize 메소드에 대한 추가나 제거의 경우는 지원되지 않는다.