오랫동안 JavaME(Micro Edition)에 대한 최대의 관심은 2000년 5월에 최종적인 형태로 공개된 바 있는 CLDC(Connected Limited Device Configuration)에 집중되어 왔으며, 2개월 후에 최초의 CLDC 기반 프로파일인 MIDP(Mobile Information Device Profile)가 발표되었다. MIDP는 새로운 애플리케이션 모델과 더불어 사용자 인터페이스 및 persistence를 위한 클래스를 정의한다는 이유로 자바 커뮤니티에서 커다란 반향을 불러일으켰었다. 다시 말해서 MIDP는 인터랙티브 애플리케이션의 배치 및 실행을 위한 완벽한 환경을 제공했던 것이다.

JavaME의의 또 다른 구성인 CDC(Connected Device Configuration)는 거의 1년 뒤인 2001년 3월에 가서야 JCP(Java Community Process)를 통해서 마무리되었고, 이와 동시에 최초의 CDC 기반 프로파일인 Foundation Profile(FP)이 발표되었다. 하지만 FP는 MIDP와 달리 인터랙티브 애플리케이션 구축을 위한 클래스를 제공하지 않았으며, 결국 CDC/FP 조합은 자바 커뮤니티에서 그다지 큰 관심을 끌지는 못했다.

한편, 두 가지의 새로운 CDC 기반 프로파일이 완결되었는데, 이 두 프로파일--Personal Basis Profile(PBP)과 Personal Profile(PP)--은 더 이상 활발한 개발이 이루어지지 않고 있는 PersonalJava 플랫폼을 대체하고 있다. 이 프로파일들은 PersonalJava와 마찬가지로 인터랙티브 애플리케이션 구축에 필요한 클래스를 제공한다. 본 기사에서는 먼저 이 두 프로파일에 대해 살펴보고, 두 프로파일의 차이점을 비롯하여 프로파일과 PersonalJava 플랫폼을 비교 분석해보기로 한다.

공통 기반

새로운 프로파일을 제대로 이해하려면, 반드시 Connected Device Configuration과 Foundation Profile이 JavaME 플랫폼에 대해 어떤 역할을 하는지 이해해야만 한다. 왜냐하면, PBP와 PP 모두 CDC/FP 조합에 기반을 두고 있기 때문이다.

CDC 요약

CDC가 정의하는 자바 런타임 환경(JSR 36)은 CLDC가 정의하는 환경보다 Java SE에 훨씬 가깝다고 할 수 있다. 일례로, CDC 기반 장치는 Java 2 Platform 언어 스펙과 Java 2 Platform 가상 머신 스펙을 완벽하게 지원한다. 또한 이들은 Java SE 1.3 애플리케이션 프로그래밍 인터페이스(API)의 서브세트이며, 클래스는 다음 패키지에 속해있다.

  • java.io
  • java.lang
  • java.lang.ref
  • java.lang.reflect
  • java.lang.math
  • java.net
  • java.security
  • java.security.cert
  • java.text
  • java.util
  • java.util.jar
  • java.util.zip

단, 일반적으로 CDC는 각 패키지 내 클래스의 일부만을 포함한다는 점에 유의할 것. 예를 들어, java.net 패키지에서는 데이터그램과 URL 처리와 관련한 클래스만 포함되며, 스트림 기반 소켓 지원은 CDC에 포함되지 않는다.

CDC는 CLDC의 수퍼세트이므로 마찬가지로 javax.microedition.io 패키지 내의 GCF(Generic Connection Framework)를 구성하는 클래스를 포함한다. CDC 기반 장치는 java.iojava.net 패키지의 API 외에도 GCF를 이용하여 파일을 읽고 쓰고, 데이터그램을 주고 받을 수 있다.

Foundation Profile 요약

Foundation Profile(JSR 46)은 주로 CDC에서 생략된 JavaSE API를 추가하는데, 특히 다음의 패키지를 예로 들 수 있다.

  • java.io
  • java.lang
  • java.net
  • java.security
  • java.security.cert
  • java.text
  • java.util
  • java.util.jar
  • java.util.zip

FP는 또한 CDC에서 볼 수 없는 다음 세 가지 패키지의 클래스를 포함한다.

  • java.security.acl
  • java.security.interfaces
  • ava.security.spec

