01.JAVA/J2me2008. 11. 27. 13:09
반응형
MIDP
사용자 삽입 이미지
MIDP는 모바일 인포메이션 디바이스(MID)를 목표로 CLDC 컨피규레이션을 기반으로 설계된 자바 클래스 라이브러리에 대한 명세이다. 그러므로, MIDP 명세는 CLDC의 명세를 확장하거나, 구체화 하거나, 변경을 가하고 있다. 우선 MIDP에서 좀 더 구체화된 하드웨어 디바이스들의 특징을 보자
 
사용자 삽입 이미지디스플레이 요구사항
    - 96x54 이상의 스크린 사이즈
  - 비트 이상의 디스플레이(모노크롬)
- 종횡비(aspect ratio)가 약 1:1에 근접
사용자 삽입 이미지입출력 요구사항
    - 한 손, 혹은 두 손으로 입력가능한 입출력 메커니즘
사용자 삽입 이미지메모리 요구사항
    - MIDP 컴포넌트를 위한 128K의 비휘발성 메모리 공간
    - 애플리케이션이 생성하는 데이터의 저장을 위한 8K의 비휘발성 메모리 공간
    - 자바 런타임을 위한 32K의 휘발성 메모리 공간
사용자 삽입 이미지네트워킹 요구사항
    - 양방향이고, 무선이며, 제한된 대역폭에, 간헐적으로 연결될 수 있음
그리고, MIDP 명세서는 다음과 같은 부분들을 정의하고 있다.

사용자 삽입 이미지애플리케이션 모델
사용자 삽입 이미지유저 인터페이스와 이벤트 핸들링
사용자 삽입 이미지영속적 저장공간
사용자 삽입 이미지네트워킹
사용자 삽입 이미지타이머 지원

사용자 삽입 이미지2.1 JAM과 신개념 애플리케이션 모델
  Application의 다운로드와 실행이라는 혁신적인 모델을 제시했던 Java언어의 특징을 한껏 살려서 자원이 적은 기기에서 실행모듈을 download하여 실행토록한다는 아이디어가 midlet이다. 이 프로그램방법은 applet과 유사한점이 많다.
MIDlet과 ‘애플리케이션 관리 소프트웨어’라는 개념은 초창기의 자바 애플릿 만큼이나 혁명적이다. 하지만, 지금은 많은 분들이 애플릿이라는 경험을 통해서 실행코드의 네트웍 이동성에 대해서는 이미 친숙해 진 상태일 것이므로, MIDlet이라는 새로운 애플리케이션 모델을 받아들이기에는 큰 무리가 없을 것 같다.
JAM(Java Application Manager)는 CLDC/MIDP 플랫폼의 새로운 애플리케이션 모델을 지원하기 위한 애플리케이션 관리 소프트웨어이다. JAM의 역할은 MIDP 애플리케이션, 즉, MIDlet을 다운로드하여 설치하고, 업그레이드하고, 실행하고, 삭제하는 것이다. <표 6>은 이러한 JAM의 기본 기능들을 정리한 것이다.

왜 JAM이라는 이해하기 쉽지 않은 새로운 애플리케이션 모델을 도입해야만 했을까? 필자가 사용하는 모 이동통신 단말기는 SMS 기반의 인터넷 기능이 디폴트로 내장되어 있다. 이 단말기로 WAP 서비스를 받기 위해서는 단말기 A/S 센터로 가서 소프트웨어 업그레이드를 해야 했다. 이 때, 서비스 매뉴얼에 충실한 직원이, “몇 개의 게임은 즐길 수 없게 되며, 전화번호 저장공간이 300개에서 200개로 줄어들게 됩니다. 그래도 업그레이드를 받으시겠습니까?”라고 물었다. 추측하건대, WAP 브라우저는 SMS 브라우저보다 메모리 풋프린트가 크고, 그 차이로 인해, 전화번호 저장공간 100개를 희생시키는 것이다.

여기서 우리는 세 가지의 개선점을 발견할 수 있다. 첫째는 고객이 굳이 소프트웨어 업그레이드를 받기 위해 A/S 센터를 찾는 번거로움을 없애준다면 좋을 것이다. 둘째는 게임과 같은 취향에 따라 다양한 선택의 폭을 가진 애플리케이션을 직접 고를 수 있도록 하면 좋을 것이다. 셋째는 이렇게 설치한 프로그램이 업그레이드되었을 경우, 자동적으로 업그레이드를 수행해 주면 좋을 것이다. JAM이 등장한 이유 중의 하나가 이런 것들을 가능하게 하기 위한 것이다.
기 능
통 신 방 법
추출(retrieval) 삭제(removal)
인스톨(installation) 추출한 MIDlet을 디바이스에 설치하는 기능.
실행(launching) MIDlet을 호출하는 기능.
버젼 관리 설치된 MIDlet을 새로운 버전으로 업그레이드 하는 기능.
삭제(removal) 설치된 프로그램을 삭제하는 기능
[ 표 5 - JAM의 기본 기능 ]

