[4th Seoul Workshop]한글 Win95상에서의 자바 한글 입력기구현

임 국주
135-080 서울특별시 강남구 역삼동 703-8
주식회사 비트컴퓨터 기술연구소/CyberBIT
E-mail : ldragon@www.bit.co.kr

1. 서론

자바 한글 입력기는 전자 결재 시스템을 구축하는 과정에서 자바로 클라이언트 프로그램을 작성하다가 만들어진 부산물이다. 클라이언트를 자바 애플릿으로 구현하는데 있어서 한글이 출력은 되는데, 입력은 되지 않아서, 많은 고민을 하던 끝에 작성을 하게 되었다.

특히 Web상에서의 전자 결재 시스템은 네트워크 상의 보안이 필수적인데 그것에 대한 대책의 하나로 자체 클라이언트와 서버를 프로그램 하는 방법을 선택했고, 또 그것이 웹 브라우저와 데이터 베이스와 연계되어야 하므로 자바 언어를 선택하지 않으면 안되게 되었다.

그래서, 일단 자바 한글 입력기를 구현하기로 하였는데, 자바 한글을 구현하기 위해서는 자바 상에서 한글 오토마타를 이용하여 프로그램을 작성하는 것이 정석인데, 이것은 시간과 노력을 너무 많이 요구하므로 뭔가 새롭고 간단한 방법을 고안해야만 했다.

한참을 고민하던 중 이상한 의문이 내 머리 속을 떠나지 않았다. 분명히 자바는 유니 코드를 지원하기 위해 2바이트를 char형의 기본 구성으로 하고 있으며, win95상에서는 자바의 한글 출력이 되며, 한글 입력에서 다만 수평 스크롤의 컨트롤이 안되는데 이것만 잘 처리하면 되지 않을 까 하는 것이다.

그래서 자바에서 한글 입력시 이 부분만 잘 처리하면 될 것이라는 확신을 가지면서 먼저 한글 입력시의 시나리오를 생각하게 되었다.

먼저 한글 입력 모드로 바뀌게 될 것이고, 키 하나가 눌려지면 어떠한 이벤트가 발생할 것이고, 다음 그 이벤트를 받아 처리를 하고 그 입력 값을 출력 할 것이다.

이렇게 어느 정도의 시나리오를 생각해보니 그 다음 내가 처리해야 할 부분이 명확해졌다. 우선 이벤트 발생을 가로채고, 그 다음 한글을 처리하고, 다시 재출력을 시키는 방식으로 작업을 하기로 하였다. 이렇게 일주일을 똑딱 거려 만든 것이 공개되지 않은 최초의 자바 한글 입력기가 된 것이다.

이런 식으로 개발할 때의 장점은 한글 윈도우의 자원을 그대로 쓰고 있기 때문에 글씨체, 폰트의 크기 등에 구애되지 않으며 차후 윈도우의 개발 버전에 따라 외국어 지원도 간단하게 된다는 것이다. 단점이 아닌 단점으로는 윈도우용이므로 유닉스에서는 효과가 없으며, 벼락치기로 개발된 것이므로 소스의 코딩이 매끄럽지 못하고 버그도 있을 수 있다는 것이다.

아울러 명백한 버그 아닌 버그는 한글 윈도우95가 완전한 완성형 한글을 지원하지 못하는 관계로 부분적으로 완성형 한글 집합체에서 빠진 글자는 코드에 포함시키지 않았음을 밝힌다.

2. 자바의 특징

자바 한글 입력기에 대하여 자세히 설명하기 전에 먼저 자바의 특징에 대하여 간단히 알아보자.

너무 많이 알려진 이야기이기 때문에 식상할 수도 있지만, 자바의 이런 특징들은 아무리 강조해도 결코 지나치지 않은 것들이다.

결코 아닐 수도 있지만, 자바는 다른 언어들에 비하여 매우 간단한 구조를 가진다.