FP에는 스트림 기반 소켓과 HTTP 연결에 필요한 java.net 클래스가 포함된다는 점에 유의할 것. 이 연결은 또한 GCF를 통해서도 이용이 가능하다--실제로, FP에는 MIDP의 javax.microedition.io.HttpConnection 인터페이스가 포함된다.

여러분도 알다시피, CDC/FP 연결은 범용 프로그램을 위한 강력한 환경을 정의하지만 정작 인터랙티브 애플리케이션 구축에 필요한 클래스는 빠져 있다.

Personal Basis Profile

Personal Basis Profile(JSR 129)은 Foundation Profile의 슈퍼세트로, 다음 세 가지의 새로운 기능을 제공한다.

  • Java TV API를 기반으로 한 Xlet 애플리케이션 모델
  • 경량형 컴포넌트에만 기반을 둔 사용자 인터페이스를 구축하기 위한 JavaSE AWT(Abstract Windowing Toolkit)의 일부분
  • RMI(Remote Method Invocation) API의 일부분을 이용하는 IXC(Inter-Xlet Communication)

이 기능들을 이용하면 효과적으로 정의된 라이프사이클을 갖춘 양방향 애플리케이션을 개발할 수 있다.

포함된 패키지

PBP는 새로운 기능을 지원하기 위해 CDC/FP에 이미 포함된 것 외에도 다음과 같은 JavaSE 1.3 패키지의 일부를 포함하고 있다.

  • java.awt
  • java.awt.color
  • java.awt.event
  • java.awt.image
  • java.beans
  • java.rmi
  • java.rmi.registry

단, PBP는 RMI를 지원하지 않는다는 점에 유의할 것. java.rmijava.rmi.registry 패키지는 정식 RMI라기보다는 Xlet 간 통신(IXC)을 지원하기 위해 포함되었다. PBP 기반 디바이스는 RMI 지원이 가능하지만, 이는 모든 CDC 기반 디바이스에 포함될 수 있는 별도의 스펙인 RMIOP(RMI Optional Package)를 구현하는 경우에만 가능하다.

Xlet 애플리케이션 모델

전통적인 자바 애플리케이션 모델은 상당히 단순하다고 할 수 있다. 즉, 클래스를 로드하고 main() 메소드를 인보크한 다음 모든 비(非) Background 스레드가 종료되거나 System.exit()가 호출될 때까지 기다린다. 대부분의 애플리케이션의 경우, 이 모델은 애플리케이션 동작에 대한 통제권을 거의 허용하지 않는다. 이런 이유 때문에 MIDP는 디바이스가 외부 이벤트에 반응하여 애플리케이션을 시작, 종료, 일시 중지할 수 있게 해주는 MIDlet 애플리케이션 모델을 정의하며, 브라우저 기반 애플리케이션--애플릿--은 다른 애플리케이션 모델을 이용한다.

PBP는 여러 가지 면에서 MIDlet 모델과 유사한 자체 애플리케이션 모델을 정의한다. Xlet 모델은 Java TV API에서 차용된 것으로, 셋톱 박스 애플리케이션의 라이프사이클을 제어하는 데 사용된다. 이 모델의 두 가지 주요 요소로는 javax.microedition.xlet 패키지에 포함된 XletXletContext 인터페이스를 들 수 있다. 이 애플리케이션의 메인 클래스는 Xlet 인터페이스를 구현하며, 이 인터페이스는 시스템이 인보크할 이벤트 메소드를 정의한다. XletContext 인터페이스는 애플리케이션이 운영 환경에 관한 정보를 입수하는 데 사용하는 콜백 메소드를 정의한다. 다음은 흔히 볼 수 있는 Xlet의 예이다.

// Example of a trivial Xlet import javax.microedition.xlet.*; public class TrivialXlet implements Xlet { private XletContext context; public TrivialXlet(){ } public void destroyXlet( boolean unconditional ) throws XletStateChangeException { } public void initXlet( XletContext context ) throws XletStateChangeException { this.context = context; } public void pauseXlet(){ } public void startXlet() throws XletStateChangeException { context.notifyDestroyed(); // immediately quit } }

Xlet과 PBP에 관한 자세한 내용은 다음 기사를 참조하도록 한다.