JAM의 구현은 주로 C와 같은 네이티브 언어로 작성된 소프트웨어 모듈로 이루어 지는 데, CLDC 1.0 베타와 MIDP Early Access 1에는 JAM을 통한 애플리케이션 관리를 기본으로 하고 있다. <그림 4>는 JAM을 통한 애플리케이션의 설치 과정에 대한 예이다. 실행과 업그레이드 및 삭제 과정은 일반적인 애플리케이션의 일종으로 보면 된다. 즉, 사용자 인터페이스를 통해 설치한 애플리케이션을 찾아서 수행하고, 업그레이드하고, 삭제하는 작업을 수행하는 하나의 애플리케이션이라고 생각하면 된다는 것이다.
사용자 삽입 이미지
[ 그림 4 - JAM을 통한 애플리케이션 설치과정 ]

이 글의 뒷부분에서 실제로 MIDlet을 개발하고, 배포하는 과정을 살펴보면서 좀 더 구체적으로 언급하겠지만, 우선은 여기서 JAM과 연관하여, MIDlet 수트(suite)의 구성과 애플리케이션 디스크립터, 애플리케이션 라이프 사이클에 대하여 알아 보도록 하자.
아래 그림에서 동작되는 순서를 정리해 보자
1. Descriptor file로 링크되어 있는 WML 문자열을 선택한다.
2. WAP browser로 부터startJAM 를 호출한다.
3. Descripter file을 다운로드한다.
4. JAR file과 icon file을 다운로드한다.
5. JAR file을 저장한다.
6. main class name이름으로 KVM 시작한다.
7. JAR file로 부터 class를 로딩한다.
8. 다운완료 메시지나 과금 작업을 호출한다.

사용자 삽입 이미지
[ 그림 5 - MIDlet배포시 흐름도 ]

사용자 삽입 이미지MIDlet 배포 파일 - JAR.
  앞에서 MIDP 애플리케이션, 즉 MIDlet은 JAR 파일의 형태로 배포되어야 한다고 얘기했다. 이 JAR 파일에는 MIDlet 수트의 패키지가 들어갈 수 있는데, MIDlet 수트의 패키지는 다음과 같은 세 가지의 구성요소를 가지고 있다.
사용자 삽입 이미지JAR 컨텐츠에 대한 설명을 담고 있는 매니페스트(manifest)
사용자 삽입 이미지MIDlet 클래스를 상속한 클래스들과 다른 공유 클래스들
사용자 삽입 이미지MIDlet이 사용하는 리소드 파일들(예를 들면 아이콘, 이미지 등)

매니페스트 파일에 포함되는 JAR 컨텐츠에 대한 설명은 MIDlet 애트리뷰트라고 하는 JAM이 사용할 애플리케이션에 대한 정보이다. 즉, JAM이 애플리케이션을 다운로드하여 설치하고, 업그레이드하고, 실행하고, 삭제하기 위해서는 애플리케이션의 이름, 버전, 제공자, 등의 정보가 반드시 필요하며, 이러한 MIDlet 애트리뷰트를 매니페스트를 통해 제공할 수 있다는 것이다. <표 7>은 MIDP 명세에서 정의된 MIDlet 애트리뷰트들이다. 이러한 애트리뷰트는 다음에 설명할 애플리케이션 디스크립터에서도 정의될 수 있으며, 만약, 애플리케이션 디스크립터와 매니페스트에서 동시에 정의되었을 경우에는 애플리케이션 디스크립터가 우선한다.

애트리뷰트 이름
설 명
MIDlet-Name
MIDlet 수트의 이름
MIDlet-Version MIDlet 수트의 버전 번호. major.minor.micro의 형태로 정의되며, JAM이 설치 및 업그레이드를 위한 정보로 활용.
MIDlet-Vendor MIDlet 수트의 제공자.
MIDlet-Description MIDlet 수트에 대한 설명
MIDlet-<n> JAR 파일안에 포함된 MIDlet의 표시이름, 아이콘, 클래스명. 하나의 JAR 파일에 여러 개의 MIDlet이 포함되어 있을 경우, 번호로 식별하게 되며, <n>은 최소값이 1이고, 반드시 순차적인 숫자를 사용하여야 한다
MIDlet-Jar-URL JAR 파일이 로딩될 URL
MIDlet-Jar-Size JAR 파일의 크기(바이트 단위)
MIDlet-Data-Size MIDlet이 필요로 하는 영속적 데이터의 크기(바이트 단위). 디바이스에서는 이에 따라 추가적인 스토리지를 제공해야 하고, 디폴트는 0이다.
MicroEdition-Configuration 시스템 프로퍼티의 microedition.configuration 값과 동일한 J2ME 컨피규레이션(예를 들어, “CLDC-1.0”)
MicroEdition-Profile 시스템 프로퍼티의 microedition.profiles 값과 동일한 J2ME 프로파일(예를 들어, “MIDP-1.0”)
[ 표 6 - MIDlet 애트리뷰트 ]