자바는 C++와 매우 유사하지만, 꼭 필요하지 않은 고급 프로그래밍 언어의 특징은 모두 빼고, 꼭 필요한 기능으로만 채운 언어이다. 그래서 다른 고급 언어에 대한 이해가 있다면 자바를 이해하기가 훨씬 쉽다.

자바는 객체 지향 프로그래밍 언어이다. 자바에서 숫자와 부울형과 같은 형을 제외한 대부분이 객체로 이루어져 있다. 또한 자바는 단일 계승 클래스 구조를 지원한다. 이것은 한 번에 하나의 클래스가 하나의 선조로부터만 상속될 수 있음을 의미한다. 어떤 언어들은 다수의 계승을 지원하지만 이것이 오히려 언어에 대한 이해를 혼란시킬 수도 있고, 언어를 불필요할 정도로 복잡하게도 할 수 있기 때문에 자바는 지원하지 않는다.

자바 프로그램이 실행될 때 프로그램은 먼저 바이트 코드로 컴파일 된다. 바이트 코드는 기계 명령어와 매우 유사하므로 자바 프로그램은 매우 효율적이다. 하지만 바이트 코드는 특정한 기계에 한정된 것이 아니기 때문에 자바 프로그램은 프로그램을 다시 컴파일 시킬 필요 없이 다른 많은 컴퓨터에서 실행할 수 있다.

자바 프로그램은 바이트 코드로 컴파일 되기 때문에 자바를 지원하는 어떠한 플랫폼에서도 실행시킬 수 있다. 새로운 기계 상에서 실행시키기 위해서 자바 프로그램을 다시 컴파일 시킬 필요는 없다. 자바 언어는 모든 컴퓨터에서 같은 방법으로 동작한다.

유닉스나 윈도 95와 같은 대부분의 컴퓨터 시스템은 멀티 태스킹을 지원한다. 자바는 언어에 내장된 멀티 태스킹을 지원한다. 이것이 바로 멀티 스레드이다. 멀티 스레드 환경에서 프로그램을 작성하는 것은 동시에 여러 가지 일이 발생하기 때문에 어렵다. 그러나 자바는 프로그래밍을 쉽게 하는 동기화 클래스를 지원하므로 쉽게 이런 문제에 대처할 수 있다.

C나 C++로 프로그램을 작성하다보면, 사용되는 메모리의 할당 및 해제에 대하여 주의 깊게 살펴보아야 한다. 그러나 자바에서는 메모리 관리에 대하여 걱정할 필요가 없다. 자바는 메모리를 검사하여 더 이상 사용되지 않는 메모리를 자동으로 해제시키는 기능을 제공한다. 이것은 자바로 프로그램을 쉽게 만들 수 있게 해주며 프로그래머가 메모리 관리에 관하여 결코 걱정하지 않도록 해준다.

전통적인 프로그램 언어들은 컴퓨터의 모든 부분의 메모리를 액세스할 수 있다. 따라서 프로그램은 메모리에서 문제를 발생시킬 수 있는 여지가 있는 부분들의 값을 변경시킬 수도 있다. 그러나 자바 프로그램은 단지 허락 받은 부분의 메모리만을 액세스할 수 있다. 자바 프로그램은 의도하지 않은 변경이 일어나지 않도록 한다.

자바는 개발 당시부터 메모리의 용량이 작은 컴퓨터에서 작동하도록 설계되었기 때문에 상대적으로 다른 컴퓨터 언어에 비하여 덩치가 작다. 자바 인터프리터는 단지 몇 백 킬로바이트 상에서도 동작한다.

자바는 포인터를 가지고 있지 않으며 실행하기 전에 자바 프로그램을 검증하기 위해서 강력한 타입 체크 기능을 지원한다. 따라서 검증된 자바 프로그램은 자바가 설정한 어떠한 제한도 넘지 않음을 보장하며 안전하게 실행될 수 있다. 자바의 바이트 코드 검증은 웹 브라우저가 애플릿이 바이러스를 포함하지 못하도록 확인하는데 사용된다.



3. 자바 한글 구현

그럼 이제 자바 한글 입력기 구현 방법에 대해서 알아보자.