PBP는 Xlet 모델뿐 아니라 종래의 애플리케이션 모델까지 지원한다는 점에 유의할 것.

AWT 서브세트

MIDP와 달리 PBP는 전혀 새로운 사용자 인터페이스 클래스 세트를 정의하지 않는 대신 표준 AWT 클래스를 서브세트로 취한다. JavaSE 애플리케이션 개발 경험이 많은 개발자들에게는 MIDP보다 PBP가(곧 살펴볼 Personal Profile과 함께) 훨씬 더 익숙한 환경으로 느껴질 것이다.

PBP의 AWT 서브세트에 포함된 클래스는 경량형 사용자 인터페이스 컴포넌트를 정의하고 사용하는 데 필요한 요소들이다. 원래 AWT는 중량형 컴포넌트로 구성되어 있었는데, 각 컴포넌트 인스턴스는 기본 운영체제에 있어서 고유한 UI 컴포넌트(이른바 피어 컴포넌트)를 위한 프록시에 지나지 않았다. 중량형 컴포넌트로 구축된 애플리케이션은 해당 플랫폼 상에서 실행되는 다른 애플리케이션과 유사한 외관과 분위기를 지니지만, 사용자 인터페이스 동작이나 외관에 대한 자바 런타임의 통제력이 제한되어 있다. 따라서 Java 1.1에는 외관과 분위기가 런타임에 의해 완벽히 통제되는 경량형 컴포넌트의 개념이 도입되었다. 이 경량형 모델에서는 각 컴포넌트가 상위의 추출 영역(drawing area)에서 자신을 직접 추출하고 상위에서 위임한 이벤트에만 반응하기 때문에, 최상위 윈도우를 제외하면 피어 컴포넌트는 아예 존재하지 않는다. 하지만, 런타임 시스템이 운영체제와 상호 작용할 방법이 필요하기 때문에 최상위 윈도우에는 대개 중량형 컴포넌트가 사용된다.

경량형 컴포넌트를 지원하기 위해 PBP에는 특히 다음과 같은 클래스가 포함되어 있다.

  • java.awt.Component - 모든 사용자 인터페이스 컴포넌트를 위한 기본 클래스
  • java.awt.Container - 타 컴포넌트를 포함하고 관리하는 AWT 컴포넌트를 위한 기본 클래스
  • java.awt.Window - 최상위 윈도우를 위한 기본 클래스
  • java.awt.Frame - 제목 표시줄과 테두리가 있는 최상위 윈도우

이들은 완벽한 사용자 인터페이스를 구축하는 데 필요한 핵심 컴포넌트 클래스들로서, 경량형 컴포넌트를 생성하는 데는 Component와 Container가, 그리고 이 경량형 컴포넌트를 담는 최상위 윈도우를 생성하는 데는 Window와 Frame이 사용된다. PBP의 다른 모든 AWT 클래스들은 이 네 가지 요소를 지원하는 데 사용된다.

PBP는 특히 Window와 Frame을 제외한 모든 중량 컴포넌트를 배제한다는 점에 유의할 것. 버튼이나 리스트, 메뉴를 비롯한 그 밖의 기본적인 사용자 인터페이스 컴포넌트는 포함되어 있지 않다. JavaSE의 경우에는 이 기본 컴포넌트의 경량형 버전이 Swing 사용자 인터페이스 툴키트에 의해 정의되지만 PBP에는 Swing이 포함되어 있지 않다.

중량형 컴포넌트가 빠져 있고 Swing을 이용할 수도 없다면 어떻게 사용자 인터페이스를 생성해야 할까? 다음과 같은 두 가지 방법이 가능하다.

각자의 애플리케이션이 아주 단순하다면 다음과 같이 자체 컴포넌트를 직접 작성할 수 있다.

import java.awt.*; /** * A _very_ simple UI component that draws a * centered text string. */ public class SimpleTextLabel extends Component { private String text; public SimpleTextLabel( String text ){ this.text = text; } public void paint( Graphics g ){ int h = getHeight(); int w = getWidth(); g.setColor( getBackground() ); g.fillRect( 0, 0, w, h ); g.setColor( getForeground() ); FontMetrics fm = g.getFontMetrics(); int textWidth = fm.stringWidth( text ); int textHeight = fm.getHeight(); int x = ( w - textWidth ) / 2; int y = ( h - 2 * textHeight ) / 2; g.drawString( text, x, y ); } }