애플릿이 java.applet.Applet 클래스를 반드시 상속해야 하듯이, MIDlet도 javax.microedition.midlet.MIDlet 클래스를 반드시 상속해야 한다. JAM은 MIDlet 클래스를 통해 애플리케이션의 시작, 일시정지, 종료 등을 제어하기 때문이다. 그러므로, MIDlet 클래스를 상속한 클래스를 하나의 MIDP 애플리케이션(MIDlet)이라고 볼 수 있으며, 하나의 JAR 파일 안에는 여러 개의 MIDlet이 존재할 수 있다. 하나의 JAR 파일, 즉, 같은 MIDlet 수트에 포함된 MIDlet들은 리소스와 실행환경을 공유한다.
아이콘, 이미지 등의 리소스 파일은 여러 MIDlet들이 공유할 수 있으며, MIDlet 수트, 즉 JAR 파일 안에 함께 포함된다. 사용자가 특정 애플리케이션을 선택해서 실행하기 위해서는 JAM이 최소한의 애플리케이션에 대한 정보를 사용자에게 보여 주어야 하는데, 이는 MIDlet 애트리뷰트에 정의된 이름과 아이콘을 이용할 수 있다. 예를 들어, 다음 MIDlet 애트리뷰트는 ‘프로미 안녕?’이라는 애플리케이션의 이름과, promy.gif 파일 아이콘을 JAM이 사용자에게 보여 주고, 사용자가 선택할 수 있게 한다.

   사용자 삽입 이미지MIDlet-1 : 프로미 안녕?, promy.gif, promy.example.midp.HelloPromy

사용자 삽입 이미지
2.3 애플리케이션 디스크립터, JAD
  JAM이 네트웍을 통해 MIDP 애플리케이션을 다운로드하려면, 우선은 JAR 파일을 봐야 한다. JAR 파일을 추출하는 방법은 여러가지가 있겠지만, 가장 손쉬운 방법이 브라우저를 이용하는 것이다. 웹 브라우저이든, WAP 브라우저이든, 혹은 MME이든 상관없이 브라우저는 컨텐츠, 혹은 파일을 네트웍에서 찾아 다니는 가장 보편적이고 일반적인 방법이다. 그러므로, WAP 브라우저(혹은 MME)가 탑재된 브라우저를 통해 다운로드할 JAR 파일을 찾고, JAM이 그 파일을 다운로드하여, 설치하는 것은 가장 생각하기 쉽고, 구현하기 쉬운 모델이다. 브라우저와 JAM의 연동 문제는 이 글의 마지막 부분에서 다시 생각하기로 하자.

JAR는 인터넷에서 이미 보편화된 파일 포맷이다. 그러므로, 기존의 J2SE 기반의 JAR 파일과 앞에서 설명한 MIDP 수트를 포함한 JAR 파일을 구분할 방법이 없다. 그러므로, 브라우저가 올바르지 못한 J2SE 기반의 JAR 파일을 JAM으로부터 다운로드하게 만들 수 있다. MIDP 애플리케이션만 있는 웹사이트를 별도로 접속할 수 있도록 해서, 이러한 염려를 기우로 만들 수 있다고 해도, 문제는 또 있다. 이미 다운로드하여 설치한 애플리케이션의 JAR 파일을 다시 다운로드하여 설치하려고 했을 경우, 똑똑한 JAM이라면, 사용자에게 그것이 부질없는 일이라는 것을 알려주어야 할 것이다. 그런데, JAM이 앞에서 설명한 JAR 파일 내에 있는 매니페스트 정보를 통해서 애플리케이션에 대한 정보를 알아야 한다면, 일단은 그 JAR 파일을 다운로드하고 난 후에 비로소 이미 설치했던 프로그램임을 알 수 있다. 그렇게 되면, 아까운 통신비용을 회수할 수 있는 방법은 없는 것이다.

그러므로, 네트웍을 통해 JAM에게 MIDP 애플리케이션과 JAR 파일의 정보, 즉, MIDlet 애트리뷰트를 전송할 수 있는 효율적인 방법이 필요하고, JAD(Java Application Descriptor)라는 애플리케이션 디스크립터는 훌륭한 해결책이다. MIDP 명세에는 모든 JAR 파일은 그에 상응하는 JAD 파일을 가질 것을 명시하고 있으며, JAD 파일은 다음과 같은 MIME 타입을 가지고 있다.

     사용자 삽입 이미지MIME 타입 : text/vnd.sun.j2me.app-descriptor
     사용자 삽입 이미지확장자 : jad

JAD 파일의 내용으로는 <표 7>에서 살펴본 MIDlet 애트리뷰트가 들어간다. 여기서는 sun tech tip에서 제공하는 예제에서 하나를 보기로하자. 파일은 run.jad이다.

   사용자 삽입 이미지filename: Run.Jad
MIDlet-Name: SunSamples
MIDlet-Version: 1.0
MIDlet-Vendor: Sun Microsystems, Inc.
MIDlet-Description: Sample suite from MIDP early access workspace.
MicroEdition-Profile: MIDP-1.0
MicroEdition-Configuration: CLDC-1.0
MIDlet-Jar-URL: http://localhost/midp/examples.jar
MIDlet-Jar-Size: 111K
MIDlet-1: Sokoban, /icons/Sokoban.gif, example.sokoban.Sokoban
MIDlet-2: Tickets, /icons/Auction.gif, TicketAuction
MIDlet-3: Colors, /icons/ColorChooser.gif, example.Color
MIDlet-4: Stock, /icons/Stock.gif, example.stock.StockMIDlet
MIDlet-5: Tiles, /icons/Tiles.gif, example.tiles.Tiles
MIDlet-6: ManyBalls, /icons/ManyBalls.gif, example.ManyBalls
MIDlet-7: Sampler, /icons/App.gif, Sampler
MIDlet-8: Properties, /icons/App.gif, example.PropExample
MIDlet-9: HttpTest, /icons/App.gif, example.HttpTest

위의 jad파일을 실행하면 응용프로그램을 선택할수있는 메뉴 같은 것이 나오는데 그것은 MIDlet-<n>부분에 여러 개를 두었기 때문이다.
MIDlet Attribute 중에서 다음은 반드시 들어가야 하는 필수적인 애트리뷰트들이다.
사용자 삽입 이미지MIDlet-Name
사용자 삽입 이미지MIDlet-Version
사용자 삽입 이미지MIDlet-Vendor
사용자 삽입 이미지MIDlet-Jar-URL
사용자 삽입 이미지MIDlet-Jar-Size
사용자 삽입 이미지
IONETKOREAE&D 연구소 제공
사용자 삽입 이미지

 
사용자 삽입 이미지2.4 웹서버에 midp 응용프로그램을 설치.
사용자 삽입 이미지
웹서버에다가 개발된 코드를 올려놓아 폰으로 접근할 수 있게 만들어야 한다. 이 작업의 단계는 다음과 같다.

1. 웹서버에 mime type설정하기
2. jar파일과 jad파일을 웹서버에 올리기
3. 폰으로 접근하여 다운 받고 실행 또는 Emulator에서 실행.

이상의 단계를 거치면 우리의 응용프로그램이 폰 또는 midp 예물레이터에 다운된 후 실행이 되는 것이다.
그럼 각단계마다 자세히 보기로 하자.

1)웹서버에 mime type설정하기
  웹서버에 midp 응용프로그램을 올려놓고 실행하기 위해서는 우선 웹서버에 jad의 mime type을 설정하여 주어야 합니다....
아래의 내용을 아파치의 경우는 conf\mime.types라는 파일에 첨가 시키고 웹서버를 restart하여야 한다.

     사용자 삽입 이미지text/vnd.sun.j2me.app-descriptor jad

그러면 우리의 웹서버는 jad라는 파일을 인식하게 되는 것이다

2) jar파일과 jad 파일을 웹서버에 올리기
  이미 프로그램을 wireless tool kit이나 커맨드라인방식을 이용하여 작성, text하였다고 가정하면 class화일이 있을 텐데 wireless tool kit에서는 jar와 jad파일을 자동으로 만들어 준다. 그러나 커맨드라인 방식에서는 개발자가 손수 만들어 주어야 한다.

* midp-ea1인 경우
  jar cvf (jar파일명) (jar파일에 묶을 class 파일들)
  예) jar cvf test.jar test.class
* midp-fcs인 경우 (midp-fcs인 경우는 아래의 jad파일 생성를 먼저 하여야 한다)
  jar cvfm (jar파일명) (jad파일명) (jar파일에 묶을 파일명)
  예) jar cvfm test.jar test.jad test.class

위의 명령을 실행 하시면 test.jar라는 파일이 생성될것입니다...
.jad파일은 다음과 같이 만들고 적당한 값을 변경해서 넣어 주면 된다.
그럼. 위의 설명대로 jad를 만들어 두어야 한다.

웹서버에 우리가 만든 jar,jad파일을 적당한 곳에 올린다. 여기서는 midp경로아래에 놓았다고 가정하자.

3) 폰으로 접근하여 다운 받고 실행 또는 Emulator에서 실행
  폰에서 실행한다면 VM가능 폰에서 URL입력하는 Page를 찾은 다음 해당 URL을 입력한다.      사용자 삽입 이미지http://xxx.xxx.xxx.xxx/midp/run.jad
그러나 폰이 준비되어 있지 않다면 Emulator에서도 직접서버에 접근해서 프로그램을 down받을 수 있다.

     사용자 삽입 이미지midp -transient http://localhost/midp/run.jad

실행을 하게 되면 Emulator에서 프로그램이 실행되는 것을 볼 수 있다. 실제로 자신의 midp홈 아래에 instapps라는 디렉토리가 생기고 그속에 우리의 jar파일이 다운되어 있을 것이다.
사용자 삽입 이미지
IONETKOREAE&D 연구소 제공
사용자 삽입 이미지



 
3. Midlet
사용자 삽입 이미지
웹서버에다가 개발된 코드를 올려놓아 폰으로 접근할 수 있게 만들어야 한다. 이 작업의 단계는 다음과 같다.

1. 웹서버에 mime type설정하기
2. jar파일과 jad파일을 웹서버에 올리기
3. 폰으로 접근하여 다운 받고 실행 또는 Emulator에서 실행.