우선 참고사항으로 먼저 자바의 문자체계에 대해서는 자바의 기본적인 참고 서적을 필독하면

간단히 이해할 수 있으며, 특히 한글과의 관계에 대해서는 Internet 9월호의 장 규오씨의 기고란을 참고 하면 될 것이며, 자바의 한글 구현에 끝까지 최선을 다하는 엘림네트에 격려의 말씀을 올리며 지금 여기 밝힌 구현 방법과 소스는 한글 윈도우상에서만 유효하며 가장적은 노력으로 한글 입력기를 구현하는 방법일 것이다.

다시 본론으로 들어가서 자바에는 입력을 받는 가상 윈도우 툴킷 패키지 중의 하나인 TextField라는 클래스가 있는데 이것이 우리가 이용해야 할 문제의 클래스이다.

소스를 보면 알 수 있듯이 그렇게 어려운 부분은 없을 것이다.

기존의 C프로그램에서의 Include 와 같은 기능을 하는 것이 자바에서는 Import라는 것은 아실 것이고, 상속받을 클래스인 TextField 와 TextArea를 import 하고, key 입력의 event를 처리해야 하므로 반드시 가상 윈도우 툴킷 패키지 중의 하나인 Event 클래스를 import해야한다.

그 다음 임의의 새로운 클래스를 TextField 에서 파생시키는데 이것은 TextField의 여러 자원을 최대한 사용하기 위해서이다.

자바 한글입력기의 주된 엔진 역할을 하는 것은 다름 아닌 keyDown 부분인데 이것은 key가 눌러졌을 때 이 함수를 실행시켜준다.

이 부분이 제일 중요하므로 자세히 다루어 보자.

우선 윈도우상에서 key입력이 있을 때 발생되는 이벤트로는 keyUp 과 keyDown이 있는 데, 하나의 키 입력이 있을 때마다 윈도우는 그 키에 해당하는 ASCII코드 값을 자바의 keyUp 이벤트에 담아 주면 자바의 가상 윈도우 툴킷은 현재 포커스 되어 있는 Component의 keyUp 함수를 실행시켜준다.

이것은 Component 의 상위 클래스에 정의 되어있는데 자세한 부분은 JDK의 source부분에 있는

awt의 package 소스를 참조하길 바란다.

다시 주제로 돌아와서 이 keyUp이벤트로는 만족할만한 결과를 만들 수 없는 데, 그것은 하나 하나의 key이벤트를 유발하고, 이 것 전부를 Control 해야하므로 기존의 한글 오토마타 처리와 크게 다른 방법이 아닌 것이기 때문이다.

그럼 이제 keyDown 이벤트에 대해서 살펴보자.

여기서는 key이벤트가 keyUp과는 다르게 발생되는데 그것은 윈도우95상에서 한글 입력 시에 모든 key이벤트를 한글윈도우95의 standard input 한글 처리기가 잡아서 한글 한 자가 완성되었을 때 keyDown이벤트를 연속으로 두 번 발생시켜주는 것 같다.

이것은 한글윈도우95가 완성형 한글을 지원한다고 할 때 key하나 하나의 처리는 윈도우 자체가 처리하도록 하고 하나의 한글의 글자가 완성되었을 때 그 글자의 완성형코드 값을 keyDown의 이벤트에 두 번 나누어 하나는 두 바이트 중 상위 한 바이트를 연달아 하위 한 바이트를 얻을 수 있다는 것이고, 이것으로 그 글자의 값을 알 수 있다는 것이다.

그래서 연속으로 발생하는 이 keyDown이벤트를 가로채어 잘 처리해주면 한글의 완성된 글자를 얻을 수 있고, 이 것을 버퍼링 해주면 자바에서 한글 입력이 가능 해진다는 것이다.

그럼 소스의 특징적인 부분을 살펴보자.

Public synchronized boolean keyDown(Event evt,int key)