런타임 시, 이 컴포넌트들을 직접 Frame 컴포넌트 상에 배치한다.

... Frame frame = ... // some frame you created SimpleTextLabel label; // Now build our user interface label = new SimpleTextLabel( "Press a key to exit" ); label.setBackground( Color.blue ); label.setForeground( Color.yellow ); label.addKeyListener( new KeyAdapter(){ public void keyTyped( KeyEvent e ){ exit(); } } ); frame.add( label );

새로운 Xlet 모델에 따라 실행되는 애플리케이션은 자체 프레임을 생성하는 대신 시스템이 공급하는 루트 컨테이너를(초기화 시 각 Xlet으로 전달되는 XletContext 오브젝트를 통해) 이용한다.

사용자 인터페이스를 작성하는 두 번째 방법은 제3의 경량형 사용자 인터페이스 툴키트를 사용하는 것인데, 이 툴키트에 벤더가 제공하는 클래스를 추가할 수도 있다.

PBP AWT 서브세트에는 중량 컴포넌트가 없다는 점 외에도, 애플리케이션의 사용자 인터페이스가 수행할 수 있는 기능에 뚜렷한 제약이 있기 때문에, UI 기능이 상대적으로 제한된 시스템 상에서만 PBP 애플리케이션의 운영이 가능하다. 가장 중요한 제약 사항은 애플리케이션이 Frame 클래스에서 하나의 인스턴스만을 사용할 수 있다는 점이다. 한편, 전통적인 모델을 이용하여 구축된 PBP 애플리케이션은 프레임을 스스로 생성하는 반면, 이와 대조적으로 Xlet 모델에서는 시스템이 애플리케이션을 대신해서 프레임을 생성하고, XletContext.getContainer() 메소드를 통해 이 프레임(또는 자식 컨테이너)을 이용할 수 있도록 한다. 그 밖의 프레임 기능은 옵션으로 제공되며, 시스템은 임의로 프레임의 크기와 상태, 위치를 제한할 수 있으며 프레임의 제목을 숨길 수도 있다. 그 밖에 커서 사용을 비롯한 몇 가지 세부사항에 대해서도 제약이 따른다.

Inter-Xlet Communication

IXC(Inter-Xlet Communication)는 동일한 가상 머신에서 운영되는 두 개 이상의 Xlet이 오브젝트를 교환하고 클래스 로더의 경계를 넘어 코드를 실행할 수 있게 해준다. IXC는 JavaSE의 RMI(Remote Method Invocation) 기능에 기반을 두고 있지만, 사실상 RMI는 VM 의 통신이 아닌 VM 에서의 통신을 위해 개발되었다. 그렇다고 해서 Xlet 간 통신 자체가 RMI 기능을 모두 이용할 수 있다는 것을 의미하지는 않는다는 사실을 기억하는 것이 중요하다. 또한, PBP 애플리케이션에서 RMI를 실행하려면 반드시 RMIOP를 사용해야 한다.

Xlet은 IXC 레지스트리를 이용하여 다른 Xlet이 오브젝트를 사용하도록 할 수 있는데, 이것을 오브젝트 바인딩 또는 익스포팅이라고 한다. 모든 Xlet은 동일한 레지스트리, 즉 javax.microedition.xlet.ixc.IxcRegistry 클래스의 싱글턴 인스턴스를 공유하는데, getRegistry() 팩토리 메소드는 아래와 같이 싱글턴을 반환한다.

... import javax.microedition.xlet.*; import javax.microedition.xlet.ixc.*; XletContext context = ..... // get the Xlet's context IxcRegistry registry = IxcRegistry.getRegistry( context ); ...

이 레지스트리는 공유 해시 테이블과 유사하다. Xlet은 bind() 메소드를 이용하여 오브젝트에 이름을 바인딩하는데, 원격 인터페이스를 구현하는 오브젝트만 레지스트리에 바인딩될 수 있다. 원격 인터페이스는 java.rmi.Remote를 확장하여 각 메소드가 java.rmi.RemoteException을 throw하도록 하는 인터페이스이며, 모든 메소드 파라미터와 반환 타입은 기본 타입이거가 직렬화가 가능한 오브젝트 또는 기타 원격 인터페이스이다.

