IBM®
메인 컨텐츠로 가기
    Korea [국가변경]    이용약관
 
 
   
        제품    서비스 & 솔루션    고객지원 & 다운로드    회원 서비스    
메인 컨텐츠로 가기

한국 developerWorks  >  SOA와 웹서비스 | 오픈 소스  >

OSGi와 스프링, Part 1: 아파치 펠릭스를 사용해 OSGi 번들을 개발하고 배포하기

개발자가 자바 컴포넌트를 구축하고 오픈 소스 OSGi 컨테이너인 아파치 펠릭스를 사용해 OSGi 번들로 패키지하는 방법을 단계별로 안내하기

developerWorks
문서 옵션

JavaScript가 필요한 문서 옵션은 디스플레이되지 않습니다.

토론

샘플 코드

영어원문

영어원문


제안 및 의견
피드백

난이도 : 중급

Rajeev Hathi, 선임 소프트웨어 컨설턴트
Naveen Balani, 소프트웨어 아키텍트, IBM

옮긴이: 박찬욱 dwkorea@kr.ibm.com

2008 년 12 월 02 일

OSGi(Open Service Gateway initiative) 번들로 자바(Java™) 클래스 컴포넌트를 개발하고, 구축하고, 패키지해 아파치 펠릭스(Felix) 런타임 환경에 배포해 보겠습니다. 그러고 나서 펠릭스 셸 커맨드를 사용해 번들을 시작하고, 정지하며, 동적으로 갱신해 보겠습니다.

소개

연재의 Part 1인 이번 글에서는 클라이언트 측과 서버 측 컴포넌트로 사용하는 주문 애플리케이션을 개발한다. 그러고 나서 이 컴포넌트들을 OSGi 번들로 패키지한다. 클라이언트는 주문을 처리해주는 서비스 컴포넌트를 호출한다. 서비스 컴포넌트는 주문을 처리해 주문 ID를 출력하는 메서드를 갖고 있다. 이 글을 읽은 후에는 OSGi 번들로 자바 컴포넌트 클래스를 구축하고, 패키지해주는 아파치 펠릭스의 개념과 특징을 적용할 수 있을 것이다.

시스템 요구사항

이번 글의 예제를 실행하려면 다음 소프트웨어가 컴퓨터에 설치, 설정되어 있는지를 확인해야 한다.

  • 자바 5 이상
  • 앤트(Ant) 빌드 도구
  • 아파치 펠릭스 바이너리 배포판 1.0.4

다음으로 환경 변수를 설정하자(예제를 위해 ANT_HOME=C:\apache-ant-1.7.0로 설정하자).

  • JAVA_HOME(자바에 대한 설정)
  • ANT_HOME(앤트에 대한 설정)

다음으로 PATH 환경 변수를 더하자.

  • JAVA_HOME\bin
  • ANT_HOME\bin



위로


OSGi

OSGi는 여러 가지 동적인 방법으로 자바 애플리케이션의 모듈화 방식(modularity)을 정의하고, 정보를 주고 받는 명세다. 전통적으로 자바 애플리케이션은 JAR 번들로 모듈화를 했다. 그러나 JAR 파일을 단위로 개발하기에는 다음과 같은 제약 사항이 있다.

  • JAR 번들은 클래스 패스 환경 변수를 통해 찾으므로, JAR 의존성을 관리할 견고한 프레임워크를 제공하지 못한다.
  • JAR 번들은 버전을 적용할 수 없다. 그러므로 생성하거나 수정한 JAR 번들의 이력을 추적할 수 없다.
  • 코드를 바꿀 때마다 런타임에 동적으로 JAR 파일을 갱신하는 프레임워크가 없다.

OSGi는 자바의 모듈화 시스템(modular system)을 재정의하기 때문에, OSGi 프레임워크를 사용하면 위 논쟁거리들을 해결할 수 있다. OSGi 기반 시스템은 전통적인 JAR 모듈에 비해 다음과 같은 장점이 있다.

  • OSGi는 번들을 서비스로 공개(publish)하고, 다른 번들이 사용할 수 있도록 노출(export)할 수 있는 견고한 통합 환경을 제공한다.
  • OSGi는 새로운 배포 때마다 번들의 버전 처리(versioning)를 제공한다. 그러므로 번들 생성과 변화에 대한 이력을 추적할 수 있다.
  • OSGi를 사용하면 코드가 변경될 때마다 런타임에 동적으로 번들을 갱신할 수 있다.

현재 잘 알려진 OSGi 구현체로는 세 개가 있다.

  • 이쿼녹스(Equinox)
  • Knopflerfish
  • 펠릭스(Felix)

이 글에서는 OSGi 컨테이너로 펠릭스를 사용해 설명한다. 이번 글 연재에서는 다음 주제를 다룬다.

  • Part 1은 OSGi API를 사용한 컴포넌트 개발을 설명한다.
  • Part 2는 OSGi 컨테이너에서 스프링 사용을 통해 얻는 기능과 컴포넌트 클래스들의 OSGi API 의존성을 제거해 컴포넌트 클래스들을 POJO(Plain Old Java Objects)로 만들어볼 것이다. 우리는 컴포넌트 클래스에 있는 비즈니스 메서드를 작성하는 데만 집중하면 되고, 컴포넌트의 생명주기는 스프링 환경설정 파일에 의해 제어 받는 장점이 있다.



위로


주문 애플리케이션

펠릭스 기반 OSGi 프레임워크를 사용해 주문 애플리케이션 번들을 만드는 방법을 살펴보자. 애플리케이션은 컴포넌트 두 개를 가지고 있다. OrderClient.java(클라이언트 측)와 OrderService.java(서버 측)다. 클라이언트 컴포넌트는 client.jar로 번들을 묶었고, 서버 컴포넌트는 order.jar로 번들을 묶었다.


Listing 1. 클라이언트 컴포넌트 OrderClient
public class OrderClient implements BundleActivator {

  private ServiceTracker orderTracker;
  private OrderService orderService;

  public void setService(OrderService orderService) {
    this.orderService = orderService;
  }

  public void removeService() {
    this.orderService = null;
  }

  public void start(BundleContext context) throws Exception {
   orderTracker = 
   new ServiceTracker(context, OrderService.class.getName(), null);
   orderTracker.open();
   OrderService order = (OrderService) orderTracker.getService();

   if (order == null) {
     System.out.println("Order service not available");
   } else {
     order.processOrder();
   }
  }

  public void stop(BundleContext context) {
   System.out.println("Bundle stopped");
   orderTracker.close();
 }

}

Listing 1에서 볼 수 있는 것처럼, OrderClient는 client.jar가 시작될 때 orderID를 출력하는 OrderService 컴포넌트의 processOrder 메서드를 호출한다. 이 클래스는 BundleActivator 인터페이스를 구현하며, 이 인터페이스는 start()stop() 두 개의 콜백 메서드를 가지고 있다. 펠릭스 컨테이너는 클라이언트 번들이 시작할 때와 정지할 때 구현한 start()stop() 메서드를 호출한다.

start() 메서드를 좀 더 자세히 살펴보자. start() 메서드는 먼저 ServiceTracker 클래스의 참조를 받아온다. 이 클래스는 팩토리 클래스로 생각하는 것이 좋다. 그러고 나서 각 팩토리 클래스의 getService() 메서드를 호출해 서비스 참조를 받아온다. ServiceTracker는 번들 컨텍스트(bundle context)와 OrderService 클래스 이름 매개변수를 사용해 구성된다.


Listing 2. OrderService 구현체
public class OrderServiceImpl implements OrderService, BundleActivator {

  private ServiceRegistration registration;

  public void start(BundleContext context) {
   registration = 
   context.registerService(OrderService.class.getName(), this, null);
   System.out.println("Order Service registered");
 }

  public void stop(BundleContext context) {
   System.out.println("Order Service stopped");
 }

  public void processOrder() {
   System.out.println("Order id: ORD123") ;
  }
}

서버 측 order.jar 파일은 OrderService 인터페이스와 OrderServiceImpl 클래스, 두 개의 컴포넌트를 포함한다. 인터페이스는 processOrder 추상 메서드를 가지고 있으며, OrderServiceImpl 클래스가 구현했다. 또한 order.jar 번들을 시작하고, 중지하기 위해 펠릭스 컨테이너가 호출하는 BundleActivator 인터페이스를 구현했다. start() 메서드에서는 클라이언트 번들이 사용할 수 있도록 레지스트리에 OrderService 컴포넌트를 등록한다. 등록하기는 다른 번들에서 사용할 수 있도록 객체를 노출하는 것과 같다.




위로


Manifest를 통한 의사소통

