본문으로 건너뛰기

6.3 배포 시 클래스로딩

클래스 로더의 이해

클래스 로더는 그 이름에서 알 수 있듯이 클래스를 로드하는 것이다. 대개의 자바 개발자는 특별히 의식하지 않고 클래스를 사용하고 있지만, 클래스는 사용되기 전에 반드시 클래스 로더를 통해 JVM(Java Virtual Machine)의 메모리 영역에 로드한된다. 올바른 Java EE 패키징을 위해서는 클래스 로더에 대한 지식이 필수적이다.

클래스 로더를 이해하는 데 가장 중요한 개념은 ‘위임 모델’이다. 아래의 그림에서 자바 가상 머신의 클래스 로더 구조를 살펴보자.

그림 3. Java VM의 클래스 로더

클래스 로더는 필요시 부모 클래스 로더에 클래스의 로드를 부탁하는 구조, 즉 맡기는(위임) 것이다. 예를 들어, 시스템 클래스 로더가 클래스를 로드하려고 할 때 시스템 클래스 로더는 자신의 로컬 클래스 패스, 즉 환경변수 CLASSPATH에서 찾기 전에 먼저 부모인 확장 클래스 로더에 클래스의 로드를 요청하게 된다. 마찬가지로 확장 클래스 로더도 먼저 부모 클래스 로더인 부트 스트랩 클래스 로더에 클래스의 로드를 위임하게 된다. 부모 클래스 로더에서 클래스가 발견된 경우에 거기서 클래스를 로딩하여 종료하게 된다. 부모에 클래스가 없을 때 비로소 자신의 로컬 클래스 패스를 찾게 되고 클래스를 로드하게 된다. 위임 모델에서 중요한 것은 자식이 먼저하는 것이 아니라 먼저 부모에게 위임하는 것이다.

배포시 클래스 로딩

클래스 로딩을 위해 JBoss EAP에서 배포는 모두 모듈로 처리된다. 이러한 배포 형식의 모듈을 다이내믹 모듈이라고 한다. 클래스 로딩의 작동 방식은 배포 유형에 따라 다르다.

배포 방식설명
WAR 패키지WAR 패키지가 하나의 모듈로 간주된다. WEB-INF/lib 디렉터리의 파일들은 WEB-INF/classes 디렉터리에 있는 클래스와 동일하게 처리된다. WAR로 패키지 된 클래스들은 동일한 클래스 로더에 로드된다.
EAR 패키지EAR 배포는 여러 개의 모듈로 구성된다. 이 모듈은 다음 규칙에 따라 정의된다. * EAR의 lib/ 디렉터리는 부모 모듈이다. * 또 EAR의 각 WAR 배포는 하나의 모듈이다. * 마찬가지로 EAR 내의 EJB JAR 배포도 하나의 모듈이다. EAR의 WAR, JAR 배포와 같은 서브 배포 모듈은 자동으로 부모 모듈에 의존하지만 하위 배포끼리 자동으로 의존성을 갖지는 않는다. 이것은 하위 배포 단절(subdeployment isolation)이라고 한다. 서브 배포 모듈 간의 명시적 종속 관계는 다른 모듈과 같은 방법으로 추가 할 수 있다.
표 3. WAR 패키지와 EAR 패키지의 동작 방식

클래스로딩의 우선순위

JBoss EAP 6 모듈 클래스 로더는 우선순위 구조를 이용하여 클래스 로딩 충돌이 발생하지 않도록 한다.

배포시 패키지와 클래스들의 리스트는 각각의 배포와 해당 종속성에 의해 생성된다. 이 목록은 클래스 로딩의 우선순위 규칙에 따라 순서대로 나열된다. 런타임에 클래스를 로드하면 클래스 로더는이 목록을 검색하여 최초로 일치하는 것을 로드한다. 이렇게 하면 배포 클래스 경로에 동일한 클래스나 패키지의 여러 복사본이 충돌하지 않게 된다.

클래스 로더는 위에서 아래로(내림차순) 클래스를 로드 한다.

우선순위의존성 분류설명
. 암시적 의존성Java EE API 들은 JBoss EAP 6가 자동으로 추가한 의존성이다. 이 의존성은 일반적인 기능 및 JBoss EAP 6의 API가 포함되어 있기 때문에 우선순위가 가장 높다.
. 명시적 의존성애플리케이션 설정에서 수동으로 추가되는 의존성이다. 이러한 의존성은 애플리케이션의 MANIFEST.MF 파일이나 새로운 옵션으로 추가된 JBoss 배포 디스크립터 jboss-deployment-structure.xml 파일을 사용하여 추가 가능하다.. 로컬 리소스
배포 애플리케이션 내에 패키지된 클래스 파일. 예를 들면 WAR 파일의 WEB-INF/classes나 WEB-INF/lib 디렉터리의 JAR 파일들. 배포 간의 의존성EAR 배포 애플리케이션에 있는 다른 배포와의 의존성. 여기에는 EAR의 lib 디렉터리에 있는 클래스 나 다른 EJB jar에 정의된 클래스가 포함될 수 있다.

표 4. 클래스 로딩의 우선순위

EAR 배포와 클래스로딩

엔터프라이즈 아카이브(EAR)는 JAR 또는 WAR 배포와 같이 단일 모듈로 로드하지 않고, 독립적인 여러 모듈로 로드한다.

다음과 같은 규칙으로 EAR의 모듈이 로드된다.

  • 각 WAR 및 EJB JAR subdeployments는 모듈이다.
  • EAR 아카이브 루트에 있는 lib/ 디렉터리의 내용은 모듈이다. 이것을 부모 모듈이라고 한다.
  • 모듈은 다른 모듈과 같이 암시적 의존성이 있다.
  • WAR의 subdeployments는 상위 모듈 및 EJB JAR 파일의 subdeployments에 암시적 종속성이 있다.
  • EJB JAR의 subdeployments는 상위 모듈과 다른 EJB JAR 파일의 subdeployments에 암시적 종속성이 있다.

💡 TIP

다른 모듈과 마찬가지로 subdeployment는 다른 subdeployment에 대해 명시적 종속 관계를 설정할 수 있다.

설정 방법은 다음과 같다. 기본값은 false이다.

<subsystem xmlns="urn:jboss:domain:ee:1.1">
<ear-subdeployments-isolated>true</ear-subdeployments-isolated>
<spec-descriptor-property-replacement>false</spec-descriptor-property-replacement>
<jboss-descriptor-property-replacement>true</jboss-descriptor-property-replacement>
</subsystem>

JBoss EAP 6는 기본적으로 subdeployment는 클래스 로더 분리(isolation)를 하지 않아서 암시적 의존성이 있다. 간단히 말하면 EAR에 있는 WAR와 EJB JAR들은 서로 참조할 수 있다. 하지만 Java EE 스펙에서는 서로 참조하지 못하도록 규정하고 있다. 엄격한 Java EE 호환성이 필요한 경우에 설정을 변경하여 사용한다. Java EE 6 표준에서는 포터블 애플리케이션 종속성을 명시적으로 각 subdeployment의 MANIFEST.MF 파일에서 클래스 패스로 선언하지 않는 한 서로 액세스 할 수 있는 subdeployments에 의존하지 않도록 규정하고 있다.

일반적으로 서로 참조하도록 구성하는 경우가 많아, 기본 옵션을 그대로 사용한다.

다이내믹 모듈의 모듈 이름

모든 모듈은 JBoss EAP 6가 모듈로 로드한 다음과 같은 규칙에 따라 이름이 지정된다.

배포 방식설명
WAR 패키지의 모듈 이름 지정deployment.DEPLOYMENT_NAME 예를 들어, inventory.war 와 store.jar 파일을 배포하게 되면 모듈의 이름은 deployment.inventory.war 과 deployment.store.jar가 된다.
EAR 패키지의 모듈 이름 지정deployment.EAR_NAME.SUBDEPLOYMENT_NAME 예를 들어, accounts.ear 에 있는 reports.war 하위 배포 모듈 이름은 deployment.accounting.ear.reports.war 이 된다.

표 5. 다이내믹 모듈의 모듈 이름 지정

jboss-deployment-structure.xml 파일

jboss-deployment-structure.xml는 JBoss EAP 6의 새로운 배포 디스크립터이다. 이 배포 디스크립터는 배포 시 클래스 로딩을 제어할 수 있도록 한다.

이 배포 디스크립터 XML 스키마는 $JBOSS_HOME/docs/schema/jboss-deployment-structure-1_0.xsd 에 있다.