OSGi 시작하기 3 – 번들간의 의존관계 : [번역] Dependencies between bundles

이 글은 Neil Bartlett 의 연재 글 “Getting started with OSGi”의 번역본입니다.
* 파트 1 – 첫번째 번들 : Your First Bundle
* 파트 2 – 프레임워크와 연동하기 : Interacting with the Framework
에 이어 3번째 글입니다. 오탈자 및 이상한 번역은 댓글로 남겨주세요

Getting started with OSGi : OSGi 시작하기 파트 3 – 번들간의 의존관계

저자 : Neil Bartlett < njbartlett at gmail dot com >
역자 : 권 정혁 < guruguru at gmail dot com >

글원본 : http://www.eclipsezone.com/eclipse/forums/t90544.html – Getting started with OSGi : Dependencies between bundles

지난회까지의 튜토리얼에서는, 어떻게 번들이 시작되고 중단되는지, 어떻게 프레임워크와 연결되고 다른 번들의 라이프 사이클에 연결되는지를 알아보았습니다. 그런데 정말 번들은 뭘 위한걸까요 ?

번들(Bundles)은 모듈(Modules)입니다. 번들은 우리의 단일 프로젝트를 관리가 가능한 조각들로 분리하여 OSGi 런타임 안으로 각각 로드될수 있도록 해줍니다. 문제는 우리가 원하든 원하지 않든간에, 모듈들이 다른 모듈에 의존관계(Dependency)를 가지고 있다는 겁니다. 평범한 Jar 파일에서는 다른 Jar 파일들에 대해 신뢰할수 있게 의존관계를 명시하는 일이 불가능했습니다. ( Manifest 에 있는 Class-Path 항목은 신뢰할 만한 방법이 아닙니다. ) 그래서 Jar 파일안에 있는 코드가 정말로 동작할지 아니면 런타임시에 ClassNotFoundException 을 낼지는 알 수 없습니다.

OSGi 는 이 문제를 매우 우아한 방법으로 해결했습니다. 말로 하는것보다 보여주는 방법이 좋을듯 하니, 코드로 가보도록 합시다. 불행하게도 우린 지금까지 기본 패키지를 이용해 왔지만, 이는 더이상 동작하지 않습니다. 우린 적절한 패키지가 필요하게 될 것입니다. 그럼 아주 간단한 JavaBean 스타일의 클래스로 시작해 봅시다. osgitut/movies/Movie.java 파일을 만들고 아래 코드를 복사하세요.

package osgitut.movies;
 
public class Movie {
    private final String title;
    private final String director;

 
    public Movie(String title, String director) {
        this.title = title; this.director = director;
    }
    public String getTitle() { return title; }
    public String getDirector() { return director; }
}

이제 같은 패키지 안에 인터페이스를 만들겁니다. osgitut/movies/MovieFinder.java 파일을 만들고 아래코드를 복사하세요.

package osgitut.movies;
 
public interface MovieFinder {
    Movie[] findAll();
}

이제 이 두개의 클래스들을 번들안에 집어 넣습니다. 우리의 번들은 터무니없을 정도로 작고, 거의 쓸모가 없지만 지금은 문제없습니다. 전과 같이 Manifest 파일을 만들어야 하므로, MoviesInterface.mf 를 만들고 아래를 복사하세요.

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Movies Interface
Bundle-SymbolicName: MoviesInterface
Bundle-Version: 1.0.0
Export-Package: osgitut.movies;version="1.0.0"
 

이전에는 보지 못했던 Export-Package 라는 새로운 줄이 있습니다. 이는 번들에서 osgitut.movies 패키지가 export 되었다는것을 의미합니다. 예전 Java jar 파일에서는 모든것이 export 되었으므로, 처음에는 좀 이상하게 보일수 있습니다. 하지만, 혹시 당신의 Jar 파일안에 내부적으로만 볼수 있는 코드를 패키지에 추가하는 것을 원해본적 없으신가요 ? 물론 클래스는 private 나 proctected 로 만들 수 있겠지만, 그러면 당신의 Jar 파일에 있는 다른 Package 에서도 못 보게 됩니다. 그래서 OSGi는 효율적인 새로운 코드 보안 레벨을 소개했습니다. 만약 번들안에 있는 패키지가 Export-Package 헤더에 포함되지 않는다면, 그 패키지는 오직 당신 모듈안에서만 접근이 가능합니다.