이상의 단계를 거치면 우리의 응용프로그램이 폰 또는 midp 예물레이터에 다운된 후 실행이 되는 것이다.
그럼 각단계마다 자세히 보기로 하자.

사용자 삽입 이미지3.1 MIDlet 애플리케이션 라이프사이클
  J2SE에서 자바 애플리케이션의 수행은 main() 메소드로부터 시작한다. MIDP 애플리케이션은 main() 메소드를 가지고 있지 않으며, 있다고 하더라도 JAM은 그것을 무시한다. 이것은 전혀 새롭지 않은 것이다. 자바 개발자라면 이미 애플릿을 통해 그러한 메커니즘에 익숙해져 있기 때문이다.
에플릿의 경우 main()메소드에서 시작하는 것이 아니라 init()에서 시작하는 것을 알고 있을 것이다.
물론, MIDlet은 애플릿과는 전혀 다른 라이프사이클을 가지고 있으며, 애플릿과는 달리, JAM이 MIDlet의 라이프사이클을 관리한다.
[그림 6]는 MIDlet의 라이프사이클에 대한 상태 다이어그램을 보여주고 있다.

사용자 삽입 이미지
[ 그림 6 - MIDlet 라이프사이클 ]

그림에서 보다시피, MIDlet은 다음과 같은 세 가지의 상태를 가지고 있다.

사용자 삽입 이미지Paused : MIDlet이 초기화되고, 정지된 상태. 공유 리소스를 점유하지 않는다.
사용자 삽입 이미지Active : MIDlet이 실행되는 상태.
사용자 삽입 이미지Destroyed : MIDlet이 종료한 상태. 공유 리소스를 해제한다.

JAM은 새로운 MIDlet의 인스턴스를 생성할 때, 이 객체의 디폴트 생성자(인자 없는 생성자)를 호출한다. 그리고, 생성자의 수행 이후에는 MIDlet이 Paused 상태로 있게 된다. 그리고, 그 이후의 상태들간의 전이를 위한 메소드들은 MIDlet 클래스의 추상 메소드들로 정의되어 있고, MIDlet 클래스를 상속한 클래스들은 반드시 이 메소드들을 구현하여야 한다. 각각의 메소드들에서 해야할 작업은 다음과 같다.

사용자 삽입 이미지startApp() : 필요한 리소스에 대한 점유 획득. Active 상태로 전이
사용자 삽입 이미지pauseApp() : 임시적인 리소스들에 대한 점유 해제. Pause 상태로 전이
사용자 삽입 이미지destroyApp() : MIDlet이 종료한 상태. 공유 리소스를 해제한다. Destoryed 상태로 전이

사용자 삽입 이미지
IONETKOREAE&D 연구소 제공
사용자 삽입 이미지



 
4. 주요 개발 스펙
사용자 삽입 이미지
사용자 삽입 이미지4.1 네트워킹
  네트워킹에 대해서는 CLDC의 커넥션 프레임웍에서 일부가 설명되었다. MIDP에서는 CLDC의 커넥션 프레임웍에 대해 확장된 네트워킹에 대한 정의와 구현을 제공한다. MIDP 1.0 명세서는 HTTP 1.1 프로토콜의 서브셋을 지원하고 있고, 이것은 TCP/IP 네트웍의 IP 프로토콜에 대한 구현과, WAP 및 iMode의 게이트웨이를 통한 비IP(non-IP) 프로토콜에 대한 구현을 포함하고 있다.

[그림 6]을 보자. 한 쪽은 WAP/iMode 게이트웨이를 통해서, 다른 한 쪽은 TCP/IP로 직접 ‘오리진 서버(웹 서버)’에 접속하고 있다. 클라이언트 프로그램이나 웹 서버는 이러한 연결 방법의 차이에 대해서 알아야 할 필요가 없다. 클라이언트 프로그램은 URL을 통해 네트웍 연결을 요청할 뿐이고, 웹 서버는 HTTP 요청에 대한 응답을 전송하는 고전적인 임무를 수행하면 된다. 무선망의 연결방법에 의한 차이는 MIDP의 구현자에 의해 해결해야 할 문제일 뿐, MIDP 애플리케이션 개발자는 네트웍 연결방법에 대해서는 고려하지 않아도 된다는 뜻이다.

사용자 삽입 이미지
[ 그림 7 - HTTP 네트웍 연결 ]

이제, HTTP의 실질적인 구현에 대해서 알아보자. MIDP는 다음과 같은 인터페이스를 통해 HTTP 연결을 지원한다.
      사용자 삽입 이미지javax.microedition.io.HttpConnection

이 인터페이스는 <그림 3>에서 본 커넥션 프레임웍의 계층도에서 제일 아래에 있는 ContentConnection을 상속한 인터페이스이다. 이 인터페이스에는 HTTP 프로토콜을 이용하기 위한 모든 상수와 메소드들이 정의되어 있다. 다음은 HttpConnection 인터페이스를 이용해서 HTTP POST 요청을 수행하는 예제이다.
사용자 삽입 이미지

