여러분은 자바 가상 머신을 메모리 용량이 적고 자원이 제한되어 있으며 네트워크로 연결된 환경에 적합하게 만들고 싶을 것이다. K 가상 머신 (KVM)의 중심에 특수한 자바 클래스가 있는데, MIDlet이 그것이다. 이 글에서 Soma Ghosh는 여러분에게 MIDlet 클래스의 장단점을 소개하고 여러분 자신의 J2ME 애플리케이션을 구축할 때 이를 활용하는 방법을 소개하겠다. 여러분은 MIDlet의 이론을 배우고 난 후 그녀가 구축하는 샘플 프로그램을 통해 그 기술이 실행되는 것을 확인하게 될 것이다.
이 주제에 대해 내가 작성한이전 글에서 나는 Java 2 Platform, Micro Edition (J2ME)의 기초 사항들에 대해 논의하였다. 그 글을 읽어보지 않은 분이라면 이 글을 읽기 전에 아마도 그것을 먼저 읽어 보아야 할 것이다. J2ME의 가장 중요한 구성 요소가 MIDlet이다. 여기서 우리는 MIDlet의 상태와 상태 애플리케이션 뿐 아니라 이벤트와 예외를 처리하기 위한 기법들을 검토하면서 MIDIet을 상세히 살펴보도록 하겠다. 또한 여기에서 설명된 개념들을 입증해 줄 간단한 애플리케이션을 구축해 봄으로써 결론을 짓도록 하겠다. 이 글을 끝낼 때쯤이면 여러분은 여러분 자신의 J2ME 애플리케이션을 작성하는 중일 것이다.
Mobile Information Device Profile (MIDP)은 이동 전화나 기본적인 수준의 팜탑 장비와 같은 모바일 정보 장비를 타겟으로 하는 자바 API 세트이다. MIDlet은 MIDP 애플리케이션을 말한다. 이 글에서는MIDlet과MID 애플리케이션라는 용어가 교대로 사용된다. MIDlet은 J2ME 실행 환경의 구성 요소가 된다.
MIDlet은 모바일 장비에서 작동하도록 설계되었으며 자바 가상 머신의 핵심만 모은 버전인 K Virtual Machine (KVM)의 애플리케이션 관리자에 의해 실행되고 제어되도록 만들어졌다.javax.microedition.midlet.MIDlet
클래스는 MIDlet과 애플리케이션 관리자 사이의 인터페이스로 작동한다. 이 클래스의 메소드는 애플리케이션 관리자가 MIDlet을 만들고 구동시키고 중지시키고 없애도록 해준다.
J2ME 애플리케이션은javax.microedition.midlet.MIDlet
클래스를 확장해야 하는데, 이는 다음 작업들에 대한 프레임워크를 제공한다.:
- 애플리케이션 관리자가 MIDlet 상태 변화를 통지하고 요청함으로써 MIDlet을 제어하도록 한다.
- MIDlet이 애플리케이션 관리자가 관리하는 애플리케이션 레지스터리인애플리케이션 디스크립터 (application descriptor)로부터 특성을 검색할 수 있도록 한다.
그림 1은 MIDlet과 애플리케이션 관리자 간의 상호작용을 보여준다.
그림 1. MIDlet 환경

![]() |
![]()
|
MIDlet은 그 수명 주기 동안 다양한상태로 있을 수 있다. 이 상태들은 애플리케이션 관리자가 런타임 환경 내에서 여러 MIDlet들의 행동을 관리하도록 해 준다. 애플리케이션 관리자는 MIDlet들을 개별적으로 시작시키고 중지시킴으로써 주어진 시점에 어떤 MIDlet이 작동할지 선택할 수 있다. 애플리케이션 관리자는 또한 MIDlet의 상태를 유지보수한다. MIDlet은 다음 상태들 중 하나로 있을 수 있다.:
- 작동 :MIDlet은 구동시에 작동 상태로 들어가고 일부 자원을 차지할 수 있다.
- 중지 :중지 상태에서 MIDlet은 공유된 자원을 해제하고 정지한다.
- 파기 :이것은 MIDlet의 종료 단계이다. 종료된 MIDlet은 모든 자원을 해제하고 애플리케이션 관리자에 어떤 영속적인 상태를 저장해야 한다.
그림 2는 MIDLet의 상태 변화를 보여주고 있다. 화살표는 허가된 상태 변화를 나타낸다. 예를 들어, 작동 상태의 MIDlet은 중지 상태나 파기 상태 중 하나로 이동할 수 있다.
그림 2. MIDlet의 상태 변화