다른 Xlet들은 lookup() 메소드를 이용하여 바인딩된 오브젝트를 찾아내며 이는 실제 오브젝트의 스텁(stub)을 반환하는데, 이 스텁은 런타임 시스템에 의해 자동으로 생성된다(이와 달리 RMI에서는 반드시 rmic 툴을 이용하여 수동으로 스텁을 생성해야 한다). 스텁은 원래의 오브젝트와 동일한 원격 인터페이스를 구현하며 이 오브젝트를 위한 프록시 역할을 한다. 애플리케이션이 스텁의 특정 메소드를 인보크할 경우, 시스템은 심지어 다른 쓰레드 상에 위치한 경우라도 원래의 오브젝트 상에서 동일한 메소드를 인보크한다. 이 때, 메소드 인수는 대부분 사용자가 예상한 대로 처리된다. 즉, 기본 타입이 복사되며, 직렬화가 가능한 오브젝트는 콜러(caller)에서 직렬화되고 콜리(callee)에서 직렬화 해제되며, 원격 오브젝트를 위해 스텁이 반환된다(실제 오브젝트에 대한 레퍼런스를 얻는 오브젝트를 바인딩한 Xlet에서는 예외).

다음은 IXC를 이용하여 애플리케이션 인스턴스가 동시에 2개 이상 실행되지 않도록 하는 예제 애플리케이션이다.