또 한 우리가 패키지에 버전 번호를 붙힌것을 볼수 있습니다. 이것은 중요한것이며 차후에 살펴볼 것입니다. 꼭 버전번호를 제공할 필요는 없습니다. 하지만 제공하지 않으면 OSGi 는 자동적으로 버전 “0.0.0”을 당신의 패키지에 할당하게 됩니다. 제 생각에 항상 버전을 명시하는것이 좋은 습관이라고 생각됩니다.

자 이제 이 번들을 빌드해 봅시다.

> javac osgitut/movies/Movie.java osgitut/movies/MovieFinder.java
> jar -cfm MoviesInterface.jar MoviesInterface.mf osgitut/movies/*.class

바로 번들을 런타임에 설치하진 않을것입니다. 먼저 이 번들에 의존하는 다른 번들을 만들 예정입니다. MovieFinder 인터페이스의 구현부를 작성할 것이므로 , 아래를 osgitut/movies/impl/BasicMovieFinderImpl.java 에 복사합니다.

package osgitut.movies.impl;
 
import osgitut.movies.*;
 
public class BasicMovieFinderImpl implements MovieFinder {

  private static final Movie[] MOVIES = new Movie[] {
    new Movie("The Godfather", "Francis Ford Coppola"),
    new Movie("Spirited Away", "Hayao Miyazaki")
  };

 
  public Movie[] findAll() { return MOVIES; }
}

매니페스트 파일 BasicMovieFinder.mf 를 아래와 같이 만듭니다.

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Basic Movie Finder
Bundle-SymbolicName: BasicMovieFinder
Bundle-Version: 1.0.0
Import-Package: osgitut.movies;version="[1.0.0,2.0.0)"
 

다른 번들에 의해 Export 되었던 osgitut.movies 번들을 import 하고 잇다는것을 주목하세요. 또한 이번엔 import 할때 버전의 범위를 추가했습니다. 프레임워크는 import 에 맞는 적절한 export 를 찾을때 이 범위를 사용합니다. OSGi 는 일반적인 수학에서 사용하는 범위형태의 문법을 사용합니다. “[” 는 포함한다는 것을 의미하며, “)”는 포함하지 않는다는 것을 의미합니다. 이에 의해 우리는 버전 “1.x” 대를 효과적으로 선택했습니다.

다시 한번 말씀드리지만, 이 경우에 버전번호 제약을 import 에 추가하는것은 꼭 필요하진 않습니다. 그냥 익숙해지면 좋을 습관일 뿐입니다.

자 이제 2번째 번들을 컴파일하고 번들로 만들어 봅니다.

> javac -classpath MoviesInterface.jar osgitut/movies/impl/BasicMovieFinderImpl.java 
> jar -cfm BasicMovieFinder.jar BasicMovieFinder.mf osgitut/movies/impl/*.class

이제, 이 번들들을 Equinox 에서 시도해볼때가 되었습니다. 이제 익숙해 지셨을테니, 이번엔 상세한 설명은 하지 않겠습니다. 먼저 BasicMovieFinder 번들을 설치한후, ss 를 입력해 보세요. 번들이 INSTALLED 상태에 있다는것을 보실수 있습니다.

id      State       Bundle
0       ACTIVE      org.eclipse.osgi_3.3.0.v20070208
4       INSTALLED   BasicMovieFinder_1.0.0

(NB 여러분의 번들 리스트는 제것과 약간 다르게 보일수 있습니다. 번들의 ID 는 당신이 얼마나 HelloWorld 번들을 설치/삭제 해보았는지에 따라 다를수 있씁니다. 번들ID 를 당신의 것으로 바꿔서 보도록 하세요.).

INSTALLED 는 프레임워크가 이제 막 번들을 설치했다는것을 의미하며, 아직 번들의 의존관계를 해결하지 못햇다는 것(not resolved)입니다.Equinox 에게 우리 번들에게 의존관계를 해결하도록 하는 하나의 방법은 refresh 명령입니다. refresh 4 를 입력하고 다시 ss 를 입력해 보세요.

id      State       Bundle
0       ACTIVE      org.eclipse.osgi_3.3.0.v20070208
4       INSTALLED   BasicMovieFinder_1.0.0

여전히 번들이 resolve 되지 않았습니다. 당연히, 우린 Movie 클래스와 MovieFinder 인터페이스를 가지고 있는 번들을 설치해야만 합니다. 이것이 정말 문제인지를 확인하기 위해 diag 4 를 입력해서, 진단 정보를 불러봅니다.

file:BasicMovieFinder.jar [4]
  Missing imported package osgitut.movies_[1.0.0,2.0.0).

네, 그게 문제였네요. 어떤 번들도 osgitut.movies 패키지를 export 하고 있지 않기 때문에 import 가 불가능합니다. 그럼 이제 MovieInterface.jar를 설치하고 ss 를 입력해 보세요. 리스트는 아래와 같을겁니다.

id      State       Bundle
0       ACTIVE      org.eclipse.osgi_3.3.0.v20070208
4       INSTALLED   BasicMovieFinder_1.0.0
5       INSTALLED   MoviesInterface_1.0.0

마지막 단계는 Equinox 에게 다시 BasicMovieFinder 번들에게 resolve 를 시도하도록 refresh 4 를 입력해 보는것입니다. ss 의 출력은 이제 아래와 같습니다.

id      State       Bundle
0       ACTIVE      org.eclipse.osgi_3.3.0.v20070208
4       RESOLVED    BasicMovieFinder_1.0.0
5       RESOLVED    MoviesInterface_1.0.0

BasicMovieFinder 이 이제 RESOLVED 가 되었습니다. 이것은 필수단계로서, 번들이 RESOLVED 상태가 되지 않으면 시작이 불가능하며, 또한 다른 번들들에게 Dependency 를 제공하지도 못합니다.

참고로, 보통은 이런 방법의 수작업은 필요치 않습니다. 일반적으로 번들은 그들이 필요로 할때 자동적으로 resolve 됩니다. 예를 들어 우리가 refresh 를 호출하지 않았어도 MoviesInteface 번들이 RESOLVED 상태가 된것을 보세요.

여기까지 입니다. Equinox 콘솔과 해볼수 있는 더 많은 재미난 것들을 위해서는 IBM developerWorks에 있는 Chris Aniszczyk 의 훌륭한 기사 를 참고하세요. 다음회에서는 OSGi 서비스에 대해 알아보겠습니다. 기대해 주세요.

  1. osgitut/movies/Movie.java 라고 하라고 하셧는데 /가 파일명에 안되지 않나요? 파일명 저게 맞는건지 ….

  2. 여기서 막혀서 너무 답답한 마음에 글을 씁니다.

    C:\>javac -classpath MoviesIntefface.jar osgitut/movies/impl/BasicMovieFinderImp
    l.java
    osgitut/movies/impl/BasicMovieFinderImpl.java:5: cannot find symbol
    symbol: class MovieFinder
    public class BasicMovieFinderImpl implements MovieFinder {
    ^
    osgitut/movies/impl/BasicMovieFinderImpl.java:7: cannot find symbol
    symbol : class Movie
    location: class osgitut.movies.impl.BasicMovieFinderImpl
    private static final Movie[] MOVIES = new Movie[] {
    ^
    osgitut/movies/impl/BasicMovieFinderImpl.java:13: cannot find symbol
    symbol : class Movie
    location: class osgitut.movies.impl.BasicMovieFinderImpl
    public Movie[] findAll() { return MOVIES; }
    ^
    osgitut/movies/impl/BasicMovieFinderImpl.java:7: cannot find symbol
    symbol : class Movie
    location: class osgitut.movies.impl.BasicMovieFinderImpl
    private static final Movie[] MOVIES = new Movie[] {
    ^
    osgitut/movies/impl/BasicMovieFinderImpl.java:8: cannot find symbol
    symbol : class Movie
    location: class osgitut.movies.impl.BasicMovieFinderImpl
    new Movie(“The Godfather”, “Francis Ford Coppola”),
    ^
    osgitut/movies/impl/BasicMovieFinderImpl.java:9: cannot find symbol
    symbol : class Movie
    location: class osgitut.movies.impl.BasicMovieFinderImpl
    new Movie(“Spirited Away”, “Hayao Miyazaki”)
    ^
    6 errors

    이렇게 에러가 나는데요 왜 그런지 이유를 모르겠어요;;

    그리고 javac를 했을때 왜 여기서는 -classpath를 썼는지 궁금하네요

    1장 2장에서는 저런 옵션이 없었는데 말이죠;;답변부탁드려요~

    • javac -classpath MoviesIntefface.jar 부분에 오타인듯 하네요.
      javac -classpath MoviesInterface.jar 입니다. 이게 틀리면 클래스를 못찾게됩니다.

      • 답변감사합니다 ^^..; 사소한 실수라서 죄송하네요ㅠ

        최근댓글이 2008년도에서 멈춰서 대답이 올지 많이 걱정됐는데

        정말 고맙습니다~!

Leave a Comment


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>