실제 논점은 "클라이언트 번들이 등록된 서비스 번들에 대해 어떻게 알 수 있을까?"다. 이런 의사소통은 Manifest 파일 사용을 통해 제어한다. Manifest 파일에서 import와 export 패키지의 일부로 번들의 참조를 제공한다. 일반적으로 서비스 번들의 Manifest에서 서비스 컴포넌트 패키지를 내보내는(export) 동시에, 클라이언트 번들의 Manifest에서 서비스 컴포넌트 패키지를 들여온다(import). 번들 A가 번들 B의 패키지를 들여올 때는, 동시에 번들 B에서는 해당 패키지를 내보내야 한다는 점을 주의하자. 적절한 import와 export 정의가 없다면 의사소통이 실패한다.


Listing 3. 클라이언트 Manifest 파일
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Order Service Client
Bundle-SymbolicName: orderclient
Bundle-Version: 1.0.0
Bundle-Activator: order.client.OrderClient
Import-Package: org.osgi.framework, org.osgi.util.tracker, order


Listing 4. 서버 Manifest 파일
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Order Service
Bundle-SymbolicName: orderservice
Bundle-Version: 1.0.0
Export-Package: order
Bundle-Activator: order.impl.OrderServiceImpl
Import-Package: org.osgi.framework

주문 애플리케이션에서 client.jar 번들 Manifest는 Import-Package: org.osgi.framework, org.osgi.util.tracker, order 엔트리를 갖고 있다. 이 말은 사실상 클라이언트 번들이 핵심 OSGi 패키지와 OrderService 패키지를 들여온다는 의미다. 이와 비슷하게 order.jar 번들 Manifest는 Export-Package: order 엔트리를 갖는다. 이 말은 번들이 클라이언트에서 사용할 패키지를 노출한다는 의미다. OSGi는 import와 export가 명시적으로 선언되어 있지 않을 경우에는 실시간 에러를 던진다.

Manifest 파일도 번들 activator 클래스 이름 같은 여타 부가 정보를 갖는다. Activator 클래스는 번들에 있는 start()stop()을 호출할 책임을 갖고 있다. 이 경우 client.jar 번들에 대한 activator 클래스는 OrderClient가 되고, order.jar 번들에 대한 activator 클래스는 OrderService가 된다.




위로


배포

번들을 배포하고 이것저것 해보기 전에 다음과 같이 한다.

  1. 루트인 C:\osgi 폴더 아래 그림 1에 나오는 디렉터리 구조를 만들고, 이번 글에서 앞서 다뤘던 컴포넌트를 넣자.
    • 자바 코드는 (클라이언트와 서비스 모두) 각각의 패키지 폴더로 이동하자.
    • Manifest 파일은 (클라이언트와 서비스 모두) 각각의 META-INF 폴더로 이동하자.


    그림 1. 코드 디렉터리 구조
    코드 디렉터리 구조

다음은 번들을 배포하는 단계다. 펠릭스 OSGi 컨테이너를 사용해 다음 단계를 따라 클라이언트와 서비스 번들을 배포한다.

  1. 서버 폴더에서 앤트를 사용해 build.xml을 실행
  2. 클라이언트 폴더에서 앤트를 사용해 build.xml을 실행

위 빌드 파일들을 실행한 후에, client.jar와 order.jar 번들이 client/bin과 service/bin 폴더에 각각 생성된다.

  1. 펠릭스 런타임을 시작하려면 마이크로소프트 윈도(Microsoft® Windows®) 명령 프롬프트에서 startfelix.bat를 실행하자.

펠릭스 런타임을 시작할 때마다 프로파일 이름을 그때그때 줄 수 있다. 프로파일 이름은 프로젝트 이름처럼 활용한다. 프로젝트 프로파일로 모든 이름을 제공할 수 있다. 연이어 시작하는 펠릭스 런타임에서 이전에 입력했던 프로파일 이름을 동일하게 제공한 경우, 펠릭스는 프로젝트 이름과 연계되어 설치된 모든 번들을 불러온다. 새로운 프로파일 이름을 줬다면, 다시 번들을 명시적으로 설치해야 한다.

  1. 펠릭스 셸에서 다음 명령어를 제공해 번들을 설치하자.
    • install file:service/bin/order.jar
    • install file: client/bin/client.jar
    • start service_bundle_id
    • start client_bundle_id

번들 ID를 지정하기 위해 ps 명령어를 줄 수 있다. 먼저 서비스 번들을 시작한 다음 클라이언트 번들을 시작해야 한다. 각 번들을 시작하면서 다음 출력이 표시된다(그림 2).


그림 2. 프로그램 출력
프로그램 출력

펠릭스 셸에서 update bundle_id 명령어를 제공해 번들을 갱신할 수도 있다. 번들은 런타임에 바로 갱신된다.