![]() |
![]()
|
애플리케이션 관리자는 상태를 바꾸기 위해 MIDlet에 특정 메소드를 호출한다. MIDlet은 이 메소드를 구현하여 자신의 내부 행동과 자원 활용을 애플리케이션 관리자가 지시하는대로 업데이트시킨다.:
startApp()
: 이 메소드는 MIDlet에게 작동 상태로 들어간다는 신호를 보내며, MIDlet의 대화형 화면 환경을 설정하기 위한 초기화 절차들로 구성되어 있다.
pauseApp()
: 이 메소드는 MIDlet에게 작동을 멈추고 중지 상태로 가라고 신호한다.
destroyApp()
: 이 메소드는 MIDlet에게 작동을 종료하고 파기 상태로 가라고 지시한다.
MIDlet은 스스로 몇 가지 상태를 개시하고, 이 메소드들 중 하나를 호출하여 애플리케이션 관리자에게 이러한 상태 변화들을 통지할 수 있다.:
notifyDestroyed()
: 자신이 파기 상태로 들어갔음을 애플리케이션 관리자에게 통지하기 위해 MIDlet이 사용하는 메소드이다.
notifyPaused()
: 이 메소드는 MIDlet이 작동 상태로 있고 싶지 않으며 중지 상태로 가고 싶다고 애플리케이션 관리자에게 통지한다.
resumeRequest()
: 이 메소드는 MIDlet이 작동 상태로 가고 싶어함을 표시하는 메커니즘을 제공한다. 이 메소드에 대한 호출은 애플리케이션 관리자가 사용하는데, 어떤 애플리케이션이 작동 상태로 갈지를 결정한다. 애플리케이션 관리자가 한 MIDlet을 활성화하기로 결정하면 그 MIDlet의startApp()
메소드를 호출할 것이다.
MIDlet은 애플리케이션 관리자로부터 지정된 특성들을 검색하는 메커니즘을 받았다.getAppProperty()
메소드가 그것이다. MIDlet 배치의 일부분으로 제공되는 이 특성들은 애플리케이션 디스크립터 파일과 manifest가 조합된 것으로부터 얻어진다.
startApp()
혹은pauseApp()
동안 런타임 예외가 발생하면 MIDlet은 즉시 파기될 것이다.
![]() |
![]()
|
사용자가 MIDlet과 상호작용할 때,이벤트가 생성된다. MIDlet은 자신의 이벤트 처리 메커니즘의 일부분으로 특정 인터페이스들을 제공하여 애플리케이션이 이벤트를 통지받고 이에 대해 응답할 수 있도록 한다. 각 인터페이스는콜백 (callback) 이라고 알려진 메소드를 제공하는데, 이것은 이벤트에 응답하여 애플리케이션이 실행시키는 프로그래머 정의 메소드를 호출하는 것이다.
MIDlet이 실행되고 있는 동안 생성되는 이벤트들은 다음과 같다. :
- 화면에서 입력되는 명령문
- 화면 아이템의 내부 상태의 변화
- MIDlet과 관련된 폰 데이터베이스의 내부 상태의 변화
MIDlet 이벤트 처리 메커니즘은listener모델에 기반하고 있다. 각 객체는 이벤트를 통지받고 여기에 응답할 수 있도록 Listener를 구현해야 한다. 이를 위해 MIDlet은ItemStateListener
,CommandListener
,RecordListener
라는 세 인터페이스를 제공한다. 각각을 상세하게 살펴 보자.
![]() |
![]()
|
CommandListener
는 화면 출력될 수 있는 아이템 (예 : 화면에 입력되는 명령어)들에서 생성되는 이벤트를 MID 애플리케이션에게 통지하는 책임을 가진다.CommandListener
는 listener를 확장하는 객체가 구현해야 하는commandAction(Command c, Displayable d)
메커니즘을 제공한다. 이 메소드는 명령어 이벤트가Displayable d
에 발생했음을 가리킨다.
![]() |
![]()
|
ItemStateListener
는 화면 아이템 (예 : 화면에 있는TextField
의 값)의 내부 상태 변화를 MID 애플리케이션에게 통지하며, 아이템의 내부 상태가 사용자에 의해 변경되었을 때 호출되는itemStateChanged(Item I)
메소드를 제공한다. 내부 상태의 변화는 사용자에 의해 발생한다.:
ChoiceGroup
에서 선택된 값들 변경하기
- 대화형
Gauge
의 값 조정하기
TextField
에 값을 입력하거나 수정하기
DateField
에 날짜나 시간 입력하기
여러분은 내가 작성한이전 글에서 이들 화면 아이템에 관해 더 배울 수 있다.
아이템에 언제 새 값을 입력해야 하는지의 결정은 장비에 달려 있다. 예를 들어,TextField
내에 텍스트 편집을 구현하는 것은 장비에 따라 아주 다양하다.
ItemStateListener
는 애플리케이션이 대화형 아이템의 값을 변경한 경우에는 호출되지 않는다. 사용자가 변경했을 때만 호출된다.
![]() |
![]()
|
RecordListener
의 책임은 애플리케이션과 연관되어 있는 레코드 스토어에서 레코드 변경과 관련된 이벤트를 받는 것이다. 이것을 사용하려면 애플리케이션은RecordListener
가 제공하는 다음 메소드들을 구현해야 한다. :
recordAdded()
: 레코드가 레코드 스토어에 추가되었을 때 호출된다.
recordDeleted()
: 레코드 스토어의 레코드가 변경된 후에 호출된다.
recordChanged()
: 레코드 스토어에서 레코드가 삭제된 후 호출된다.
![]() |
![]()
|
MIDlet이 실행될 때 객체들이 이벤트에 응답할 수 있도록 Listeners가 이들 객체들에 연결되어야 한다. MIDlet 클래스는 이벤트 listener를 객체와 연결시키기 위한 특정 메소드들을 제공한다.:
setCommandListener()
: 이 메소드는 모든 명령어에 대한 listener를Displayable
에 설정하며, 이전의CommandListener
를 바꾼다
setItemStateListener()
: 이 메소드는 화면 아이템에 대한 아이템 상태 listener를 설정하며, 이전의itemStateListener
를 바꾼다.
addRecordStateListener()
: 이 메소드는 레코드 스토어에 레코드 상태 listener를 추가한다.
그림 3은 MIDlet 이벤트 처리 모델이다.
그림 3. MIDlet 이벤트 처리