이 예제는 인자로 주어진 URL의 HTTP 연결을 생성하고, HTTP POST를 통해 ‘사랑은 움직이는 거야’라는 메시지를 전달하고, 그 응답을 받는 과정을 구현하고 있다. 이 예제에서 굵은 글씨로 강조된 부분은 HTTP 헤더의 User-Agent와 Content-Language를 지정하고 있는데, 이는 MIDP에서 User-Agent 요청 헤더에 다음과 같은 시스템 프로퍼티의 정보를 포함할 것을 명시하고 있기 때문이다.

사용자 삽입 이미지microedition.profiles
사용자 삽입 이미지microedition.configuration
사용자 삽입 이미지microedition.locale

사용자 삽입 이미지4.2 영속 저장공간
  다음은, MIDP 애플리케이션이 데이터를 영속적으로 저장하고 사용할 수 있는 메커니즘을 제공해 주는 RMS(Record Management System)에 대해서 알아보자.

왜 RMS가 필요할까? 앞에서 CLDC/MIDP 디바이스들에는 파일시스템이 없음을 강조한 바 있다. 그렇다면, 애플리케이션이 실행중에 생성한 데이터는 어떻게 저장할까? 예를 들어, 50개의 스테이지를 가진 게임이 있는 데, 사용자가 49 스테이지를 돌파하고, 잠시 전화를 거느라 애플리케이션을 중단시켰다. 이 경우에 처음부터 새로 게임을 시작해야 한다면, 사용자는 차라리 그 애플리케이션을 JAM을 통해 삭제해 버리게 될 것이다. 그렇게 되지 않기 위해서는 조금 전에 보았듯이, HttpConnection을 통해 리모트 서버에 저장해 두는 방법을 생각할 수 있다. 하지만, 사용자의 현재 위치나, 1인용 테트리스 게임 애플리케이션의 최고기록과 같은 작은 데이터들을 항상 서버에서 가져와야 한다면, 상당히 불합리하다. 그러므로, 게임스코어 같은 데이터를 영속적으로 저장하고, 언제라도 이 데이터를 활용할 수 있는 저장공간이 필요하고, RMS는 이러한 기능을 제공해 주는 레코드 기반의 초소형 데이터베이스이다.
레코드는 바이트 배열로 구성되며, 레코드스코어는 여러 개의 레코드들로 구성된다. RMS는 이러한 영속적 저장공간 기능을 javax.microedition.rms 패키지를 통해 제공하고 있으며, <표 8>은 RMS 패키지가 제공하는 1개의 클래스와 4개의 인터페이스에 대한 설명이다.

클래스 및 인터페이스
설 명
RecordStore 바이트 배열로 이루어진 레코드들을 여러 개 가지고 있는 레코드스토어에 대한 구현 클래스
RecordComparator 두 개의 레코드를 비교하기 위한 Comparator 인터페이스
RecordEnumeration 레코드를 탐색하기 위한 Enumeration 인터페이스
RecordFilter 어떤 레코드가 조건을 만족하는 지 검사하기 위한 필터 인터페이스
RecordListener 레코드에 대한 추가/변경/삭제 이벤트를 감지하기 위한 리스너 인터페이스
[ 표7 - RMS 패키지 ]

사용자 삽입 이미지4.3 타이머 지원
  MIDP에는 javax로 시작하는 확장 API에 대한 정의가 대부분이지만, java.util 패키지에 포함되는 다음 두 가지의 클래스는 예외이다.

      사용자 삽입 이미지java.util.Timer
      사용자 삽입 이미지java.util.TimerTask

Timer 클래스는 애플리케이션에서 특정 작업을 백그라운드 쓰레드에서 스케쥴링할 수 있는 기능을 제공하고, TimerTask는 Timer를 통해서 스케쥴링할 수 있는 특정 작업에 대한 구현 클래스이다. 이 클래스들을 이용해서 특정한 작업을 일정한 시간을 지정해서 한 번만 실행하거나, 일정한 간격으로 여러 번 반복적으로 실행하도록 스케쥴링을 할 수 있다.

사용자 삽입 이미지4.4 유저 인터페이스
  자바는 아키텍처 중립적이다. 이 문장의 의미는 자바의 전통적인 그래픽 유저 인터페이스인 AWT(Abstract Window Toolkit)가 아키텍처에 대해서 중립적(neutral)이라는 것이다. AWT는 MS의 윈도우 시스템과 유닉스 계열의 X-윈도우 시스템에서 ‘비슷하게’ 나타나지만, ‘동일하게’ 보이지는 않는다. 그래서 ‘Abstract’인 것이다. 예를 들어, Button 컴포넌트를 생성하면, 서로 다른 GUI 시스템에서 그 버튼의 모양과 크기는 조금씩 다르다. 이것은 피어(peer)를 통한 컴포넌트의 생성으로 인해서 발생하는 문제이고, 스윙을 통해서 이러한 아키텍처에의 종속성은 해결되었지만, 아직도 GUI는 자바의 아킬레스 건이다.