위로


결론

이번 글에서는 간략하게 OSGi 프레임워크의 특징과 개념, 그리고 동적으로 JAR 번들들을 만들어 어떻게 이용할 수 있는지를 설명했다. 우리는 컴포넌트를 OSGi 번들로 구축하고 패키징해서 펠릭스 런타임 환경에서 실행하는 방법에 대해 배웠다. 또한 번들 사이의 의사소통 인터페이스로 활용되는 번들 Manifest 파일 생성도 살펴 봤다.

OSGi는 JAR 번들들을 구축하고, 관리하는 방법의 새로운 차원을 부여했다. 이번 연재의 Part 2에서는 스프링 프레임워크가 어떤 방법으로 OSGi 환경에서 OSGi에서 번들 관리에 대한 책임을 넘겨받는지를 보여줄 것이니 계속 지켜 봐주길 바란다.





위로


다운로드 하십시오

설명이름크기다운로드 방식
OSGi 주문 애플리케이션osgi_orderapp.zip6KBHTTP
다운로드 방식에 대한 정보


참고자료

교육

제품 및 기술 얻기
  • IBM 제품 평가판을 다운로드하고, 애플리케이션 개발 도구와 DB2®, Lotus®, Rational®, Tivoli®, WebSphere®의 미들웨어 제품을 접해보자.


토론


필자소개

Rajeev Hathi's photo

Rajeev Hathi는 J2EE 플랫폼의 소프트웨어 컨설턴트로 일해왔다. 그의 관심사는 J2EE 기반 애플리케이션의 아키텍처 수립과 설계다. Rajeev는 자바와 J2EE 기술(웹, EJB, 아키텍처)에서 썬 자격증을 가지고 있다. 그는 Ajax, 웹 서비스, DB2와 XML에 대한 글을 IBM developerWorks에 기고한다. 그 외에도 자바 6 적용과 직접 따라 해보는 웹 서비스에 대한 책을 집필하는 데 참여했다. 지금은 인도 뭄베이에 거주하며, 스포츠를 보고, 록 음악을 듣는 걸 즐긴다.


Naveen Balani's photo

Naveen Balani는 IBM 인도 소프트웨어 랩(ISL)에서 아키텍트로 일하며 ISL의 WebSphere Business Services Fabric에 대한 설계와 개발 활동을 이끌고 있다. 새로운 기술을 연구하길 좋아하며 웹 서비스, ESB, JMS, SOA, 아키텍처, 오픈 소스 프레임워크, 시맨틱 웹, J2ME, 편재형 컴퓨팅(pervasive computing), 스프링, Ajax와 다양한 IBM 제품 등의 주제에 대해 IBM developerWorks에 지속적으로 기고하고 있다. 또한 그는 Beginning Spring Framework 2Getting Started with IBM WebSphere Business Services Fabric V6.1의 공동 저자이기도 하다.




기사에 대한 평가


보다 나은 서비스를 제공하기 위함이오니 잠시 짬을 내어 이 양식을 제출하여 주십시오.



 


 


 


이 문서 북마킹 하기

mar.gar.in mar.gar.in naver naver eolin eolin del.icio.us del.icio.us





위로


IBM, the IBM logo, ibm.com, DB2, developerWorks, Lotus, Rational, Tivoli, and WebSphere are trademarks or registered trademarks of International Business Machines Corporation in the United States, other countries, or both. These and other IBM trademarked terms are marked on their first occurrence in this information with the appropriate symbol (® or ™), indicating US registered or common law trademarks owned by IBM at the time this information was published. Such trademarks may also be registered or common law trademarks in other countries. See the current list of IBM trademarks. Adobe, the Adobe logo, PostScript, and the PostScript logo are either registered trademarks or trademarks of Adobe Systems Incorporated in the United States, and/or other countries. Java and all Java-based trademarks are trademarks of Sun Microsystems, Inc. in the United States, other countries, or both. Microsoft and Windows are trademarks of Microsoft Corporation in the United States, other countries, or both. 기타 회사, 제품, 및 서비스명은 다른 상표나 서비스 마크일 수 있습니다.

developerWorks 콘텐트를 다른 사이트에 전재하기:
developerWorks 콘텐트에 대한 저작권은 IBM에 있습니다. IBM의 서면 허가나 원본 저자의 허락이 없이는 전재를 금합니다. 저희 콘텐트를 전재하시려면 IBM developerWorks 담당자 에게 문의하십시오.
    IBM 소개 개인정보 보호정책 문의