의 부분에서는 상위클래스의 keyDown함수를 오버라이드한 부분인데 개념적인 것은 위 부분에 언급한 대로이며 참고로 주지해야 할 부분은 synchronized 인데 이것은 자바의 멀티 스레드의 스케쥴링에 대한 것에 대해 조금 기초지식이 필요하다.

금번 프로젝트에서는 MFC 의 스레드 기법을 이용한 화상회의시스템도 개발했는데 이와 같은 스레드의 개념을 알아두면 프로그램의 다양한 기능을 구사할 수 있을 것이다.

선점형 시스템에서의 프로세스(스레드)는 시간 또는 인터럽트에서 스케쥴링이 일어나는데 그것은 하던 작업을 중단하고 다시 자기 차례가 올 때까지 Sleep을 한다는 것이다.

이것은 굉장히 중요한 데 다름 아닌 양쪽의 프로세스(스레드)가 하나의 변수를 공유한다던가 또는 순서적인 절차에 근거해서 트랜젝션이 일어나기를 원할 때는 주의해야 하는 부분이다.

이러한 점을 감안해서 자바에서는 synchronized라는 키워드를 주어 선점당하지 않게 배려하고 있는 것 같다.

파라미터 안의 값은 이 함수를 호출하면서 채워지게 되는데 이 때 우리가 체크하는 것은 key값이다.

그래서, 소스의 숫자들은 key 값인데 한글입력모드와 아닌 것을 구별해야 하므로 약간의 어려움이 있었고 각 입력상태에서의 수평 스크롤을 Control해야 하므로 그것이 힘들었다.

그럼, 아래 코드를 보면서 분석해보자.

static boolean dotStatus = false;

static boolean korWait = false;

static int Arrow = 0;

String korString;

boolean korbyte = false;

static char korChar[] = new char[2];

위 코드에서 여러 변수가 있는데 기본적으로 중요한 변수는 korWait 와 korString 과 korChar[]

인데 여기에 대해 잠깐 생각해 보자.

korWait변수는 한글 입력 모드에서 한글 한 자가 완성될 때 발생되는 연속적인 두 번의 keyDown Event를 체크하기 위한 것인데 첫 번째 keyDown Event중 완성형 한글key 값의 범위내의 상위 바이트를 검사하여 한글key값일 때는 korWait를 True로 세팅시키고, korChar[0]에 그 값을 얻는다.

이것은 정확한 완성된 한글 한 자를 받아들이기 위해서이며, 연속된 두 번째 keyDown Event에서 korChar[1]에 key값을 얻고, 그 것의 버퍼링을 위해서 현재의 문자열 값을 getText의 함수를 사용해서 korString에 얻은 뒤 여기에 세팅된 현재의 포지션에 방금 입력된 완성된 글자를 삽입, 또는 첨가시키고 다시 setText함수를 사용해서 세팅 시킨다.

이 시나리오가 자바 한글입력기의 기본적 골격인데, 프로그래밍을 어느 정도 하신 분께서는 이 정도에서 자신의 자바 한글 입력기를 만들 수 있을 것이다.

자바 한글 입력 프로그램을 하면서 어려웠던 것은 한글 입력 모드에서의 Enter Key라든지, 좌우 화살표 키, 점등의 입력이 있을 때는 한글 입력기 시나리오 자체에 버그가 생겨버려서 이러한 것을 처리하기 위해서 뜻하지 않은 코드를 생성시켜야만 했던 것이다.

예를 들면, 점의 입력이라든가, 자음의 연속적인 입력이 있을 때는 한글 입력 순서가 다시 엉망이 되버려서 이러한 것을 수정하는 데 조금 애를 먹었다.

그리고, TextArea 는 TextField와 같이 keyDown부분만 Copy하면 된다.







4. 자바 한글 입력기 사용하기

다음으로는 이 자바 한글 입력기의 사용에 대해 알아보겠다.

이렇게 만들어진 TextFieldKor 클래스와 TextAreaKor 클래스를 TextField 와 TextArea 대신 사용하면 되고 그 사용 실례를 아래 그림에서 보였다.



[그림 1]