CLDC/MIDP 플랫폼에서도 마찬가지다. 기존의 AWT를 사용하기에는 너무 무겁고, 서로 다른 다양한 입출력 메커니즘을 가지고 있는 디바이스들에 공통된 유저 인터페이스를 새로 설계하는 일도 녹녹하지 않은 작업이었다. kAWT 프로젝트와 같은 PalmOS 환경에서, AWT를 기반으로 한 유저 인터페이스를 설계하려는 시도가 있기는 하지만, MIDP에서는 결과적으로 전혀 새로운 유저 인터페이스가 설계되었다. lcdui라는 이 새로운 유저 인터페이스야말로 모바일 솔루션을 개발하기 위해 자바 개발자가 만나야 하는 가장 높은 벽이다. 필자 역시 아직 이 벽을 넘어 보지 못했으며, 상세하게 다루기에는 너무 방대한 내용이 될 것이므로, 실제 구현에 필요한 각각의 컴포넌트와 API들에 대해서는 다음 기회를 기약하기로 하고, 여기서는 lcdui의 설계와 그 뼈대를 이루는 구조에 대해서만 살펴보도록 하자.

MIDP는 다음과 같은 디자인 원칙에 입각하여 UI를 디자인하였다.
1. 한 손으로 입력가능해야 한다.
2. 작은 스크린 사이즈에 적용가능해야 한다.
3. 포인팅 디바이스가 없는 단말기에 적용가능해야 한다.
4. 기존의 입출력 방법과 통합되어야 한다.

그리고, MIDP UI는 이러한 기준에 입각해서 다음과 같은 두 가지 레벨의 API를 정의하고 있다.
사용자 삽입 이미지상위 레벨 API : 비즈니스 애플리케이션과 같은,
높은 수준의 포터빌리티를 요구하는 애플리케이션의 제작에 사용될 API.
사용자 삽입 이미지하위 레벨 API : 게임 애플리케이션과 같은,
특정한 목적에 맞게 사용이 가능한 애플리케이션의 제작에 사용될 API.

이러한 MIDP의 유저 인터페이스 API는 javax.microedition.lcdui 패키지를 통해 제공되고 있다. <그림 7>은 핵심적인 유저 인터페이스 API의 클래스 계층도이다.

사용자 삽입 이미지
[ 그림 8 - 유저 인터페이스 클래스 계층도 ]

MIDP는 스크린 기반의 디자인을 가지고 있는데, 스크린은 사용자 입력을 렌더링하는 특정 디바이스 그래픽스를 캡슐화하는 객체라고 정의하고 있다. 이 난해한 정의를 풀어쓰면, 스크린이라는 것은 사용자에게 나타나는 화면이며, 사용자는 한 번에 하나의 스크린 만을 볼 수 있고, 사용자 입력에 대한 처리는 이 스크린에 의해서 이루어 진다고 할 수 있을 것이다.
[그림 7]에서는 두 종류의 스크린이 있음을 알 수 있는데, Screen 클래스와 Canvas 클래스가 그것이다. Canvas 클래스는 게임과 같은 하위 레벨 API를 사용하는 애플리케이션을 위한 스크린을 제공하고, Screen 클래스는 텍스트 박스, 리스트, 등의 상위 레벨 API를 위한 최상위 추상화를 제공한다. Screen 클래스를 상속하는 List, TextBox, Alert와 같은 클래스들은 사전에 정의된 구조를 사용할 수 있는 컴포넌트들이고, 이렇게 사전에 정의된 구조를 사용할 수 없는 TextField, ImageItem, Gauge 등의 클래스들은 Screen 클래스를 상속하는 Form 클래스를 상속하도록 설계되어 있다.

사용자 삽입 이미지4.5 Event처리
  이벤트 처리에서도 상위 레벨 API와 하위 레벨 API에 대한 구분이 있다. 이벤트 처리에서는 <그림 7>의 제일 윗쪽에 놓여진 Command 클래스로 구현된 추상 커맨드에 대한 이해가 필요하다. 대부분의 신형 단말기에는 <화면 2>의 타원 안에 있는 것과 같은 소프트 키가 있다. 그리고 이 소프트 키를 이용해서 스크린의 아래 부분에 있는 ‘About’이라는 커맨드를 선택하여 실행시키거나, 위 아래로의 화면 스크롤을 수행할 수 있다. 이렇게 추상 커맨드와 소프트 키를 통한 이벤트 처리는 상위 레벨 API을 통해 구현이 이루어진다.

void commandAction(Command c, Screen s);

사용자 삽입 이미지
[ 그림 9 - 소프트 키와 커맨드 ]

그러나, 게임 애플리케이션의 경우, 비행기가 8가지 방향으로 날아다니기 위해서는 그림에서와 같이 동서남북의 네 개 뿐인 소프트키를 이용할 수 없다. 그러므로, 이런 경우에는 숫자 키 패드 입력 같은 하위 레벨 API를 이용해서 애플리케이션을 작성할 수 있다.

      사용자 삽입 이미지public void keyPressed(int keyCode);