![]() |
![]()
|
MIDlet은예외 처리 기능을 사용해 예외적인 상황을 처리할 수 있다.예외란 프로그램이 실행되는 동안 정상적인 명령의 흐름을 혼란시키는 이벤트를 말한다. MIDlet은 자바 예외 처리 메커니즘의 모델을 보존하고 있다. 그러한 에러가 메소드에 발생했을 때, 메소드는 예외 객체를 만들어 이를 런타임 시스템에 넘겨 준다. 예외 객체는 예외의 유형 및 예외가 발생했을 때 프로그램의 상태 등 예외에 관한 정보를 가지고 있다. 그러면 런타임 시스템은 에러를 처리하기 위해 몇 가지 코드를 발견해야 한다. 자바 전문 용어에서, 예외 객체를 만들어 이를 런타임 시스템에 넘겨 주는 것은예외를 던진다(throwing an exception)라고 불린다.
앞에서 살펴 보았듯이, MIDlet은 수명 주기 동안 다양한 상태로 있을 수 있다. MIDlet은 요청된 MIDlet 상태 변화가 실패했음을 함축적인MIDletStateChangeException
을 던짐으로써 알려준다.
자바 예외 처리에 관한 상세 정보는 아래의참고 자료부분을 참조한다.
![]() |
![]()
|
이번 섹션에서 우리는 다양한 단계에서의 MIDlet의 역할을 보여주는 J2ME 이미지 애플리케이션을 개발할 것이다. 이 애플리케이션은 또한 이벤트 처리 메커니즘을 통해 종료하는 기능도 가질 것이다.
PhoneImage
애플리케이션은 자신의 MIDIet 메소드에 대한 호출에 대응하여 하나의 생성자를 불러온다. 이 생성자는 전화기 화면 환경, 전화기 화면 아이템, 애플리케이션을 종료시키기 위한 화면 명령어를 생성하여 초기화 절차를 수행한다.
전화기 화면 환경은Display
클래스에 의해 표시된다. MIDlet당 정확히 하나의Display
인스턴스가 있고,PhoneImage
생성자는getDisplay()
메소드를 호출함으로써 그 인스턴스에 대한 참조를 얻는다.:
|
이 애플리케이션의 UI 측면은 그래픽 이미지 데이터를 보유하기 위해 사용되는javax.microedition.lcdui.Image
클래스이다.Image
객체들은 화면 장치와 독립적으로 존재한다. 그들은 화면과 무관한 메모리에만 존재하며, 애플리케이션이 명시적인 명령어(Canvas
의paint()
메소드에서처럼)를 발행하지 않는 한 혹은Image
객체가Form
화면이나Alert
화면 내에 위치하고 그 화면이 갱신되기 전까지는 화면에 표시되지 않을 것이다.
이미지는 그들이 만들어진 방식에 따라가변일 수도 있고불변일 수도 있다. 불변 이미지는 일반적으로 자원 번들, 파일 혹은 네트워크에서 이미지 데이터를 로딩함으로써 만들어진다. 이들은 한 번 만들어지면 수정할 수 없다. 가변 이미지는 화면과 무관한 메모리에서 만들어진다. 애플리케이션은 이를 위해Graphics
객체를 명확하게 생성한 후 이들을 표시할 수 있다.Alert
,Choice
,Form
혹은ImageItem
객체에 있는 이미지는 불변이어야 한다. 런타임 환경이 애플리케이션에게 통지하지 않고 언제든지 화면을 업데이트하기 위해 이들을 사용할 수 있기 때문이다.
PhoneImage
애플리케이션은javax.microedition.lcdui.Image
클래스의createImage(String resourceName)
메소드를 호출함으로써 불변 이미지 아이템을 생성한다. 이 메소드는 지정된 자원에서 얻어지는 해독된 이미지 데이터들로부터 불변 이미지를 생성하는데, 이 데이터들은 장비 구현에 따라 자원 번들 내에 혹은 파일 시스템상에, 혹은 네트워크상에 존재할 수 있다.resourceName
은 지원되는 이미지 포맷 중 하나로 된 이미지 데이터를 포함하고 있는 자원의 이름을 표시하고 있다. 구현은 PNG (Portable Network Graphics) 포맷 v.1.0에 저장되어 있는 이미지들을 지원해야 한다.
자원 명이 null일 경우 메소드는NullPointerException
을 던진다. 자원이 존재하지 않거나 데이터를 로딩할 수 없거나 이미지 데이터를 해독할 수 없는 경우에는IOException
을 던진다. Listing1은 이 모든 것이 어떻게 작동하는지 보여준다.
Listing 1.이미지 생성하기
|
PhoneImage
애플리케이션은startApp()
메소드를 호출함으로써 작동 상태로 들어간다.Image
아이템은Form
객체 (Listing 2 참조)에 내장되어 있다. 구현은 화면 배치, 순환 및 스크롤링을 처리한다.Form
역시 화면 명령어와 연결되어 있다.
Listing 2.전화기 화면에 이미지 추가하기
|
startApp()
메소드는 Listing 3과 같이 각 명령어를 listener에 연결하고Form
을 현재 표시 가능한 아이템으로 정의함으로써 이벤트 처리 메커니즘을 설정한다.
Listing 3. 화면에 사용자 상호작용 특성 추가하기
|
애플리케이션 관리자가pauseApp()
메소드를 호출하면PhoneImage
애플리케이션이 정지 상태로 들어간다. 이는 백그라운드 작업이 없거나 레코드 스토어가 종료되었을 때 사용하는 무연산 메소드이다.destroyApp()
메소드는PhoneImage
애플리케이션의 종료 단계를 시작시킨다. 이 메소드는 모든 자원을 해제하는 책임을 가지고 있다.
commandAction
메소드 (Listing 4 참조)는PhoneImage
MIDlet이 명령에 응답하도록 하며, 모든 화면 명령어 작업시 호출된다.exitCommand
가 호출되었을 때 MIDlet을 종료시키는exitCommand
의 핸들러가 정의된다.
Listing 4. 명령어 콜백 구현하기
|
Listing 5는PhoneImage
애플리케이션의 전체 소스 코드이다. :
Listing 5. PhoneImage
|
그림 4는 장치 에뮬레이터상에서 실행되는 애플리케이션이다.
그림 4. PhoneImage 애플리케이션

![]() |
![]()
|
모든 이동 전화나 호출기에서 작동하는 무선 애플리케이션의 작성이 MIDlet으로 훨씬 쉬워졌다. MIDlet의 잘 정의된 아키텍처는 광범위한 기능을 제공하지만 요약된 아키텍처를 유지하는 잘 정의된 메소드 세트를 기반으로 구축되었다. 나는 이 글이 여러분 자신의 MIDlet 구축에 착수하는데 도움이 되기를 바란다.
![]() |
![]()
|
- developerWorks worldwide 사이트에서 이 기사에 관한영어원문.
- 이 글의 필자가 이전에 작성한 "Think small with J2ME" (developerWorks) : J2ME 기술에 대한 소개
- JavaWorld의예외 처리에 관한 유용한 자료들
- IBM의Pervasive Computing사이트
- J2ME 홈페이지
- MIDP홈페이지
- 자바 무선 애플리케이션 시도에 관한광범위한 글들
- J2ME 무선 툴킷과 함께 제공되는 MIDP API 문서