<그림 1> 에 보는 바와 같이 이것은 Window Resource를 사용하므로 Window의 한영 표시기의

모습이 제대로 작동하는 것을 볼 수 있을 것이다.

이것은 간단한 알고리즘이지만 지금의 Interner 열풍의 환경에 맞추어 저마다 구축하려는 Interanet Business에 개발의 확장성에 비추어 볼 때는 Font의 기존의 활용 및 개발과 기타 Window에서 지원하는 외국어를 자바로 구현할 수 있는 구현기법으로 생각되므로 여러 곳에서 활용될 수 있을 것이다.

class TextFieldKor extends TextField {

//한글 입력 모드에서의 이전의 키 입력이 dot였을 때

static boolean dotStatus = false;

static boolean korWait = false;

static int Arrow = 0;

String korString;

static char korChar[] = new char[2];

// 생성자

TextFieldKor()

{

super("");

}

TextFieldKor(int cols)

{

super(cols);

}

// 어떤 문자열을 가지고 생성자호출

public TextFieldKor(String text)

{

super(text);

}


public synchronized boolean keyDown(Event evt,int key)

{

//Enter Key

if(key == 10){

// 한글 입력모드의 상태를 체크

if(Arrow == 3) {

Arrow = 1;

// 현재의 Position을 구한다.

int selStart = getSelectionStart();

//버그로 인한 거지만 반복된 글자를 지우고 정상적인 문자열로

Buffering을 한다.

korString = getText().substring(0,getSelectionStart()-2)

+ getText().substring(getSelectionStart());

setText(korString);

select(selStart,selStart);

}

return false;

}

//왼쪽 화살표 key

if(key == 1006 ){

if(Arrow == 3) {

Arrow = 1;

int selStart = getSelectionStart();

korString = getText().substring(0,getSelectionStart()-2)

+ getText().substring(getSelectionStart());

setText(korString);

select(selStart,selStart);

}

return false;

}

if(key == 1007) {

if(Arrow == 3) {

Arrow = 1;

int selStart = getSelectionStart();

korString = getText().substring(0,getSelectionStart() -2) +

getText().substring(getSelectionStart());

setText(korString);

select(selStart,selStart);

}

return false;

}


if(key == 164 && (korWait == false)) {

return true;

}

// 첫 번째 한글키 이벤트에 대해서

if((korWait == false) && (key >= 176) && (key <= 200))

{

korChar[0] = (char)key;

korWait = true;

Arrow = 1;

return true;

}

//두 번째 한글키 이벤트에 대해서

else if((korWait == true) && (key >= 161) && (key <=254))

{

korChar[1] = (char)key;

korWait = false;

Arrow = 3;

int selStart = getSelectionStart();

korString = getText();

//점의 입력이 전에 있었는 가를 체크

if((getText().charAt((selStart < 1 ) ? 0 : selStart-1) == '.') && (selStart == getText().length()))

{

selStart = selStart - 1;

dotStatus = true;

}

// 완성된 한글 문자에 대한 Buffering

korString = korString.substring(0,selStart) + new String(korChar) + korString.substring(selStart,korString.length());

setText(korString);

if(dotStatus == true) {

dotStatus = false;

Arrow = 0;

korWait = false;

korbyte = false;

select(selStart + 4,selStart + 4);

select(getSelectionStart() +1,getSelectionStart()+1);

}

else {

if(selStart < getText().length() - 4) {

select(selStart+2,selStart+4);

}

else {

select(selStart +2,selStart+4);

}

}

return true;

}

Arrow = 0;

return false;

}

protected String paramString() {

String str = super.paramString() + ",text=" + getText();

return str + ",selection=" + getSelectionStart() + "-" + getSelectionEnd();

}

}

5. 결론

이제까지 자바를 이용한 한글 입력기를 구현해 보았다. 아직은 코드 자체가 상당히 미숙한 부분이 있는데, 끝까지 보아주신 점에 대하여 감사드린다. 미흡하나마 이 코드를 이용하여 프로그램을 개발하는데 많은 도움이 되었으면 한다.