때로는 상위 레벨 API와 하위 레벨 API를 동시에 매핑하여 지원해야 할 경우도 있을 텐데, 예를 들어, 비행기가 8방향으로 날면서 레이저를 발사해야 하는데, 0번 키가 레이저를 발사하는 키로 매핑 되었다면, 어떤 사용자의 경우는 소프트 키를 이용해서 방향 이동을 하기를 원할 수도 있다. 이럴 경우에는 0번 키의 입력에 의한 하위 레벨 이벤트 처리와 소프트 키 입력에 의한 상위 레벨 이벤트 처리를 동일하게 레이저를 발사하도록 작성할 수도 있다는 것이다.

사용자 삽입 이미지4.6. MIDlet 프로그래밍
  자, 그럼, 이제 실제로 간단한 MIDlet을 개발하고, 배포하고, 테스트 해 보자. 다음은 MIDlet을 개발하는 데 거쳐야 하는 일반적인 순서이다.

1. 프로그램 작성
2. 컴파일
3. 사전검증
4. JAR 파일 생성
5. JAD 파일 작성 및 테스트
6. 웹 사이트 배포

제일 먼저 해야 할 일은 코딩을 하는 것이다. <리스트 2>는 간단한 MIDlet 프로그램인 HelloMIDlet이다. 이 예제는 TextBox 스크린을 하나 생성하고, 여기에 ‘종료’라는 추상 커맨드를 추가한 이후에 사용자가 종료 커맨드를 선택하면, 해당하는 이벤트에 대한 액션으로 프로그램의 수행을 종료하는 기본적인 기능만을 수행한다.

<리스트2> HelloMIDlet.java

import javax.microedition.midlet.*;

import javax.microedition.lcdui.*;

 

/**

* MIDlet예제: HelloMIDlet

*/

public class HelloMIDlet extends MIDlet implements CommandListener {

  private Command exitCommand;

  private Display display;

  public HelloMIDlet() {

     display = Display.getDisplay(this);

     exitCommand = new Command("종료", Command.SCREEN, 2);

  }

  /**

   * startApp() : JAMMIDlet실행할호출한다.

   */

public void startApp() {

     TextBox t = new TextBox("안녕? MIDlet", "테스트", 256, 0);

     t.addCommand(exitCommand);

     t.setListener(this);

     display.setCurrent(t);

  }

   /**

   * pauseApp() : MIDlet일시정지할호출한다.

   */

  public void pauseApp() {

  }

   /**

   * destroyApp() : MIDlet정시시킬호출한다.

   */

  public void destroyApp(boolean unconditional) {

  }

   /**

   *커맨드이벤트에대한액션의처리,여기서는종료커맨드를

   *선택했을destroyApp()메소드를명시적으로호출한다.

   */

  public void commandAction(Command c, Displayable s) {

     if (c == exitCommand) {

        destroyApp(false);

        notifyDestroyed();

     }

  }

 }

 

 


작성된 소스 코드는 다음과 같은 명령으로 컴파일한다. -g:none 옵션은 디버깅 정보를 삭제해 주고, -bootclasspath 옵션은 시스템 클래스 파일을 midp.jar 파일에서 찾도록 지정해 준다. ?d 옵션은 클래스 파일이 classes 디렉토리 아래에 생기도록 지정한다. 디버깅 정보를 삭제하는 이유는 CLDC 클래스 파일 포맷에서 이 부분이 삭제될 것을 명시했기 때문이다.

D:\midp-ea1>javac -g:none -bootclasspath lib\midp.jar -d classes

다음은 classes 디렉토리에 생성된 HelloMIDlet.class 파일을 사전검증하는 것이다. 이 때, 주의할 점은 lib\midp.jar 파일의 압축을 해제해 두어야 한다는 것인데, 이것은 preverify.exe가 JAR 파일 포맷을 인식하지 못하는 것으로 생각되기 때문이다.

D:\midp-ea1\lib>jar xvf examples.jar
D:\midp-ea1>bin\preverify -classpath classes;lib -d preverfied classes

preverified 디렉토리에 사전검증된 클래스 파일이 생성되었으면, 이제 JAR 파일을 생성하도록 하자.

D:\midp-ea1\preverified>jar cvf ..\hello.jar .

이제, JAD 파일을 생성할 차례다. 다음은 hello.jad 파일에 포함될 MIDlet 애트리뷰트들이다.

MIDlet-Name: PromyWorks
MIDlet-Version: 1.0.0
MIDlet-Vendor: promy
MIDlet-Description: Working MIDP Examples
MicroEdition-Profile: MIDP-1.0
MicroEdition-Configuration: CLDC-1.0
MIDlet-Jar-URL: http://localhost/midp/hello.jar
MIDlet-1: HelloMIDlet, /icons/promy.gif, HelloMIDlet

모든 것이 준비되었다면, 다음 명령어를 통해 에뮬레이터를 실행해 보자. < 그림 10 >은 HelloMIDlet의 실행화면이다.

D:\midp-ea1>bin\midp -classpath hello.jar -descriptor hello.jad

사용자 삽입 이미지
[ 그림 10 - HelloMIDlet 실행화면 ]

Posted by 1010