import java.rmi.*; import javax.microedition.xlet.*; import javax.microedition.xlet.ixc.*; /** * An Xlet that uses inter-Xlet communication (IXC) * to ensure that only once instance of the Xlet is * ever running. */ public class RunOnceXlet extends BasicXlet { private static final String NAME = "RunOnceXlet.activator"; private boolean removeBinding = false; public RunOnceXlet(){ } // The first thing the Xlet does is check to see if an // instance of itself is already running. public void initXlet( XletContext context ) throws XletStateChangeException { try { // Get the IXC registry and create an instance of // our own remote interface in case we're the first // instance running IxcRegistry registry = IxcRegistry.getRegistry( context ); RemoteInterface remote = new RemoteInterfaceImpl(); while( true ){ try { // First we try to bind our remote interface // to the registry. If two instances are // started simultaneously, only // one of them will win. registry.bind( NAME, remote ); removeBinding = true; break; } catch( AlreadyBoundException abe ){ try { // Somebody else has bound an interface, // so we get it and call its // activateAgain method before // terminating. remote = (RemoteInterface) registry.lookup( NAME ); String[] args = (String[]) context.getXletProperty( XletContext.ARGS ); remote.activateAgain( args ); throw new XletStateChangeException( "Already running" ); } catch( NotBoundException nbe ){ // Whoops, no object was found, the other // instance might have just terminated // so try to register ourselves again.... } } } } catch( RemoteException e ){ // If we can't connect, just start up... System.out.println( "Error dealing with registry:" ); e.printStackTrace(); } ..... // perform normal initialization } // Deregister the instance from the IXC registry. This // will happen automatically when the Xlet is destroyed, // but it's better to do it explicitly. public void exit(){ if( removeBinding ){ try { IxcRegistry registry = IxcRegistry.getRegistry( getContext() ); registry.unbind( NAME ); } catch( NotBoundException e ){ } catch( RemoteException e ){ } } ..... // do other cleanup stuff } /** * The remote interface instances of RunOnceXlet use to * communicate with each other. */ public interface RemoteInterface extends Remote { void activateAgain( String[] args ) throws RemoteException; } /** * The implementation of the remote interface. One difference * between IXC and regular RMI is that in regular RMI this * class would extend java.rmi.server.UnicastRemoteObject * and you would have to run rmic to generate the appropriate * stub classes. With IXC the stubs are generated * automatically. */ private class RemoteInterfaceImpl implements RemoteInterface { public RemoteInterfaceImpl() throws RemoteException { } // Our activation method. All it does is print out a // message, but it could easily do other // things by invoking methods on its containing class. // methods on its containing class. public void activateAgain( String[] args ) throws RemoteException { System.out.println( "[RemoteInterfaceImpl] Activation request" ); } } }

이 때, 클래스들은 IXC를 이용해 원격 로딩되지 않는다는 점에 유의할 것. 스텁은 자동으로 생성되지만, 이 스텁이 구현하는 실제 인터페이스는 반드시 애플리케이션과 함께 사전에 패키징되어 있어야 한다.

Personal Profile

Personal Profile(JSR 62)은 Personal Basis Profile의 슈퍼세트로, 다음과 같은 기능이 추가되었다.

  • 브라우저 기반 애플리케이션 구축을 위한 애플릿 지원
  • 중량형 컴포넌트, JDK 1.02 형 이벤트, deprecated API 등에 대한 지원을 포함하는 보다 포괄적인 AWT 서브세트
  • java.awt.datatransfer 패키지의 서브세트를 이용한 클립보드 지원

이와 같이 PP는 Xlet 애플리케이션 모델 및 Xlet 간 통신과 같은 새로운 PBP 기능을 제공하는 것은 물론, 보다 풍부하고 JavaSE에 가까운 환경을 제공한다.

포함된 패키지

PP는 PBP 클래스에 다음과 같은 세 가지의 JavaSE 1.3 패키지 클래스가 추가되어 있다.

  • java.applet
  • java.awt
  • java.awt.datatransfer

PP는 PBP와는 달리 비 JavaSE 클래스를 더 이상 정의하지 않는다.

애플릿 지원

애플릿 모델은 PBP가 지원하는 전통적인 애플리케이션 모델과 Xlet 애플리케이션 모델의 또 다른 대안이라 할 수 있다. 애플릿은 웹 브라우저에 의해 작성된 통제 환경(종종 sandbox로 불림) 내에서 실행되는 브라우저 기반 애플리케이션이다. MIDlet 및 Xlet과 마찬가지로, 애플릿은 사용자가 브라우저를 이용해 특정 웹 페이지에서 다른 웹 페이지로 이동하는 것과 같은 이벤트에 반응해 언제 시작 혹은 일시 중지, 종료할 것인지에 대해 시스템의 지시를 받게 된다. PP에서의 애플릿 지원은 본질적으로 Java 1.1 버전과 동일하기 때문에 대부분의 독자들에게 상당히 익숙한 방법일 것이다.

AWT 서브세트

PP의 AWT 서브세트는 PBP AWT 서브세트와는 달리 java.awt.Buttonjava.awt.List 클래스와 같은 표준 중량형 UI 컴포넌트를 지원한다. 이들 클래스는 애플릿 모델을 정상적으로 지원하는 데 필요한데, 이는 java.applet.Applet 클래스가 java.awt.Panel을 직접 확장하며, 많은 애플릿들이 표준 컴포넌트를 이용해 사용자 인터페이스를 작성하기 때문이다. 또한 AWT 서브세트는 애플릿 모델 지원을 위해 java.awt.Event 클래스와 Component.handleEvent() 메소드를 기반으로 하는 오리지널 Java 1.0.2 이벤트 모델도 지원한다. 한편, PP는 기존 애플릿과의 역호환을 위해 Component.enable() 등 PBP에서 제외된 deprecated AWT 메소드를 다시 도입하고 있다.

PP는 JavaSE 1.3의 AWT 클래스 대부분을 포함하고 있으며, 제외된 클래스로는 2차원 그래픽 클래스(java.awt.Paintjava.awt.Stroke), 프린팅 클래스(java.awt.PrintJob), 액세스 가능 클래스(java.awt.Component.AccessibleAWTComponent), java.awt.Robot class 등이 있다.

Personal Profile은 Personal Basis Profile에 적용된 사용자 인터페이스 제약 사항들을 다소 완화시켰는데, 특히 애플리케이션이 생성하는 프레임이나 대화상자의 수를 제한하지 않는다. 그러나 시스템은 전과 마찬가지로 최상위 윈도우의 크기나 상태, 위치 등을 임의로 제한할 수 있다. 즉, 이들 제약 사항들은 지나치게 UI 기능이 제한되는 시스템들을 지원하기 위한 것이다.

PersonalJava에서 마이그레이트하기

PersonalJava 스펙에 따라 작성된 애플리케이션의 경우, Personal Profile(일부의 경우 Personal Basis Profile)에 대한 JavaME 마이그레이션 수단을 제공한다. 물론 이 두 개의 Java 환경은 서로 이질적인 특성을 띠기 때문에 마이그레이션이 그리 간단하지는 않을 것이지만 숙련된 Java 프로그래머들이라면 작업이 그다지 어렵지 않을 뿐 아니라, 마이그레이션이 완료되는 순간부터 과거의(이제는 상당히 낡은) Java 1.1 API 대신 보다 친숙한 JavaSE 1.3 API를 사용하는 애플리케이션을 보유할 수 있게 될 것이다.

PersonalJava 1.2a 스펙이 정의하는 아래 패키지들은 Personal Profile에 포함된 같은 이름의 패키지들과 동일하거나 그 서브세트이다.

  • java.applet
  • java.awt.datatransfer
  • java.awt.event
  • java.awt.image
  • java.io
  • java.lang
  • java.reflect
  • java.net
  • java.security
  • java.security.cert
  • java.security.interfaces
  • java.security.spec
  • java.text
  • java.util
  • java.util.jar
  • java.util.zip

이 리스트에는 java.awt가 포함되어 있지 않다는 점에 유의할 것. PersonalJava에는 이 패키지의 PrintGraphicsPrintJob 클래스가 포함되어 있지만 Personal Profile은 그렇지 않다. 하지만 이 두 가지만 제외하면, PersonalJava java.awt 패키지는 Personal Profile java.awt 패키지의 서브세트와 동일하다.

PersonalJava 애플리케이션이 위에 나열된 패키지들(프린터 클래스가 없는 java.awt 포함) 만을 사용하도록 제한한다면, 이 애플리케이션은 별다른 수정 사항 없이 그대로 실행이 가능할 것이다. 프로그래머가 곤란을 겪을 수 있는 유일한 요소가 바로 deprecated 메소드인데, 왜냐하면 Personal Profile에는 AWT 클래스의 deprecated 메소드만 포함되어 있고, Java 1.1.8의 deprecated 메소드는 제외되어 있기 때문이다.

PersonalJava에 포함된 다른 패키지들이 Personal Profile에도 모두 포함되어 있는 것은 아니다. 특히,

  • java.beans 패키지에서 디자인 타임 클래스가 제외되어 있다.
  • PP는 RMI Optional Package가 없을 경우 RMI를 지원하지 않는다. (PersonalJava에서는 RMI가 옵션으로 제공된다는 점에 유의할 것).
  • CDC/Foundation Profile (JSR 169)의 JDBC Optional Package가 없을 경우, PP는 java.sql 패키지의 JDBC 클래스를 단 한 개도 포함하지 않는다. (PersonalJava에서는 JDBC가 옵션으로 제공된다는 점에 유의할 것).
  • PP는 com.sun.awt.com, com.sun.lang, com.sun.util 패키지에서 PersonalJava별 API를 지원하지 않는다. 따라서 이들을 이용하는 코드의 경우, Personal Profile의 가장 비슷한 API를 이용할 수 있도록 재작성되어야 한다.

PersonalJava에서 Personal Profile로의 마이그레이션이 쉽지 않은 이유가 바로 여기에 있다. 하지만 이러한 변경 작업 중 일부는 매우 간단하게 수행할 수 있는데, 한 예로 Personal Profile에 메소드가 존재하지 않을 경우에는 com.sun.lang.UnsupportedOperationException이 throw되는 경우를 들 수 있다. 반면에, com.sun.util.PTimer 사용을 java.util.Timer 사용으로 대체하는 것과 같은 작업은 이보다 훨씬 어려운 과정을 거쳐야 한다.

결론

이제까지 살펴본 것과 같이, Personal Basis Profile과 Personal Profile 모두 JavaSE 구현을 100% 지원하기에는 지나치게 많은 제약을 받는 디바이스를 위해 유저 인터렉티브한 Java 애플리케이션을 개발할 수 있는 완벽한 환경을 제공한다. 또한 이들 프로파일은 PersonalJava 애플리케이션을 Java 2 Platform으로 마이그레이트할 수 있는 수단을 제공하기도 한다.

이들 프로파일에 관한 자세한 내용은 Personal Profile section of the Wireless Java portal을 참조할 것.


Posted by Golmong
: