10장. EJB3 서브시스템

Name

Date

Reason For Changes

Version

오픈나루

2013/11

Initial Version

1.0

전준식, jjeon@opennaru.com

2018/02

Second Version

2.0

EJB(Enterprise JavaBeans) 3는 Java EE의 분산 컴포넌트 기술이다. 예전에는 몹시 어렵고 복잡한 기술이었지만, 이젠 쉽게 사용할 수 있는 기술이 되었다. 이번 장에서는 EJB 3 기능을 제공하는 JBoss EAP 6의 서브시스템과 EJB의 여러 가지 종류와 특징에 대해서 설명한다.

10-1.EJB3 서브시스템

EJB(Enterprise JavaBeans) 3.1은 Enterprise Bean라는 서버 측 컴포넌트를 사용하여 분산 Java EE 애플리케이션을 개발하기 위한 표준 API이다. Enterprise Bean은 컴포넌트화하여 재사용하기 쉽도록 애플리케이션의 비즈니스 로직을 구현한다. EJB 3.1은 Java EE 표준 JSR-318에서 정의되어 있다.

JBoss EAP 6는 EJB 3.1 표준을 사용하여 개발한 애플리케이션을 완벽히 지원한다. EJB 컨테이너는 JBoss EJB 3 커뮤니티 프로젝트(http://www.jboss.org/ejb3)를 사용하여 구현하였다.

이전 버전인 Java EE 5에서 가장 큰 변화는 DI(Dependency Injection)나 POJO(Plain Old Java Object), 어노테이션과 같은 기존의 J2EE에 없었던 기술을 도입한 것이 EJB 3.0이었다. Java EE 6에 포함된 EJB 3.1에서도 이 흐름을 이어가고 있다.

EJB는 Java 엔터프라이즈 컴포넌트의 표준이다. 하지만 EJB는 ‘복잡하고 다루기 힘든 기술 '이라는 인식을 가지고 있는 개발자들이 많다. 물론 기존의 EJB 2.x까지는 바로 그런 기술이었다. 사용하려면 복잡한 XML 설정 파일들을 여러 개 작성해야 하고, 많은 규칙을 기억해야 해서 간단한 작업조차 마음대로 하기 힘든 것이 바로 EJB였다.

그러나 이제는 다르다. 2006년 초에 릴리즈된 새로운 버전 ‘EJB 3.0 '에는 기존의 EJB의 복잡성을 없애기 위한 대대적인 개선이 이루어졌다. ‘편리한 사용’을 가장 중시하여 EJB를 사용하는 개발자의 어려움들을 크게 개선한 것이다. 따라서 이제는 EJB가 ‘사용할 수 있는 기술’로 새롭게 만들어진 만큼 다시 많은 관심을 기울일만한 기술이다.

사실 EJB 대신에 개발자들은 JBoss Hibernate를 많이 사용했다. EJB 3 버전은 JBoss Hibernate를 표준화한 기존 버전과는 다른 완전히 새로운 O/R 맵핑 프레임로 JPA(Java Persistence API)가 채택되었다.

Java EE 6에서는 JPA를 EJB와 다른 새로운 표준으로 나누어 ‘JPA 2.0’이 되었다. 즉, EJB Entity Beans가 없어지고 JPA Entities가 이를 대신하게 되었다.

EJB 3에서는 다음과 같은 기능들을 지원한다.

  • 세션 빈(Session Bean)

  • 메시지 드리븐빈(Message Driven Bean)

  • 인터페이스 없는 뷰(No-interface view)

  • 로컬 인터페이스(Local Interface)

  • 원격 인터페이스(Remote Interface)

  • JAX-WS 웹서비스

  • JAX-RS 웹서비스

  • 타이머 서비스

  • 비동기 호출

  • 인터셉터

  • RMI / IIOP 상호 운용성

  • 트랜잭션 지원

  • 보안

EJB 3.1에서는 다음과 같은 기능이 추가되었다.

  • 로컬 인터페이스 생략 가능

  • WAR내에 패키징 가능

  • Singleton EJB

  • 타이머 서비스 강화

  • 비동기 실행

10-2.EJB 의 이해

EJB란

EJB는 분산, 트랜잭션, 보안 등의 서비스를 제공하는 서버 사이드 컴포넌트이다. EJB 표준은 개발 순서가 복잡하여 불편한 점이 많았지만, EJB 3. 0에서는 배포 디스크립터 대신 어노테이션을 이용할 수 있게 되어 개발이 쉬워지게 되었다. 그리고 EJB 3.1에서는 로컬 세션 빈에 대해서는 인터페이스도 필요하지 않고, WAR 아카이브에 EJB를 포함할 수가 있어 개발자에게 사용하기 쉬운 표준으로 진화하고 있다.

JBoss EJB 3 구현

EJB 3 서브시스템은, JBoss EAP 6의 EJB 3를 구현하는 컴포넌트로, EJB 3.1을 완벽히 지원한다. 이 서브시스템은 표준적인 EJB3 컨테이너로의 기능과 인스턴스 풀, 스레드 풀 등의 JBoss EAP가 EJB를 관리하기 위한 기능을 제공한다. 또, JBoss에 특화된 어노테이션이나 배포 디스크립터를 사용할 수 있고, EJB 컴퍼넌트가 JBoss EAP에서 제공하는 클러스터링 기능 등 각종 서비스를 이용할 수 있도록 하고 있다. EJB의 인스턴스 풀, 스레드 풀 등을 지정할 수 있기 때문에 EJB의 튜닝에 유용하게 사용된다.

10-3.EJB 3.1의 새로운 기능

EJB 3.1 Lite

EJB 3.1 Lite는 EJB 3.1의 부분집합으로 웹 프로파일에서도 사용할 수 있다. EJB 3.1의 대부분의 기능을 제공하고 있지만, 다음 기능을 제공하지 않는다.

  • 원격 인터페이스

  • RMI와 IIOP 상호 운용성

  • JAX-WS 웹서비스 엔드포인트

  • EJB 타이머 서비스(@Schedule, @Timeout)

  • 비동기 세션 빈 호출(@Asynchronous)

  • 메시지 드리븐 빈

싱글 톤

싱글 톤(singleton) 단 하나의 인스턴스 만 실행되는 새로운 유형의 세션 빈이다. 빈이 실행되는 JVM당 하나만 생성된다. 이러한 특징을 잘 활용할 수 있는 곳을 예를 들면, 인스턴스에 1개만 있어야 하는 캐시와 같은 것이 있다.

EJB Timer

EJB 2.1 이후 EJB는 타이머 메커니즘을 가지고 있다. 지정한 시간 간격으로 실행되는 것이고, 설정이 매우 복잡하다. EJB 3.0에서는 상황이 조금 개선되었지만, 타이머를 사용하려면 절차적으로 선언하여야 하고, 간격(interval)을 기반으로 해서 복잡한 로직에는 적용하기 어려웠다. 예를 들어, 만약 매주 일요일 자정마다 어떤 작업을 하는 것을 프로그래밍하려면, 많은 작업을 해야 했다. EJB 3.1은 Quartz와 Flux와 같은 다양한 다른 스케줄러들이 리눅스의 CRONTAB 작업과 같이 이런 시간을 지정하는 유연한 타이머 서비스를 제공하여 많이 개선했다. CRONTAB과 같은 일정을 포함하여, 간단한 스케줄링의 요구사항들이 반영되어 있어 EJB 3.1의 Timer는 매우 좋은 솔루션이다.

다음과 같이 특정일에 실행되는 스케쥴을 Java 어노테이션을 사용하여 지정할 수 있다.

@Schedule( ... dayOfMonth="1", month="1", year="2014")

Interface없는 빈

EJB 2.x 이전에 하나의 EJB를 생성하기 위해 빈을 구현하는 소스파일뿐만 아니라 비즈니스 인터페이스, 홈 인터페이스, XML로 작성된 디플로이먼트 디스크립터가 필요했다.

EJB 3.0에서는 어노테이션으로 EJB의 메타 데이터를 설정할 수 있기 때문에 디플로이먼트 디스크립터를 작성할 필요가 없다. 또 홈 인터페이스가 없어졌고 빈 구현 소스파일과 비즈니스 인터페이스만으로 EJB를 만들 수 있게 되었다. 빈 구현 파일도 기존에 필요했던 콜백 메서드 작성 등이 필요 없어 매우 쉽게 EJB를 만들 수 있게 되었다.

EJB 3.1에서도 이 흐름을 이어받아 로컬에서 접근하는 EJB는 로컬 비즈니스 인터페이스를 생략할 수 있게 되었다. 이렇게 하면 로컬에서만 사용되는 EJB는 빈을 구현하는 소스 파일 하나로만 만들 수 있어, EJB 2.x의 시대와 비교하면 엄청나게 단순화되었다.

배포의 단순화

기존의 EJB는 ‘EJB jar 파일’이라는 하나의 jar 파일로 저장하여야만 했지만, EJB 3.1에서는 @Stateless 등 EJB 관련 ‘주석’을 붙인 빈 클래스를 클래스 패스에 놓기만 하면 자동으로 EJB로 인식하게 된다. 또 웹 애플리케이션의 아카이브 파일인 WAR 파일의 ‘WEB-INF/classes’ 에 EJB 구현 클래스 파일을 놓으면 EJB로 사용할 수 있기 때문에 개발 생산성이 매우 높아졌다.

기존의 애플리케이션은 EJB를 사용하기 위해서는, EJB를 EJB-jar 파일에 저장하고 웹 애플리케이션과 관련된 부분은 WAR 파일에 저장한 후 그것을 EAR 파일로 묶어야만 하는 조금 귀찮은 과정이 많이 필요했지만, EJB 3.1에서는 하나의 WAR 아카이브에 EJB를 사용하는 웹 애플리케이션을 만들 수 있게 되었다. 정말 간편해졌다.

EJB에서 사용하는 디스크립터 파일도 WEB-INF/ejb-jar.xml 파일에 정의하여 사용할 수 있다. WAR 파일로 패키지된 빈은 하나의 네임 스페이스를 공유하고 WAR 일부가 된다. WEB-INF/lib 디렉터리에 .jar로 패키징하는 것도 WEB-INF/classes 디렉터리에 클래스를 두는 것과 같다. 새로운 표준 중 또 다른 형태가 EJB Lite이다. 최근의 많은 애플리케이션은 EJB 의 많은 기능을 필요로 하지는 않는다. EJB Lite는 EJB 중에서도 가장 많이 사용하는 세션 빈을 중심으로 한 EJB 3의 부분 집합이다. EJB Lite는 Stateless, Stateful세션 빈, Singleton세션 빈을 지원한다. 빈은 로컬 interface 또는 interface없이 뷰를 만들 수 있다. 이들은 인터셉터와 트랜잭션, 보안과 같은 컨테이너가 제공하는 서비스를 사용할 수 있다.

10-4.EJB 컨테이너

엔터프라이즈 시스템은 여러 대의 서버를 네트워크상에서 연결하어 시스템을 구성하는 것이 일반적이다. 분산된 시스템에서 동작하는 애플리케이션은 비즈니스 로직뿐만이 아니라 네트워크 통신, 스레드 관리, 메모리 관리, 보안, 트랜잭션, 확장성 등의 기능을 제공할 수 있어야 한다. 또한, 엔터프라이즈 시스템에서는 대규모로 애플리케이션이 개발되기 때문에, 프로그램 이식성, 유지 보수성, 개발 생산성을 높이는 일도 매우 중요하다. EJB는 업무 애플리케이션을 개발하는 개발자의 엔터프라이즈 시스템의 높은 수준의 요구사항을 충족시키면서, 분산된 서버에서 애플리케이션을 효율적으로 개발할 수 있어야 하는 요구사항을 만족하게 하기 위한 엔터프라이즈 전용 표준 컴포넌트이다.

The composition of an EJBHome proxy in JBoss.

그림 1. EJB 컨테이너

EJB 컨테이너는 빈를 분산 컴포넌트로서 동작시키기 위한 트랜잭션이나 보안 등의 각종 서비스를 제공하는 실행 환경이다. EJB 인스턴스의 생성이나 제거 등의 라이프 사이클도 EJB 컨테이너에 의해 관리된다. EJB 컨테이너는 EJB를 호출할 때, 다른 스레드가 그 EJB 인스턴스에 동시에 접근하지 않도록 보장한다. 즉, 개발자가 빈를 구현할 때 스레드 세이프하게 만들 필요가 없고 EJB 컨테이너가 관리한다. 분산 애플리케이션 개발에서 기술적으로 어려운 부분을 EJB 컨테이너가 담당해 처리하기 때문에, 개발자는 비즈니스 로직 개발에만 집중할 수 있게 된다.

10-5.EJB 종류

EJB 3는 세션 빈(Session Bean)과 메시지 드리븐 빈(Message-Driven Bean)를 지원한다. 이제 엔티티 빈은 없다. 세션 빈은 비즈니스 로직을 구현하기 위한 빈이며 클라이언트는 RPC(Remote Procedure Call)와 같이 다른 서버에서 컴포넌트를 네트워크를 통해 호출할 수 있다. 메시지 드리븐 빈은 JMS 메시지를 수신했을 때 시작되는 빈으로 비동기 처리에 사용된다. 세션 빈은 Stateless, Stateful, Singleton의 세가지 종류가 있다. 프로그래밍할 때 javax.ejb 패키지의 어노테이션을 추가하는 것으로 EJB 종류를 구분한다. 예를 들어, Stateless 세션 빈이면, @javax.ejb.Stateless라는 어노테이션을 추가한다.

EJB 종류 어노테이션 설명

세션 빈

Stateless 세션 빈

@Stateless

Stateless 세션 빈은 가장 간단하고 많이 사용되는 세션 빈이다. 클라이언트에 비즈니스 메서드를 제공하지만, 메서드 호출간 상태를 유지하지 않는다. 상태가 없어서 애플리케이션 서버는 각 메서드 호출이 같은 인스턴스에서 실행되는지 확인해야 한다

Stateful 세션 빈

@Stateful

Stateful 세션 빈은 서버 측에서 상태를 보관하고 유지하는 세션 빈이다. 접속한 클라이언트 전용 EJB 인스턴스를 할당할 수 있기 때문에, 메서드 호출할 때 빈 인스턴스 내에서 상태 정보를 유지하는 것이 가능하다.

Singleton 세션 빈

@Singleton

싱글톤 세션 빈은 서버 측에서 상태를 보관하고 유지하는 빈이다. 싱글톤 세션 빈은 서버 측에서 1개의 인스턴스만 실행되어 여러 대의 클라이언트의 정보를 공유할 때 유용하다.

메시지 드리븐 빈

@MessageDriven

메시지 드리븐 빈(MDB)은 애플리케이션 개발에 이벤트 모델을 사용한다. MDB는 클라이언트 코드에서 JMS(Java Messaging Service) 서버에 메시지를 전송하면, 메시지를 수신하여 실행된다.

다음은 간단한 EJB 3 예제 코드이다. 간단히 Java 소스에 @Stateless 어노테이션을 붙이면 Stateless 세션 빈이 된다.

@Stateless
public class CustomerService {

  @PersistenceContext
  private EntityManager entityManager;

  public void addCustomer(Customer customer) {
    entityManager.persist(customer);
  }
}

위의 코드에서는 addCustomer라는 메서드에서 Customer라는 객체를 JPA O/R 맵핑을 사용하여 저장한다. CustomerService라는 EJB는 위의 소스 파일 하나만 작성하면 된다. 기존 버전처럼 XML 디스크립터 파일들을 작성할 필요가 없다. 또, EJB가 영속성 컨텍스트를 관리하고 있고, addCustomer() 메서드는 트랜잭션을 지원하고 스레드 세이프하다.

10-6.EJB 3 서브시스템 관리 항목

EJB 3 컨테이너에서 관리하는 설정항목들은 다음 표와 같다. 관리 콘솔에서 ‘Profile’ ‘Container’ ‘EJB3’에서 설정할 수 있으며, CLI에서는 /subsystem=ejb3 에서 아래 항목들을 설정할 수 있다.

항목 설명 기본값

EJB3 컨테이너 설정

default-slsb-instance-pool

Stateless 세션 빈의 인스턴스 풀 개수 기본값

slsb-strict-max-pool

default-mdb-instance-pool

메시지 드리븐 빈 인스턴스 풀의 기본값

mdb-strict-max-pool

default-stateful-bean-access-timeout

Stateful 세션 빈의 기본 타임아웃 값

5000 ms

default-singleton-bean-access-timeout

싱글톤 빈의 기본 타임아웃 값

5000 ms

default-sfsb-cache

Stateful 세션 빈이 사용할 캐시 이름

simple

default-resource-adapter-name

자원 어댑터(Resource Adapter)의 이름

hornet-ra

Timer 서비스

path

데이터를 저장하는 디렉터리

timer-service-data

relative-to

path의 기본 경로

jboss.server.data.dir

thread-pool-name

스레드 풀 이름

default

Async 서비스

thread-pool-name

스레드 풀 이름

default

Remote 서비스

thread-pool-name

스레드 풀 이름

default

EJB 3의 인스턴스 풀이나 스레드 풀 등은 EJB를 사용하는 애플리케이션을 튜닝할 때 활용할 수 있는 값들이다.