다음 버전 개발 근황

날개셋 한글 입력기 8.9는 지난 8.8과는 달리 딱히 치명적인 버그가 발견된 게 없고 잘 만들어져 있다. 한편으로 다음 버전인 9.0은 현재 이렇게 순조롭게 개발되고 있다.

0. 한글 공식 명칭에서 <> 제거

이 시간부터 내 프로그램의 공식 명칭은 그냥 '날개셋 한글 입력기'임을 밝힌다. 날개셋이라는 단어를 감싸는 화살괄호(angle bracket)를 쓰지 않기로 했다. 프로그램의 모든 UI와 도움말, 각종 예제 파일, 홈페이지에서 이걸 이미 제거했다. 프로그램이 완성되는 날, 웹에다가도 업로드해서 반영만 하면 된다.

몇 년 전에 한번 얘기한 적이 있지 싶은데 검색하기가 귀찮다.
세벌식 최종은 타 한글 글쇠배열과는 달리 가운뎃점이 있으며, 화살괄호(컴퓨터에서는 그냥 부등호일 뿐이지만..)가 아랫글쇠(non-shift)에 있다. 하지만 날개셋 한글 입력기 1.0이 최초로 개발되던 시절에 여전히 많이 쓰이던 Windows 95는 비록 공식적으로 최종을 지원했음에도 불구하고 마소 직원의 무지(?)로 인해 기호의 배열에 틀린 게 굉장히 많았다. 그래서 화살괄호조차도 원래 의도했던 방식으로 입력할 수 없었다.

그래서 결국 허접하게나마 내가 입력기를 직접 만들고 나니 가운뎃점이고 참고표고 화살괄호고 다 제대로 입력이 가능했다. 그 당시엔 그것 하나만으로도 참 감격스러워서 뒷일을 별로 생각 안 하고 프로그램 브랜드명에다가도 화살괄호를 쌌다. 아래아한글이 고유명사에다가 옛한글을 쓴 것처럼 뭔가 튀어 보이는 효과는 덤이고 말이다. 그게 사건의 전말의 전부이다.

하지만 고유명사의 내부에 문장 부호가, 그것도 dash 정도의 작은 물건도 아니고 아예 여닫는 pair가 존재하는 놈이 끼어들어 있는게 그리 보기 좋지는 않다. 아래아한글도 옛한글을 표현할 수 없는 환경에서는 '한/글'이라는 대체 표기가 쓰이는데, slash는 그 자체가 디렉터리 같은 토큰 구분용으로 쓰이는 문자이기도 하니 이 역시 그리 보기 좋은 표기는 아니다.

또한 화살괄호는 컴퓨터 키보드로 칠 때는 의미가 완전히 다른 부등호가 돼 버리며, 명령 프롬프트에서는 도스와 유닉스를 막론하고 redirection 기호로 쓰여서 파일명에 들어갈 수 없고.. HTML 태그를 여닫는 기호이기도 해서 본문에 간단히 삽입할 수도 없다. 이 때문에 지금처럼 공식적으로 화살괄호를 제거하기로 결심하기 전부터도 내 프로그램의 명칭은 화살괄호가 빠진 형태로도 암묵적으로 많이 쓰이고 있었다. 이제 본인은 그렇게 간소화된 명칭만을 사용하기로 했다.

지난 7.0에서는 프로그램의 얼굴이라 할 수 있는 아이콘이 대거 바뀌어서 지금에 이르고 있는데, 그로부터 4년 뒤인 9.0에서는 프로그램의 이름 표기가 바뀌는 큰 변화를 겪게 되었다. 나름 의미 있는 변화이다.

1. 복합 낱자 입력 로직 생성기: 허용 한글 범위 제약 기능 + 오토마타 연동

복합 낱자 입력 로직 생성기는 날개셋 한글 입력기 8.x대 후반, 그리고 본인의 박사과정 연구 기간의 대미를 장식한 그야말로 엄청난 핵심 기능이다. 나로서는 정말 엄청난 시간과 노력을 들여서 구현해 냈고 논문도 썼다. 그래서 주요 기능들이 잘 완성됐으며 동작에 딱히 심각한 버그도 없긴 하지만, 이번 9.0에서는 '허용 한글 범위 제약' 기능과 연계하는 기능들이 또 추가되었다. 허용/금지 등 등급별로 분류된 글자들을 날개셋 한글 입력기의 오토마타와 연계하여 재미있는 오덕질을 하는 옵션인데, 다음과 같은 것이 있다.

(1) 먼저, 허용되는 글자 중에서 더 결합의 여지가 없는 단말(terminal) 글자에 도달한 경우 자동으로 조합을 종료하는 옵션이다.
예를 들어 '고'라는 글자는 ㅏ를 결합해서 '과'가 될 수 있고 종성과 결합해서 '곡', '공' 같은 글자가 될 수도 있다. '안'이라는 글자도 '앉'이나 '않' 같은 글자로 추가 결합이 가능하다. 그러나 '엌', '같' 같은 글자는 더 결합이 이뤄질 게 없다. '판'이라는 글자도 KS X 1001 하에서는 '안'과는 달리 겹받침이 붙을 수 있는 게 없다.

이런 글자를 terminal로 간주하며, 이게 만들어지는 순간 조합을 종료하는 것이 이 기능의 핵심이다. 조합을 미리 끊든 말든 사용자의 타자 행동이 달라지는 건 없지만, 이것이 지금 입력 체계 하에서 더 결합의 여지가 없는 단말 글자였다는 시각· 심리적인 피드백을 준다. 이런 것도 날개셋 한글 입력기로 구현 가능하다는 데모 차원에서 옵션을 구현했다.

'허용 한글 범위 제약' 기능을 사용하면 이 프로그램은 일단 입력 가능한 글자들을 받아서 입력을 위해 추가로 허용해야 하는 글자를 수집하고, 글자가 완성된 뒤에 연속 입력을 위해 다단계 분리 처리를 해야 하는 글자도 제3 그룹에다 수집해 준다. 이 글자들은 기존 허용 글자들의 밖에 존재하는 것들이다. (1은 무조건 허용되는 글자, 2는 무조건 실패하는 글자로 용도가 예약됨)

그런데 이 옵션을 사용하면, 기존 입력 가능 글자들 "중"에서 terminal에 속하는 글자들을 제4 그룹에다가 따로 모은다. 그래서 지금까지 오토마타에서 T==3에 대해 다단계 분리 -12를 적용하듯이 T==4에 대해서는 이미 있는 기능인 -3 (결합 후 조합 중단)만 지정하면 일이 깔끔하게 끝난다.

terminal 감지는 두벌식에서는 그렇게 의미 있는 기능이 아니다. 종성이 있는 글자는 그 종성의 일부나 전부가 다음 글자의 초성이 될 수도 있으니 도중에 조합을 끊어서는 절대로 안 된다. 하지만 종성이 없는 글자 중에서도 '긔, 꾜, 뀨, 눼, 댜, 듸, 쮸, 켸, 쿄' 등 terminal이 20여 자 있다. 이 글자들 이후에는 종성이 이어지는 게 전혀 없으니 두벌식에서도 조합을 바로 끊어 버려도 안전하다.

얘들은 '쌰, 쓔, 뢔, 쬬' 같은 고아 글자와는 성격이 정반대이다. 고아 글자들은 받침이 붙은 '썅, 쓩, 뢨, 쭁'은 KS X 1001에 있는데 받침이 빠진 형태가 빠진 경우이고, 모음 terminal 글자는 자신 이후로 아무 받침이 붙지 않는 경우이니 말이다. 어쨌든, 고아 글자를 찾는 기능이 있으니 terminal을 찾는 기능도 있어야 한다는 생각이 들어서 잠시 시간을 내어 이 기능을 구현하게 됐다.

세벌식으로는 terminal 감지 기능이 제 기능을 발휘할 수 있다. 그 극단적인 경우는 현대 한글 기준으로 모든 받침을 1타 만에 입력 가능한 최종(391) 글쇠배열이다. 받침을 찍는 순간 글자가 완성됨과 동시에 그냥 조합이 종료돼 버린다. 물론 이렇게 테이블을 참조할 필요조차 없는 일방적인 경우라면 아예 오토마타 수식을 고쳐 버려도 되지만 '안'일 때만 조합이 유지되고 '판'일 때는 조합이 끊어지게 하려면 이 기능을 사용하면 된다.

(2) 그 다음으로, 허용되지 않는 글자를 만드는 낱자는 다음 글자로 보내는 게 아니라 그냥 무시하는 옵션이 있다. '또+ㅁ'의 경우 ㅁ을 다음 글자로 보내는 게 아니라 그냥 무시한다는 뜻이다. 이 역시 두벌식에서는 종성에 대해서는 적용할 수 없고, 중성에 대해서만 적용 가능하다. T==2에 대해서 -1 (무시)을 되돌리게만 하면 간단히 구현 가능하다.

날개셋 한글 입력기의 완성도를 더욱 끌어올릴 아이디어가 하나 떠올라서 성공적으로 구현되니 좋다. 이제야 '복합 낱자 입력 로직 생성기는' 진짜로 더 만들 게 (현재로서는) 안 떠오르고 작업이 완전히 종결된 것 같다.
이 옵션이 추가됨으로써 '복합 낱자 입력 로직 생성기' 마법사의 2단계 대화상자는 너무 큼직하고 복잡해졌다. 사실, '허용 한글 범위 제약'은 통상적인 로직 생성 옵션과는 성격이 좀 다른 액세서리에 가깝다. 그렇기도 하니 이건 마법사의 별도의 단계로 분리해 버렸다.

사용자 삽입 이미지사용자 삽입 이미지

복합 낱자 입력 로직 생성기가 쓰라는 의도로, "오토마타에 '0번 상태에서 모든 실패 상황을 처리"라는 옵션을 추가했다.
정상적인 한글 입력에 따른 상태 분기와는 달리, 실패 상황의 상태 분기 방식은 지금 오토마타 상태와 무관하게 언제나 동일한 경우가 많다. T가 3이면 -12, T가 4이면 -1 이렇게 T라든가 I~K의 값에 따라 달라질 뿐, 성공 상황처럼 매번 처리 방식이 들쭉날쭉해지는 건 매우 드물다.

이 점에서 착안하여, T==3 ? -12 : T==4 ? -1: 0 같은 수식은 초기 상태에서 A ? 1: B ? 2: C: 3 : (!!) 다음에 한 번만 추가하면 모든 오토마타 상태에서 동작하게 했다.

  • 8.8: 복합 낱자 입력 로직 생성기 첫 도입
  • 8.9: 그 기능에다 '한글 허용 범위 제약' 기능 연계 추가
  • 9.0: '한글 허용 범위 제약' 연계 기능에다가 '오토마타'와의 연계를 또 추가. 이제 진짜 끝?

2. 그 밖에 복합 낱자 입력 로직 생성기의 사소한 개선 사항

  • '낱자 최적화' 알고리즘이 좀 더 개선되어서 글쇠에 등장하지 않고 쓰이지 않는 낱자 결합 군더더기를 더 잘 걸러내게 했다.
  • 매우 드문 상황이겠지만, 로직 생성 작업이 아무 메시지 없이 깔끔하게 끝났다면 "작업을 완료했습니다"라는 말 한 마디라도 출력해서 사용자가 심리적으로 혼동하지 않게 했다. PC용 세벌식+현대 한글처럼 복잡한 처리가 필요하지 않은 설정에서는 드물게 이런 일이 있을 수 있다.
  • 초성 문맥이 전혀 존재하지 않는 종성 두벌식 날개셋문자를 사용하더라도 초성에 등장하는 것 자체는 가능하니 이를 감안하여 동작하게 했다. 물론 원래 소속이 종성이니 이 낱자들은 초성 '대결합'은 전혀 처리하지 못한다는 걸 사용자가 염두에 둬야 한다.

그리고, 입력 데이터를 검증할 때 현재는 대결합의 결과값이 소결합의 시작과 결과값에 또 등장하는 것을 금지시키고 에러로 처리하는데, 9.0은 여기에 덧붙여 대결합의 결과값이 자신이나 다른 대결합의 과정값에도 등장하지 못하게 조건을 강화했다. ㅂ+ㅅ → ㅄ이 있다고 해서 ㅄ+ㄷ → ㅵ를 줘서는 안 되고 반드시 매번 ㅂ+ㅅ+ㄷ → ㅵ로 해야 한다는 뜻이다. 그렇게 해야 대결합을 실제로 expand할 때 동일 input으로부터 a+b → x와 a+b → y가 동시에 등장하는 식의 논리 오류를 방지할 수 있다.

이런 제약을 가한 대신, ㅂ+ㅅ+ㄷ → ㅵ에서 ㅅ+ㄷ → ㅼ이라는 다른 대결합이 존재하고 ㅼ이 글쇠에 존재해서 한 타 만에 입력 가능한 경우, 이 프로그램이 ㅂ+ㅼ → ㅵ이라는 결합도 자동으로 찾아서 생성하게 했다.

3. 기본 글자판 설정에 두벌식 관련 고급 옵션 추가

날개셋 한글 입력기가 제공하는 빠른설정들 중에 '기본 글자판 설정'은 대중적이고 기본적인 입력 기능만 사용하는 분들이 가장 자주 사용할 만한 빠른설정이다. 처음으로 개발된 이래로 별다른 변화 없이 10년이 넘게 존속해 왔다.

본인은 다른 대화상자들이라면 몰라도 얘만은 프로그램 내부 구조 지향이 아니라 사용자 지향· 사용자 친화적으로 만들려 애썼다. 복잡한 각종 옵션들을 어지럽게 한 화면에 몽땅 노출하지 않고 새끈하게(?) 보이게 하려고 단계별 마법사 UI를 쓸까 생각도 했다. 대화상자를 보면 좀 마법사 UI처럼 생겼지 않는가?

그런데 실제로 개발을 해 보니 기본 글자판 설정이란 게 굳이 몇 단계짜리 마법사까지 동원할 정도로 구조가 복잡하지는 않아서 '다음' 단계 대신 그냥 '고급' 버튼만 넣는 걸로 퉁쳤다.
마법사 UI는 먼 훗날에 '복합 낱자 입력 로직 생성기' 빠른설정이 대신 찜했다. '기본 글자판 설정'보다 기능이 훨씬 더 많고 복잡하니 처음에 3단계 마법사로 시작했고 이번 9.0부터는 4단계로 더 늘었다.

이런 사정을 거쳐, 기본 글자판 설정엔 현재까지 '고급' 옵션이라는 게 세벌식 자판과 관련된 것 네 종류만 있었다. 그러나 이제는 표준 두벌식을 골랐을 때도 '고급' 옵션을 사용할 수 있으며, 여기에는 두벌식에만 적용되는 고유한 고급 옵션이 몇 가지 들어갔다.

사용자 삽입 이미지

먼저, '자음의 처리 방식'이다. '초성과 종성 따로'는 일반적인 동작 방식이고, '초성 지향'은 '날 - 나라' 대신 '나ㄹ - 날'이 되는 동작을 말한다. '종성 지향'은 초성도 일단 종성 문맥으로 입력되었다가 나중에 중성을 받았을 때에야 초성으로 바뀌는 동작이다.

기술적으로야 초성 지향은 '고급 입력기'의 옵션을 사용해서 동작하고 종성 지향은 '종성 두벌식'이라는 별도의 날개셋문자를 사용해서 동작한다. 구현 방식이 서로 완전히 다르지만 이 빠른설정에서는 한데 선택할 수 있다는 것에 의의가 있다.

그리고 표준 두벌식은 오로지 알파벳 26개 자리에만 한글 글쇠가 있고 숫자와 기호를 사용하지 않는다는 특성상, 숫자와 기호는 굳이 입력기가 가로채지 않고 응용 프로그램으로 보내도록 하는 옵션을 빠른설정에서 곧장 선택할 수 있게 했다.

이로써 두벌식과 세벌식 모두 빠른설정에서 오로지 자신만의 고유한 고급 옵션을 갖게 됐다. 단지 세벌식의 고급 옵션들은 3.x 완전 초창기 때부터 존재했지만, 두벌식의 고급 옵션들은 다 6~7.x에 가서야 도입됐고 빠른설정에 반영은 훨씬 늦었다는 것이 차이점이다.

4. 토씨 자동 교정

한글 입력과 직접적인 관계가 있지 않고 평생 다시 볼 일이 없을 거라고 생각했는데, 토씨 자동 교정 알고리즘을 우연한 계기로 재검토해서 정확도를 조금 올렸다.

토씨 자동 교정 기능은 동작이 은근히 복잡하다. 은/는, 을/를, 과/와 같은 거야 아주 쉬운 케이스이다. 그러나 (으)로는 유일하게 ㄹ 받침도 무받침과 동급으로 간주해야 한다는 예외가 있으며, '이'는 처리하기가 훨씬 더 어렵다. '이나마, 이랑, 이라'처럼 받침 유무에 따라 '이'를 넣거나 생략해야 하는 것들이 많기 때문이다. '이다'의 경우는 받침이 없더라도 반드시 생략할 필요는 없다.

이것들부터 먼저 검토한 뒤, 한글이 또 등장하지 않아서 명백하게 주/보격 조사인 '이'에 한해서 '이/가' 처리를 해야 한다. 하긴 중세 국어에서는 조사 '가'가 없었다고 하더라만..
'이'만 처리가 이렇게 복잡한 이유는 한국어의 매우 독특한 단어 '이다'의 정체성과 밀접한 관계가 있다.

한국어의 어절(띄어 쓰는 단위)에서 관형어나 부사· 감탄사, 기능어 등등 잡다한 거 빼고 내용어를 구성하는 것은
딱 (1) '체언+조사' 계열, 아니면 활용을 하는 (2) '용언+어미'라는 두 계열로 나뉜다.
그런데 '이다'라는 단어는 정말 요물이다. 얘는 문법적으로 무엇으로 분류해야 할지 쟁쟁한 국어학자 문법학자들 사이에서도 의견이 오랫동안 일치하지 않았다.

마치 영어에서 be 동사가 여느 다른 동사들과는 문법적으로 다르게 취급되는 동사이듯, 쟤도 평범한 용언은 아니다.
오늘날 표준 국어 대사전 + 학교 문법에서는 '이다'를 서술격조사로 본다. '이었다' 등 영락없이 용언처럼 생긴 물건이 조사라니.

그래서 '이니', '이고', '이면'처럼 '이다'의 활용형도 다 별개의 접속조사이고, 일단 사전에 일일이 단독으로 등재돼 있다.
이것도 많은 고민 끝에 내린 결론이겠지만 이게 합리적인 결정이라고 볼 수 있는지는 모르겠다.
하긴, '귀신이다', '불이야'처럼 체언에 잘도 척척 달라붙는 동사나 형용사가 다른 예가 없긴 하다. (공부하다 이런 건 논외. 그때의 '-하다'는 접사임.)

체언과 용언을 파동과 입자에다 비유하자면, '이다'는 진짜 빛처럼 두 성질을 모두 지닌 이상한 물건이다.
그리고 이 '-이' 때문에 '찾기/바꾸기'에서 한글 토씨 자동 교정 기능도 구현하기 꽤 복잡하고 어려워져 있다.

끝으로, '야'의 경우 호격조사 '아' 또는 보조사 '이야'가 모두 가능한데, 이것은 용례 domain이 겹치기 때문에 글자만 보고 구분하기가 불가능하다. 토씨 자동 교정 알고리즘의 구조적인 한계가 될 수밖에 없는 점이다.

5. 기타 사소한 것들

(1) 도움말 부록의 자음 참조표에서 ㅁㅂㅅ의 순서가 잘못 기재되었던 오타를 지적해 주신 분이 있어서 고쳤다. 78이 빠지고 79가 두 번 들어가 있었다. 이 오타는 굉장히 오랫동안 발견되지 않고 지금까지 잘도 숨어 있었다. 오죽했으면 5년 전, 2012년에 발행된 본인의 석사 학위논문의 부록에도 동일한 오타가 그대로 들어갔다!

(2) 편집기에는 프로그램의 중복 실행이 감지된 경우 인스턴스를 또 생성하지 않고 기존 인스턴스에다 새 문서창을 열게 하는 기능이 있다. 그런데 기존 인스턴스가 어떤 이유로 인해 응답이 없고 뻗은 상태라면 그 옵션이 지정되어 있더라도 예외로 그냥 새 인스턴스에서 실행되게 하여 동작에 융통성을 더했다.

(3) 날개셋 편집기를 비롯해 내 프로그램이 내부에서 자체적으로 사용하는 빨랫줄 모양 옛한글 비트맵 글꼴의 중성 자형을 일부 수정했다. 그래서 ㅣㅛ, ㅓㅛ, ㅕㅗ 등, ㅗ/ㅛ가 포함돼 있는 겹모음들이 위의 초성과 더 잘 포개져서 조화롭게 보이게 했다.

(4) 두벌식 옛한글의 Shift+H(ㅗ) 자리에 지금까지 ㅗㅜ가 배당돼 있던 것을 ㅗㅗ로 변경했다. 기왕 내 프로그램은 Shift 자리에는 다른 자모와 겹치지 않는 한 아랫자리에 있는 낱자의 double(쌍) 버전을 넣는 것으로 컨셉을 잡았으니 저렇게 하는 게 더 일관성이 있을 것 같다. 아래아한글의 영향을 받아서 내 프로그램도 까마득한 2.x 옛날 버전부터 ㅗㅜ이긴 했는데, 그냥 breaking change(하위 호환성이 깨지는 단절적인 변화)를 만들었다.
ㅜ와 ㅡ도 double 버전이 있긴 하지만 쟤들은 Shift 자리에 다른 글쇠가 정해져 있기 때문에 double 버전을 넣을 수 없다. 두벌식은 옛한글 배열이라 해도 숫자· 기호 자리를 침범하지 않는 게 일종의 불문율이긴 하다.

Posted by 사무엘

2017/05/16 08:31 2017/05/16 08:31
Response
No Trackback , 2 Comments
RSS :
http://moogi.new21.org/tc/rss/response/1360

1. 외부 모듈 핵심부의 EXE 분리

오래 전부터 조금씩 풀었던 썰이긴 한데, 마침 최근에 회사에서 유사 개발 업무를 한 적도 있고 해서 다시 얘기를 꺼내 보겠다.
Windows는 타 OS들과는 달리 IME가 EXE가 아닌 DLL 형태이다. 한 프로세스의 주소 공간에 완전히 속해 있는 덕분에 성능이 좋다는 장점이 있겠지만, 한영 상태가 스레드들마다 제각각 따로 놀고 거기에다 memory-mapped 방식으로 로딩된다는 특성까지 겹쳐서 IME의 on-the-fly 업데이트가 몹시 난감하다.

EXE라면 업데이터 하나 띄워서 자신을 종료한 뒤 업데이트 된 놈으로 재시작만 하면 간단하게 끝났을 일인데 Windows용 IME는 업데이트 하려면 자신을 사용하는 프로그램들을 몽땅 종료해야 하고, 그게 여의치 않으면 그냥 운영체제를 재시작/로그오프 해야 한다. 거기에다 32/64비트까지 모두 신경 써야 한다.

그래서 <날개셋> 한글 입력기 외부 모듈도 인제 와서 처음부터 다시 만드는 건 무리이겠지만, 앞으로 덩치 큰 IME를 만들 일이 있으면 DLL은 거의 업데이트 할 일 없는 껍데기만 남겨 놓고 실질적인 문자 조합은 EXE 기반의 '서버'에 담당시키면 어떨까 생각을 해 왔다. 업데이트도 IME가 통신하는 EXE만 하고 말이다.

이렇게 하면 모든 IME들의 설정과 상태 동기화는 자동으로 이뤄진다. 서버와는 함수 호출이 아니라 메시지와 memory-mapped file 같은 간접적인 방법으로 통신을 하니 서버는 굳이 바이너리 구분을 할 필요 없다. 64비트 OS에서는 64비트 서버 하나만 띄워 놓으면 32비트와 64비트 IME가 모두 통신이 가능하니 더욱 좋다.

실제로 실험용 IME를 만들어 본 결과는 흥미로웠다. 서로 다른 프로세스끼리 메시지를 주고받을 때는 단일 스레드끼리 메시지를 주고받을 때에 비해 고려해야 할 점이 더 많았다. 받는 쪽에서 자체적으로 대화상자 같은 걸 출력하고 그 상태로도 자체 메시지를 처리하지 못하는 block 상태가 되지 않으려면 대화상자는 modal이 아니라 반드시 modeless 형태로 만들어야 했다.

SendMessage와 PostMessage를 조심해서 가려 써야 하며, 리턴값을 꼭 받기 위해 Send를 하면서도 신속한 반응성을 보장하기 위해서는 지금까지 머리로만 알고 있던 ReplyMessage 같은 함수를 난생 처음으로 써 보기도 했다. 특히 호스트가 클라이언트로부터 Send된 메시지를 받은 뒤에 대화상자 같은 modal UI를 띄운다면 말이다.

여기까지 생각을 하긴 했으나.. IPC 기법들은 근본적으로 IME들이 쓰라고 만들어진 메커니즘이 아니다 보니 한계도 많다.
가장 먼저 권한 문제가 걸리니, IME 서버는 번거롭게 관리자 권한으로 실행하거나 아니면 애초에 운영체제의 서비스 같은 급으로 만들어야 한다. 메트로와 데스크톱 앱 사이의 소통도 문제이고..
IME가 글쇠 입력을 받은 것을 서버로 요청을 보내는 건 그럭저럭 할 만하나, 반대로 서버가 IME로 문자 입력 요청을 하는 것은.. IME가 제각각 스레드 동기화 오브젝트나 윈도우를 만들어야 가능할 것이다.

서버는 자신과 접속하거나 종료하는 클라이언트들을 파악하고 있어야 하는데 자고로 프로세스라는 건 강제 내지 비정상 종료될 때도 있다. 그렇기 때문에 모든 프로그램들의 근황을 언제나 정확하게 파악하고 있는 것도 훅킹이라도 동원하지 않으면 의외로 쉽지 않더라.

이것저것 가성비를 생각해 보니 서로 장단점이 있고 근본적으로 한 방식이 다른 방식을 완전히 대체 가능해 보이지는 않았다. 안 그래도 날개셋의 경우 EXE 기반의 입력기 개발 실험은 입력 패드를 만들면서 이미 그럭저럭 하기도 했다. Windows에서 어떤 DLL이 타 프로세스에 합법적으로 침투할 수 있는 양대 통로는 미우나 고우나 훅킹 아니면 IME이다.

다만, 지금 MS 일본어 IME가 이미 그런 것처럼 제어판 대화상자만은 EXE로 분리하는 게 나은 점도 있다.
실행되는 응용 프로그램에 따라서는 공용 컨트롤.. 특히 6.0 이상에서만 지원되는 syslink나 split button, 에디트 컨트롤의 풍선 도움말(cue banner) 같은 게 초기화되지 않은 경우가 종종 있어서 내 날개셋 제어판도 그거 영향을 받아 제약을 받기도 하기 때문이다.

뭐 그건 그렇고..
기존 데스크톱 앱인 '제어판' 말고 메트로 앱인 '설정'에서 돌아가는 환경설정은 어떻게 만드는지 모르겠다. MS 한글 IME에는 그런 게 있던데..;;

2. 설치 시스템 개편

예전에도 여러 번 언급한 바와 같이, <날개셋> 한글 입력기는 Visual Studio가 기본 제공하는 Windows Installer 기반 msi 패키지 형태로 배포되고 있다. 이 솔루션은 MS 본가에서 만든 만큼, 프로그램을 설치하거나 제거하는 본연의 성능은 일정 수준 이상의 퀄리티가 보장된다. 프로그램 디렉터리 어딘가에 uninstall stub 프로그램 같은 게 덕지덕지 붙어 있을 필요도 없고 아주 seamless + 깔끔하다. 하지만 개발툴이 제공하는 GUI 템플릿은 customize가 매우 제한적이고 불만족스러운 점이 많기 때문에 다른 솔루션을 써 볼까 생각도 자주 해 왔다.

이상적인 설치/배포 솔루션은 다음과 같은 조건을 만족해야 한다. 다른 프로그램이라면 몰라도 <날개셋> 한글 입력기에 대해서는 내가 보다시피 욕심이 좀 많다.

  1. CPU 통합: 한 exe 파일 단독으로 32비트와 64비트 OS에서 잘 동작하고, 32비트에서는 당연히 64비트 바이너리를 설치하지 않아야 한다. EXE처럼 32/64비트 중 사용 가능한 상위 바이너리 하나만 설치하면 되는 파일은 선별이 옳게 돼야 한다. 필요한 디스크 공간 계산도 이 모든 변수를 감안해서 돼야 한다.
  2. 언어 통합: 한 exe 단독으로 운영체제의 기본 언어가 한국어이면 한국어, 그렇지 않으면 자동으로 영어로 설치 프로그램의 UI가 출력되어야 한다.
  3. 유니코드 통합: 평상시에 유니코드 API를 사용하는 건 너무 당연한 얘기이고, 그럼에도 불구하고 구닥다리 Windows 9x에서도 유니코드만 포기하고 기본적인 실행이 돼야 한다. 이것도 물론 단일 파일로 말이다. <날개셋> 한글 입력기 본제품이 Windows 95/NT4부터 꼬박꼬박 다 지원하는 프로그램이기 때문이다.
  4. known 폴더: 또한 아무 액세서리 없는 깡통 Windows 95 RTM에서 실행되더라도 IE 4~5 이상에서 첫 도입된 ProgramData (Application Data)같은 known 디렉터리를 인식해서 파일을 제 위치에 설치해야 한다.
  5. 원활한 제거: Windows용 IME는 그 특성상 on-the-fly로 업데이트나 제거가 꽤 난감한 물건인데, 당일 제거를 못 했으면 재부팅 요청 같은 후처리를 적절히 수행해야 한다.
  6. 그 밖에: 관리자 권한 드립 치는 UAC 화면은 setup을 실행하자마자 뜨는 게 아니라, 실제로 설치가 시작되어 관리자 권한이 정말로 필요해졌을 때 직전에 뜨는 게 바람직함.

진짜 유명한 세계구급 소프트웨어인 경우, 설치 프로그램이 언어를 선택받는 대화상자부터 띄우는 경우가 있다. 하지만 날개셋의 경우 그렇게 유명한 물건은 아니니 그냥 운영체제의 기본 GUI 언어가 한국어가 아닐 때에만 영어로 동작하는 걸로도 충분할 듯하다. 날개셋은 GetSystemDefaultLangID() 함수를 써서 판별하는데, 이게 GetUserDefaultLangID와 차이가 무엇이 있는지는 개인적으로 궁금하다.

msi는 (1)과 (2)는 전혀 만족하지 않는 것으로 보여서 문제다.
그러나 (3)과 (4)는 Windows installer runtime (non-Unicode 9x용 에디션)자체만 미리 설치하면 그럭저럭 어렵지 않게 충족된다. 2.0 런타임은 의외로 깡통 Windows 95에서도 깔끔하게 설치 가능하다. 이것 때문에 <날개셋> 한글 입력기가 MSI 외에 다른 배포 솔루션으로 갈아타기가 어렵다.

"HKCU 또는 HKLM"\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders라는 레지스트리를 참조하면 known 폴더 위치를 얻을 수 있다. MSI가 이런 것까지도 생성해 준다. 이렇게 레지스트리를 수동으로 뒤지는 방법은 오늘날에는 마소에서 권장하지 않는 방법이지만, The old new thing 블로그의 설명에 따르면 아직도 여기를 참조하는 고집쟁이 옛날 어플 때문에 어쩔 수 없이 호환성 차원에서 레지스트리를 계속 지원해 주는 거라고 한다. 사실, IE 4~5가 없고 SHGetSpecialFolderPath 함수가 존재하지 않는 골동품 Windows 95 환경에서는 여기를 뒤지는 것밖에 선택의 여지가 없기도 하다.

다음으로 (5)의 경우 msi는 딱 기본만 수행한다. "다음 프로그램들이 요 DLL을 사용하고 있습니다" 대화상자도 찍어 주고, 뭔가 못 건드린 파일이 있으면 "재부팅 하시겠습니까?"라는 여운을 남기기도 하는데, 가끔은 안 그럴 때도 있는 듯하다.

msi 말고 3rd party installer 중에서는 오픈소스이기도 한 NSIS가 세계적으로 제일 유명하다. WinAmp는 역사 속으로 사라졌고 개발사인 Nullsoft도 없어졌지만, 그래도 NSIS만은 유용성 덕분에 오픈소스 진영에서 살아남아 있다. Nullsoft의 개발자들이 왕년에 불멸의 작품 하나로 이름을 남겼다.

얘는 어떤가 하면..
(1)과 (2)는 기술적으로 일단 가능하다. msi보다 분명 우월한 점이다. 그러나 그냥 '가능하다'에서 끝일 뿐, 막~ 적극적으로 지원되고 깔끔하고 편한 형태로 가능하지는 않아 보인다.

단적인 예로, 생성되는 installer에 붙는 런타임 바이너리가 기본적으로 32비트 기반이다 보니, 거기 스크립트 언어에서 기본 제공하는 등록 명령만 이용해서는 64비트 DLL에 대해서 DllRegisterServer(시스템 등록) 호출을 할 수 없다. 뭐, 운영체제가 제공하는 regsvr32 /s를 이용하면 되긴 하지만, 사용자가 직접 저렇게 외부 유틸리티나 플러그 인을 끌어들일 필요 없이 NSIS가 내장 명령어 차원에서 저걸 지원하면 더 좋을 것이다.
홈그라운드 운영체제의 지원빨이 있는 msi에서는 반대로 DLL의 등록쯤은 전혀 걱정할 것 없는 사항이다. 64비트용 msi라면 64비트 DLL이건 32비트 DLL이건 불문하고 등록이 깔끔하게 잘 처리되기 때문이다.

(3)은 NSIS가 한동안 정식으로 지원하지 않아서 Unicode NSIS라는 별도의 프로젝트 브랜치가 나돌 정도이다가 비교적 최근에 NSIS가 3.x 버전에 진입하고 나서야 유니코드를 정식으로 수용하게 됐다.
그러나 NSIS는 기술 수준이 그냥 이미 있는 Windows API를 감싸는 정도를 벗어나지 않기 때문에 유니코드와 Windows 9x를 동시에 지원한다거나, 구버전 OS에서 신버전의 known 디렉터리를 만들어 주는 정도의 과잉 친절을 베풀지는 않는다.
(5)의 경우는 NSIS가 어디까지 자비롭게 대처하는지 아직 제대로 확인을 못 해 봤다.

요약하면, 완전한 스크립트 기반인 NSIS가 당장 자유도가 뛰어나 보이기는 하지만, 그래도 레거시 운영체제 지원이나 시스템 차원에서의 융통성은 그래도 msi가 나은 게 있어서 한 솔루션이 다른 솔루션을 완벽하게 대체하지는 못하는 실정이다.
NSIS의 스크립트는 무슨 파이썬이나 Lua 급으로 복잡한 연산식이나 복합 자료구조를 지원하는 본격적인 고급 언어가 아니다. 스크립트의 문법은 반쯤 어셈블리어에다가 C언어의 전처리기를 얹은 것 같은 구조이며 생각보다 제약이 많다.

어셈블리어 같은 문법인데 CPU 인스트럭션이 들어가는 게 아니라 Windows API의 함수와 각종 속성 명칭이나 상수들이 들어간다는 점만 다르다. if-then-else, switch 같은 조건 판단과 분기조차도 언어의 키워드가 아니라 그냥 분기문을 표현하는 매크로 형태로 구현되었을 정도이다.
그나저나, 파일 경로를 많이 다루고 역슬래시를 필연적으로 많이 쓴다는 특성상 \ 자체는 탈출문자로 쓰지 않고 $를 붙여서 $\n으로 개행문자를 표현하는 건 인상적이었다.

설치 스크립트도 당장 필요한 기능만 주먹구구식으로 구현하는 게 아니라 치밀하게 잘 만들려면 끝이 없겠다.

  • 한 스크립트로 몇몇 스위치만 달리하여 동일 제품의 여러 파생형이나 변형 에디션(가령, 셰어웨어 데모/정식 같은)을 조건부 컴파일로 간단히 감당 가능
  • 한 제품에서는 아까 말한 언어와 아키텍처를 단일 출력 바이너리만으로 모두 커버 가능
  • 모든 문자열 값들은 언어 중립적인 값과 언어 종속적인 값으로 나눠서 관리 가능하고, 제품 이름 같은 건 한 곳에서 값을 바꾸면 등장하는 모든 곳에서 값이 알아서 바뀌어야 함
  • 컴퓨터의 상태 파악을 알아서 해야 함. 처음 실행됐을 때 지금이 첫 실행인지, 동일 버전, 구 버전, 또는 동일 버전의 바리에이션이 이미 설치돼 있는지, 이전에 설치를 하다가 만 상태인지, 심지어 자신이 중복 실행됐는지 같은 걸 사용자가 수동으로 파일이나 레지스트리 삽질 안 해도 알아서 감지해야 함
  • 설치할 파일과 삭제할 파일을 NSIS는 수동으로 일일이 써야 하는 것 같던데, 마치 C++ 개체 선언하듯이(생성자, 소멸자) 설치하는 파일, 추가하는 레지스트리 같은 걸 한 곳에다만 명시하면 역순의 제거 작업 역시 자동으로 파악돼야 하며, 작업을 실제로 수행하기 전에 예상 디스크 공간 계산 같은 것도 알아서 돼야 함.
  • 서로 다른 소프트웨어 제품이 동일한 파일을 설치하고 사용하는 경우, 그런 공용 파일은 reference counting을 해서 그 제품들이 모두 제거되었을 때에만 최종적으로 삭제되게 해야 함.
  • 그리고 uninstall 시엔 사용자가 생성한 데이터처럼 이 프로그램이 초기에 설치하지 않은 파일이나 레지스트리도 필요하다면 싹 제거하는 메커니즘이 제공돼야 함. (조건 범위 지정)
  • 최종 생성된 msi 내지 exe 파일에 대한 디지털 서명 후처리도 언어 내지 툴 차원에서 명시해서 자동 처리하기.

오픈소스 프로젝트에 기여한 것도 없는 주제에 불평만 길게 늘어놓은 것 같다만.. 이게 NSIS를 좀 써 보고 개인적으로 느꼈던 아쉬운 점이다. 오죽했으면 반디소프트에서 개발하고 있는 유명 파일 압축 유틸리티인 반디집도 6.0부터는 NSIS 대신 자체 개발한 인스톨러로 갈아탔다. 다만, NSIS는 저 정도 꽤 적지 않은 기능을 제공하고도 exe에 붙는 자기 런타임 stub 크기가 겨우 몇만 바이트에 불과할 정도로 작은 건 굉장히 인상적이었다.

그냥 간단한 파일 몇 개만 복사하고 끝나는 게 아니라 컴퓨터를 좀 깊게 제어하는 설치/제거 패키지를 만든다면 이걸 만드는 툴도 GUI 위주의 가벼운 툴이 아니라 그냥 핵심 기능만 SDK 형태로 만들고, 자주 쓰는 프로그램 패턴은 Visual C++의 프로젝트 마법사 형태로 구축하는 것도 나쁘지 않을 것 같다. 배포 패키지 자체를 그냥 C/C++로 만들라고 말이다. 그러면서 파일 압축 풀어서 복사하거나 지우는 등의 정말 핵심적인 공통 기능만 라이브러리를 쓰라고..

근데 생각해 보니 애시당초 그러라고 만들어진 라이브러리가 Windows Installer이긴 하다. 쟤도 사실은 단순 GUI 껍데기가 아니라 라이브러리가 본질이니까. 하지만 저 라이브러리도 구조가 워낙 복잡하고 설치, 제거, 롤백이 어떻고 알아야 할 사전 배경지식이 많다 보니 그 저수준 함수를 직통으로 쓰면서 배포 패키지를 만들 일이라곤 없을 듯하다.

Posted by 사무엘

2017/05/01 08:30 2017/05/01 08:30
, ,
Response
No Trackback , 4 Comments
RSS :
http://moogi.new21.org/tc/rss/response/1355

날개셋 한글 입력기 8.9 -- 下

<날개셋> 한글 입력기 8.9는 지난 8.8 버전에서 첫 도입되었던 "복합 낱자 입력 로직 생성기"에 '허용 한글 범위 제약'을 연동하는 기능이 추가되었으며, 이 기능의 구현을 위해서 기존 '허용 한글 범위 제약' 기능의 제공 형태도 약간 변경되었다.

이전 버전에서 복합 낱자 입력 로직 생성기 대화상자의 2단계 페이지는 그렇잖아도 뭔가 2% 부족하고 텅 비고 허전해 보였다. 그러던 것이 이제는 UI가 더 추가되면서 아래와 같이 더 빵빵하게 바뀌었다.

사용자 삽입 이미지

그럼, 이미 있던 기능에 대해서 복습부터 해 보자.
'허용 한글 범위 제약'이란 말 그대로 특정 문자 집합에 속하는 한글만 조합을 허용하고, 이 조건을 만족시키지 않는 낱자는 다음 글자로 보내거나 무시하는 등의 처리를 하는 기능이다. 가령, KS X 1001에 정의된 한글 2350자만 조합을 허용하고 '똠, 아햏햏' 같은 글자는 조합되지 않게 할 수 있다. '또ㅁ, 해ㅎ'으로 끊어진다.

이런 기능 자체는 <날개셋> 한글 입력기가 먼 옛날, 거의 2.x 시절부터 갖추고 있었다. 2.x는 한컴 2바이트 코드 기반이었는데, 얘는 일부 옛한글을 완성형으로 표현했다. 그러니 테이블에 등록되어 있지 않은 옛한글은 애초에 조합을 거부하고 입력되지 않게 하는 기능이 반드시 들어있어야 했다.

오늘날이야 유니코드에다 문자열 + 글꼴 처리 기술의 발전 덕분에 저런 한계가 진작부터 없어졌다. 인코딩 차원에서의 한글 표현 한계로 인해서 '허용 한글 범위 제약' 같은 기능이 동원되어야 할 필요는 없다. 그러나 이런 기능은 필요에 따라서는 지금도 여전히 유용하게 쓰일 수 있다.

가령, 일본어나 중국어 같은 외국어를 한글로 입력한다고 치자. 이들 언어는 종성이 매우 적으며, 소리를 표기하는 데는 한글 음절이 수십~수백 종류면 충분하다. 그러니 두벌식으로 종성 문맥에서 ㄹ을 입력하는데, '어+ㄹ' 같은 실제로 쓰이는 글자에 대해서만 '얼'이 입력되고 나머지 상황에서는 그냥 초성 ㄹ로 빠진다면 불필요한 도깨비불 현상이 발생하지 않으니 좋을 것이다. 두벌식으로도 반쯤 세벌식 같은 효과를 낼 수 있으며 초성 검색 자동 완성을 구현할 때도 더 편하다.

이런 건 아주 간단한 예에 불과하다. KS X 1001 완성형 2350자는 워낙 역사적인 상징성이 큰 문자 집합이니 진작부터 존재해 왔거니와, 저런 식의 활용을 염두에 두고 사용자가 작성한 임의의 텍스트 파일에 있는 한글들의 입력만 허용하는 '허용 한글 범위 지정 기능'도 지난 7.9 버전에서부터 추가된 바 있다.

그런데 문제는...
이렇게 닥치고 금지하고 조합을 끊기만 하는 기능은 완성도와 유용성이 100점 만점에 70점밖에 안 된다는 것이다. 그리고 그나마 PC니까 괜찮지 모바일로 가면 70점은 택도 없고 영 못 쓸 수준이 돼 버린다. 허용되는 글자를 입력하는 도중에 금지 글자를 예외적으로 거쳐 가는 것에 대한 대비가 없기 때문이다.

대표적인 예는 KS X 1001에서 '쓩'이다. 이 글자는 허용이지만 그 중간 과정의 '쓔'는 금지인 것으로 잘 알려져 있다. 그러니 무턱대고 '쓔'를 금지했다가는 허용 글자인 '쓩'도 입력할 수 없게 된다.
PC용 두벌식 + KS X 1001 기준으로는 이런 고아 글자가 5자 정도 알려져 있는데, 모바일로 가면 이런 예가 더욱 많아진다. 프로그램을 짜서 조사해 보면 수백 개에 달한다. 가령, 천지인에서는 ㅇ을 거쳐서 ㅁ을 입력한다는 특성상 '틈'을 입력하기 전에 금지 글자인 '틍'을 거친다. '폈'을 입력하기 위해서는 금지 글자인 '폇'을 거쳐야 한다.

그러니 범용적인 '허용 한글 범위 제약' 기능을 매끄럽게 구현하려면 허용-금지 문자 집합뿐만 아니라 지금 입력 방식을 총체적으로 분석해서 pre-compute된 메타정보를 갖고 있어야 한다. 부득이하게 입력을 허용해야 하는 중간 단계 글자가 무엇인지가 그 입력 방식의 구조에 따라 달라지기 때문이다.

이번 8.9의 로직 생성기는 '지정된 파일에 들어있는 한글' 범위(입력 일반 탭)가 읽어들이는 것과 동일한 형태의 텍스트 파일을 줘서 허용 한글 범위를 지정할 수 있다. 단, KS X 1001은 워낙 유명하고 프로그램 내부에 테이블이 들어있기도 하기 때문에 별도의 파일 지정이 필요 없다.

그 뒤 중간 과정 글자의 표현 방식을 지정할 수 있다. '쌰' 같은 중간 글자를 (1) '샤'나 '썅'과 다를 바 없는 온전한 형태로 그대로 표시할지, (2) 아니면 끊어진 것처럼 풀어서 표시하되 조합은 다 유지하고 있게 할지, 혹은 (3) 나랏글에서 대결합 ㅜ+ㅏ를 ㅝ로 바로 자동 완성해서 표시하는 것처럼 '쌰'만으로 목적지인 '썅'을 자동 완성할지를 고르면 된다.

그러면 이 프로그램은 기본으로 규정된 한글 문자 집합 데이터에다가 추가로 허용돼야 하는 중간 글자들을 덧붙인 문자 집합 데이터 파일을 추가로 생성하고, 이 데이터를 '허용 한글 범위'로 사용하는 입력 설정을 생성해 준다. 그리고 중간 글자를 표현하는 방식 중에서 (2)와 (3)은 <날개셋> 한글 입력기의 '고급 입력기'가 제공하는 글자 단위 출력 치환을 이용해서 구현한다.

(3)의 경우 목적지가 둘 이상 존재 가능하여 하나로 딱 떨어지지 않으면 (1) 타수가 더 짧은 놈, (2) 목적지가 사전 오름차순 정렬에서 먼저 등장하는 놈의 순으로 선택된다. 가령, 천지인의 경우 '쌋'이라는 중간 문자는 추가 입력을 통해 '쌌'이 될 수 있고 '쌓'도 될 수 있다. 이 경우 타수가 더 짧은 '쌓'이 먼저 제안되며, ㅅ을 끝까지 계속 눌러서 실제로 '쌌'을 입력해야 글자가 바뀐다.

사실 두벌식은 종성과 초성 사이의 연속 입력 문제--종성의 마지막 소결합이 다음 글자의 초성으로 고스란히 넘어갈 수 있음-- 때문에 허용 한글 범위 제약 기능을 구현하기가 더욱 어렵다.
어떤 초성+중성 다음에 받침 ㄱ이 허용된다면 ㄱ으로부터 해당 입력 방식에서 소결합 차원에서 파생 가능한 ㅋ, ㄲ 같은 것도 원칙대로라면 몽땅 다 허용해 줘야 한다. 그래야 해당 자음을 다음 글자에서 연속 입력할 수 있기 때문이다.

그런데 그렇게 해 버리면 모바일 입력 방식의 경우 추가적으로 허용되는 글자가 너무 많아진다. '액'이 된다는 이유만으로 '앸', '앢'도 다 허용해야 하고 '밟' 이후로 '밢' 같은 것도 허용해야 각각 'ㅋ, ㄲ, 발ㅍ' 같은 연속 입력을 할 수 있게 된다.

그렇기 때문에 두벌식의 자음 연속 입력을 위한 미래형 도깨비불은 기본적으로 '초성 분리' 형태로 행해지게 했다. '액'에서 ㅋ, '밟'에서 ㄿ로 넘어가는 순간에 ㅋ과 ㅍ은 다음 글자로 넘어가 버리고 그 자음이 ㄱ이나 ㅂ을 순환하게 된다. 그래서 연속 입력을 가능하게 하는 동시에 앞 글자에서 중간 단계의 종성을 붙들고 있어야 하는 가짓수를 줄였다.

물론 그런 파생되는 글자 중에 붙잡고 있어야 하는 글자가 존재한다면 분리시키지 않고 붙잡고 있는다. 예를 들어 '각' 다음에 '갘, 갂'은 건질 만한 게 없으니 분리되지만 '박' 다음에 '밬'은 분리되지 않고 전체 조합이 유지된다. 나중에 '밖'이라는 허용 글자가 만들어질 수 있기 때문이다. 이거 제어하는 기능이 얼마나 까다로운지 알 수 있다.

'허용 한글 범위 제약'이 제대로 돌아가려면 이 정도로 복잡하고 정교한 세부 기능이 필요하다는 것을 10여 년 전에도 본인이 모르지는 않았다. 그래서 2003~04년, <날개셋> 한글 입력기가 무려 3.0이 개발되던 시절에는 구체적으로 어떻게 구현할지는 아직 모르겠지만, 어쨌든 문자 집합을 고른 뒤에는 이와 관련된 '세부 동작'을 어떻게 할지도 지정하는 UI가 제공되었다.

사용자 삽입 이미지

'가까운 글자로 근사'가 앞서 소개한 자동 완성과 같은 개념이며, '풀어 쓴 상태로 조합'도 이해하기 어렵지 않을 것이다. 이런 개념들을 다~ 먼 옛날부터 생각은 하고 있었다. 단, '롤백'은 무슨 '빠꾸' 기능 같은데 무엇을 의도하고 집어넣었던 것인지 잘 모르겠다만..
저건 아직 지원되지 않는 기능이라고 (x)가 쳐진 채 오랫동안 잉여 UI로 전락해 있었다. 그러다가 이건 가까운 시일 내에 구현이 영 무리이겠다는 판단 하에 UI가 언제부턴가 완전히 삭제되고 오늘날에 이르렀다.

이 오랜 숙제가 8.9 버전에서 해결되었다. '쌰'만 입력했는데 '썅'이 자동으로 완성되게 하는 이론적인 근거를 마련하는 건 결코 쉬운 일이 아니었다. 지금 있는 입력 설정을 사전에 총체적으로 분석해서 pre-computed된 메타정보를 넣어 준 뒤에야 간신히 구현되었다.
자체 에디트 컨트롤의 스크롤 막대에 치명적인 문제가 있던 것도 무려 15년 묵은 버그였고 오랜 숙제들이 여럿 해결되었으니 뜻깊은 일이 아닐 수 없다. 그래서 번호도 상징성이 큰 9.0으로 정하고 싶었으나.. 뭐 8.9에서 미리 선보이게 됐다.

이런 기능들을 구현하기 위해 '허용 한글 범위 제약' 기능은 단순히 한글의 허용 여부를 예/아니요로만 지정하는 게 아니라 허용하더라도 등급을 줘서 허용할 수 있게 구조를 확장했다. 그리고 '다단계 낱자 분리'를 오토마타 차원에서 지정 가능하게 했다.

자, 지금까지 늘어놓은 개념들을 요약하면, 단순히 허용/불허 글자 지정 기능을 넘어서 (1) 중간 과정 글자 챙기기, (2) 두벌식 연속입력 가능성 챙기기 기능이 빠른설정에 도입됐다. 그리고 이를 뒷받침하기 위해 (3) 한글 범위 제약 + 다단계 낱자 분리 기능 + 오토마타 사이의 연계 강화까지 유기적인 작업이 이뤄졌다. 먼저 소개했던 버그 수정 + 사소한 기능들과는 완전한 딴판인 분야 얘기이다.

거기에 덧붙여서 본 빠른설정에는 (4) 낱자 최적화 기능도 추가되었다. 옛한글을 사용하긴 하는데 사용하는 낱자나 글자 수는 일부에 불과한 경우, 대결합을 옛한글 전체로 주더라도 한글 데이터를 쭉 분석해 본 뒤, 실제로 쓰이는 한글의 것만 결합 규칙에다 집어넣어 주는 기능이다. 이것도 시작과 끝부분에서만 안 쓰이는 것을 커트해 주는 것과, 기존 낱자들의 입력 방식이 바뀌더라도(더 짧아짐) 안 쓰이는 낱자를 중의성이 발생하지 않는 한도 내에서 짤라 버리는 더 적극적인 최적화로 옵션 지정이 가능하다.

썰 0. 작곡과 편곡의 관계

우리가 폰이나 컴퓨터에서 매일 듣는 노래 내지 음악 음원이 만들어지기 위해서는 작사, 작곡, 편곡이라는 세 가지 작업이 필요하다.
가사를 쓰는 건 일단은 음악이 아닌 문학 소양으로 가능한 일이다.
작곡은.. 아무나 할 수 있지는 않겠지만 그래도 음악 이론 안 배워도 창의력 똘끼 충만한 사람이면 절대로 못 할 일은 아니다.

나라도 5분만 해골 굴리면 지금 내 감정을 담은 짤막한 멜로디 자체는 만들어 낼 수 있다. 단지 Looking for you 같은 급의 선율을 만들 수 없을 뿐이지.
그런데 작사· 작곡 그 자체만으로 만들 수 있는 음원은 혼자 무반주로 흥얼거리는 쌩목소리 노래 녹음뿐이다.
그 선율에다가 온갖 다채로운 화음과 반주, 비트를 만들어 넣어야 한다. 그걸 넣는 작업이 바로 편곡이다.

편곡이라 했을 때 흔히 떠올리는 연주 형태 변경은 재편곡에 가까우며, <엘리제를 위하여>를 3/8박자 못갖춘마디에서 4/4박자 갖춘마디로 주선율 자체를 바꾼다거나 하는 건 개념상 아예 리메이크에 더 가깝다. 편곡의 가장 좁은 의미는 주선율이라는 뼈대에다 반주라는 살을 붙이는 작업을 말한다.
편곡은 작곡과 같은 급의 창작은 아니지만 그래도 주선율에 대한 편곡자의 해석과 창작이 들어갈 수 있으며, 매우 다양한 편곡이 나오는 게 가능하다. 또한 편곡이야말로 본격적으로 음악· 화성 이론과 각종 악기 구성에 대한 지식을 갖춰야만 할 수 있는 일이다.

그리고 따지고 보면 한글 입력 방식을 설계 구현하는 것도 이렇게 작곡에 속하는 영역과 편곡에 속하는 영역이 서로 구분되어 있다.
천지인 가획 원리로 모음을 입력한다든가, 요런 순서대로 ㄱ~ㅎ을 배당하는 것은 작곡이다.
그러나 그렇게 기본 자모의 입력법이 정립된 뒤에 이를 토대로 복합 낱자들을 입력하는 규칙을 생성하고, 그 과정에서 발생할 수 있는 내부/음절 경계의 모호성을 해소하고, 오토마타라든가 backspace 동작 등을 세밀히 customize하는 것은 편곡의 영역에 속한다.

한글 입력은 알파벳처럼 key 글자들을 주루룩 늘어놓기만 한다고 끝이 아니기 때문이다. 아시다시피 종성 ㄱ과 초성 ㄱ은 다르고 심지어 ㄱㄱ도 ㄲ과 같지 않다. 한글 입력 오토마타가 뭔가 해석을 할 여지가 남아 있다.
음악에 대해서 주선율만 만들면 나머지 반주는 별 존재감 없이 자동으로 따라온다고 생각하기 쉬운 것처럼, 한글 입력 방식도 주선율에 해당하는 부분만 만들면 나머지 mechanical한 요소는 자동으로 따라온다고 생각하기 쉽다. 하지만 실상은 그렇지 않고 훨씬 더 복잡하다.

날개셋 한글 입력기 8.8은 "복합 낱자 입력 로직 생성기"라는 빠른설정이 도입됨으로써 단순히 한글 입력 방식이라는 음악을 작곡만 가능한 게 아니라 편곡까지 자동화해 주는 도구로 수준이 올라갔다. 그리고 8.9에서는 '한글 조합 범위 제약'과 연계된 기능이 더 추가되어 완전체에 도달한 것이다.

썰1. 두벌식 옛한글 글자판의 원조는?

PC에서 옛한글 글자판이라 함은 현대 한글에 맞춰진 기존 글쇠배열을 약간 변형해서 아래아, 여린이응 등을 집어넣은 글쇠배열을 말한다. 이것도 두벌식과 세벌식이 모두 존재한다.

두벌식은 세벌식보다 글쇠 수가 적어도 되지만 낱자와 음절의 경계 구분이 잘 안 되는 관계로 모음 filler와 조합 종료라는 비문자 특수 글쇠가 두 종류 필요하다. 전자는 종성 단독 같은 미완성 한글의 입력을 위해, 그리고 후자는 모호성 해소를 위해서이다. 이게 있어야 세벌식과 동등한 표현력을 발휘할 수 있다.
세벌식은 현대 한글과 별 차이 없는 직관적인 입력이 가능하지만, 글쇠가 워낙 많이 필요하다 보니 숫자 글쇠 위치를 차지하는 것도 모자라서 이제 숫자 자체를 포기해야 한다는 단점이 있다.

다음으로 낱자 결합 규칙의 관점에서 살펴보자면.. 현대 한글에서는 ㅃㄸㅉ이 종성에 등장하지 않는 초성 전용이었다.
옛한글은 표현 범위가 더 넓어져서 저것들도 받침으로 올 수 있는 반면, 잘 알다시피 정치음과 치두음이라는 새로운 초성 전용 낱자가 등장한다.

세벌식 옛한글은 부산 대학교 김 경석 교수가 390 글쇠배열을 변형하여 고안한 글쇠배열이 저서 <컴퓨터 속의 한글 이야기>(1993)에 소개된 게 있다. 아래아한글과 내 프로그램에서 이걸 오늘날까지 그대로 지원한다. 그 뒤로 이 분야의 후속 연구는 없다시피하니 말이다. (세벌식만으로도 얼마나 마이너한데 옛한글까지?)

그러나 두벌식 옛한글 배열은 누가 공식적으로 연구해서 논문을 발표하기라도 한 게 있는지 궁금하다. 표준 두벌식은 윗글쇠에 빈 자리가 워낙 많기도 하니 그냥 비전문가 개발자가 적당히 옛한글 자모를 야메로 집어넣기라도 했는지?

오늘날 두벌식 옛한글 글쇠배열을 구경할 수 있는 프로그램은 역시나 날개셋과 아래아한글에다가 MS 옛한글 입력기(Windows 8부터, TSF A급 전용)이다.
현재 내 프로그램은 전통적으로 Shift+ㄴ에 쌍니은, Shift+ㄹ에 쌍리을, 그리고 Shift+ㅣ에 쌍ㅣ(??)이 배당돼 있다. Shift에 더블(!) 버전이 들어있는 ㅂㅈㄷㄱㅅ 자리의 관행을 따른 것이다.

하지만 아래아한글은 그 자리에 각각, ㄶ, ㅀ, ㆌ가 들어있으며 내 프로그램도 옛한글이 처음으로 지원된 2~3.x 초창기 버전은 아래아한글과 동일했다. 사실, 쌍ㅣ는 유니코드 1.1 내지 날개셋 3~4 시절에는 있지도 않던 자모였다.
내가 언제 무슨 생각으로 배열을 왜 변경했는지는 잘 모르겠다. 세벌식도 아닌데 ㄶ, ㅀ 같은 걸 한데 배당할 필요가 있는지, 저게 초성 단독으로 중세 국어 문헌에서 많이 쓰였는지도 잘 모르겠다. 중세 국어 말뭉치를 살펴보면 옛한글의 자모 사용 빈도 통계도 뽑을 수 있을 텐데.

어쨌든 내 프로그램과 아래아한글이 두벌식 옛한글 배열이 Shift 쪽에 차이가 있다는 걸 알게 됐다. 참고로 MS 입력기는 Shift+저 자리에 딱히 다른 낱자가 배당돼 있지 않은 것 같다.

끝으로, 그러고 보니 현재 두벌식 옛한글과 세벌식 옛한글은 방점의 위치가 Shift+Y/U로 서로 동일하다는 것도 처음 알았다. 지금까지 한 번도 진지하게 생각해 본 적이 없었는데 흥미로운 사실이다.

썰2. 수록할 세벌식 글쇠배열/입력 설정 파일 모집

<날개셋> 한글 입력기는 실용성, 역사성, 구현 원리의 독창성 등의 의미를 갖는 수십여 종의 입력 방식들을 예제 차원에서 내장하고 있다. 예전에도 이에 대해 언급한 바 있다.
한글의 경우 지금까지 두벌식과 세벌식을 기발한 방법으로 절충한 입력 방식, 혹은 두벌식에서 음절 경계 구분 문제를 독창적인 방법으로 해결한 입력 방식 같은 걸 주로 수록해 왔다.

하지만 그런 것에만 신경 쓰다 보니 정작 순수 세벌식 분야의 예제의 수록에는 다소 소홀한 감이 있었다. 왼손/오른손 세벌식, 맥OS/아래아한글 97 세벌식 같은 역사적 자료 말고 뭔가 본격적으로 실용적인 성능을 염두에 둔 최근 자료는 내 기억이 맞다면 팥알 님이 먼 옛날에 제작하신 '세벌식 3-3012'이 전부이다. 그 뒤로 딱히 업데이트를 한 것도 없다.

2010년대부터 소위 세벌식 진영 내부의 파편화가 두드러지게 진행되어 온 듯하다. 글쇠배열에 관심 좀 있는 분들이 다들 자기만의 글쇠배열을 만들어서 세벌식 사용자 커뮤니티 내지 자기 홈페이지에다 홍보를 하고 있다. 특히 신세벌식 패러다임은 일부 희소 낱자에만 한정해서 적용한다 하더라도 확실히 피할 수 없는 요즘 대세인 듯하다. 모든 작품들을 예제로 넣을 수는 없겠지만 그래도 제작자들에게서 제작 의도를 들어 보고, 현행 세벌식 390을 대체할 만한 가치가 있는 것을 한두 개 정도 더 수록했으면 좋겠다.

뭐, 세벌식 입문자에게는 날개셋이고 한글 기계화고 뭐고 골치아픈 건 싹 다 무시하고 당장 어디서나 설정만 바꿔서 사용 가능한 세벌식 390이나 최종부터 현실적으로 권해야 하는 건 변함없다. 그러나 좀 더 편리한 글쇠배열을 연구하는 시도 자체를 혼란을 야기한다는 이유로 백안시해서는 안 될 것이다.

Posted by 사무엘

2017/04/11 08:37 2017/04/11 08:37
Response
No Trackback , 12 Comments
RSS :
http://moogi.new21.org/tc/rss/response/1348

날개셋 한글 입력기 8.8이 나온 지도 두 달 남짓한 시간 만에.. 새 버전을 공개하게 되었다.
원래 내 계획은 새 기능 추가에만 계속 전념하다가 올해 6월 말쯤에 깔끔하게 9.0을 공개하는 것이었다. 그러나 지금까지 발견되고 수정된 버그들만 해도 꽤 중요하고 만만찮은 것들이 잔뜩 쌓이면서.. 결국 원래 구현하려던 주요 기능 하나만 작업을 마친 뒤에 8.9를 한번 더 거쳐 가기로 결정을 내렸다. 그 긴 시간 동안 심혈을 기울여 완성했던 8.8마저도 완벽한 물건이 아니었다.

원래 이 글도 새 버전 소개가 아니라 그냥 다음 버전 개발 근황 정도를 소개하는 글이 됐을 예정었으나, 글의 성격이 바뀌었다. 분량이 매우 긴 관계로, 이번 상편에서는 버그 수정과 작은 기능 얘기부터 먼저 하고, 중요한 기능 추가분은 다음 시간에 소개하겠다.

1. 오랜 버그: 스크롤 막대 딜레마 문제

이번 새 버전에서는 <날개셋> 한글 입력기의 전용 에디트 컨트롤에 존재하던 "아주 오랜 지병"이 하나 극적으로 치료되었다. 그 지병은 바로 스크롤 막대와 관계가 있다.
이건 편집기에 '자동 줄바꿈'이라는 기본 옵션이 제공된 이래로.. 3도 아닌 자그마치 2.x 시절부터 지금까지 근 15년 가까이 전혀 고쳐지지 않고 고스란히 남아 있던 문제였다. 가끔 이런 문제가 발생한다는 것이 경험적으로 알려져 있긴 했지만 그 빈도가 매우 낮으며 정확한 재연 조건을 알 수 없었다.

가끔 재연되는 케이스를 발견했을 때에도 스크롤 막대 관련 코드를 대충 건드려 보는 것만으로는 원인과 해결책을 알 수 없었다. 그래서 더 추가적인 작업 없이 프로그램은 이런 버그가 잔류한 채로 2.x에서 무려 9 직전까지 버전이 올랐다.

문제가 뭐냐 하면, "자동 줄바꿈 + 스크롤 막대"를 켜 놓고 새 문서를 텅 빈 상태에서 차근차근 작성해 보면 된다. 문서가 차지하는 영역이 가로와 세로로 적당히 한 화면의 크기를 초과할 즈음이 되면 스크롤 막대가 생긴다.

사용자 삽입 이미지

위의 그림처럼 '가나 다라'를 중간의 공백이 줄 사이에 걸치게 입력한다. 그러면 공백 때문에 가로 스크롤 막대가 생기는데, 그 상태에서 엔터를 계속 눌러서 줄 수가 늘어나서 세로 스크롤 막대가 생기게 해 볼 것. 그러면 뜻밖에도 편집창 화면의 테두리가 갑자기 저렇게 깨진다. 기술 용어를 동원하자면, non-client 영역의 표시가 맛이 간다.

사용자 삽입 이미지

이 현상은 계속 엔터를 눌러서 줄수가 늘어나면 없어지긴 한다. 하지만 도대체 저 현상이 왜 발생하는지 근본적인 원인을 알 길이 없었다. 한때는 참 당돌하게도 이건 가로· 세로 스크롤 막대 설정이 미묘하게 꼬였을 때 발생하는 운영체제의 버그이려니 하고 안일하게 생각하고 넘기기도 했다. NT 계열이 아닌 Windows 9x에서는 이때 프로그램이 아예 통째로 뻗기까지 했는데도 말이다.

이 문제의 원인은 내가 '스크롤 막대 딜레마'라고 이름을 붙인 아주 기묘한 현상 때문이었다.
처음에는 가로 스크롤 막대만 있는데, 줄 수도 늘어서 세로 스크롤 막대가 추가되었다. 그러면 세로 스크롤 막대가 차지하는 공간 때문에 편집창도 폭이(클라이언트 영역의 가로 크기) 감소한다. 자동 줄바꿈 옵션이 켜져 있다면 새로운 폭을 기준으로 텍스트의 문단 정렬이 다시 행해진다.

이제 스크롤 막대가 가로와 세로에 모두 생겼다. 그런데 편집창의 폭이 감소하면서 지금까지 가로로 한 칸 툭 튀어나오던 공백이 다음 줄로 완전히 이동했다. 가로 스크롤 막대가 필요 없어진 것이다. 그래서 최종적으로는 세로 막대만 남는 것 같은데...

이것도 끝이 아니다. 가로 스크롤 막대가 없어지니까 편집창의 높이가 증가했다. 그 결과 텍스트의 모든 줄이 한 화면에 표시가 가능해지고 세로 스크롤 막대조차 필요 없어진다. 그러니 모든 상황은 스크롤 막대가 전혀 없던 원점으로 돌아오는데...

세로 스크롤 막대가 없어지고 편집창의 폭이 원래대로 돌아오자 아까처럼 공백이 다시 줄 경계에 걸려서 가로 스크롤 막대가 필요해지는 상황으로 되돌아온다.
이솝 우화로 치면 당나귀에다 아들(가로 스크롤)만 태워도, 아버지(세로 스크롤)만 태워도, 둘 다 태워도, 둘 다 걷게 해도 어떻게 해도 사람들이 욕을 하는 것과 같은 상황이 되는 것이다.

WM_SIZE 메시지를 처리하는 과정에서 스크롤 막대의 상태가 바뀌고, 그게 또 WM_SIZE를 중첩 생성한다. 이건 이론적으로는 무한 루프에 빠지지만 실제로는 함수의 호출 깊이가 한없이 증가하기 때문에 스택 overflow로 이어진다. 다만, 대놓고 내가 짠 함수로만 스택이 깊어지는 게 아니라 message loop이 중첩해서 쌓이기 때문에 상황을 곧장 파악하지 못했을 뿐이었다.

이 문제를 해소하기 위해 WM_SIZE 메시지와 스크롤 막대 처리 함수가 일정 깊이 이상으로 종료 없이 중첩 호출되는 것을 감지하는 코드를 추가했다. 이런 꼬인 상황에서는 양방향 스크롤 막대를 깔끔하게 모두 제거시켰다. 이로써 문제를 해결했다.

사용자 삽입 이미지

2.x 때부터 있었던 지병이 9.0을 바라보는 타이밍에서야 고쳐졌다는 게 참 감개무량하다. 이건 버그가 아니라 지병에다 비유하고 싶었다. 또는 몇십 년 전에 전사한 무명용사의 유해를 이제야 DNA 감식을 통해 다시 찾아내고 신원까지 파악한 듯한 느낌에다가도 비유할 수 있겠다.

15년 전부터 존재하던 버그가 뒤늦게 고쳐지기도 하니 이 쾌감에 내가 코딩 중독에서 빠져나올 수가 없는 거다. 이걸 고칠 생각을 하게 된 건 우연한 계기 때문이었다. 지난 8.8에서 해치운 작업들을 다 삭제하고 to do list를 정리하고 있었는데, 하필 이 문서가 스크롤 막대 딜레마 오류를 일으키고 있었기 때문이다.

세월이 흐르면서 본인의 절대적인 프로그래밍 실력...이라기보다는 일단 품질을 보는 눈이 예전보다 높아졌다. 예전에는 대충 적당히 만들었던 것을 지금 꼼꼼하게 다시 개량하는 게 개발 트렌드가 됐다. 과거의 철도가 자갈 노반 나무 침목 단선 비전철이라면 지금은 콘크리트 노반과 침목에 복선 전철이 기본인 것처럼 말이다.

2. 조금 거시기한 버그: 타자연습에서 또 외부 모듈을 사용할 때의 충돌

이건 입력기 엔진의 직접적인 문제는 아닌데..
<날개셋> 타자연습에서 외부 모듈(IME)를 또 구동할 때 외부 모듈에서 플러그 인의 기능들을 사용하지 못하는 충돌 문제가 꽤 오래 전부터 있었다. 그걸 사용자의 버그 신고 덕분에야 인지하여 문제를 해결했다.

사실, 외부 모듈이 이미 <날개셋> 한글 입력기를 사용하고 있는 편집기나 타자연습 같은 프로그램(호스트)의 밑에서 돌아가는 상황에 대한 대비 자체는 오래 전부터 돼 있었다. 호스트가 자신과 바이너리 호환이 되지 않는 날개셋 엔진을 사용할 경우, 외부 모듈은 자기에게 맞는 엔진을 따로 로딩하게 했으며, 한 프로세스에 디렉터리 위치만 다른 ngs3.dll이 동작하더라도 문제가 없게 조치를 취했다.

저것 자체는 늦어도 지난 2010년대 초에 이미 다 이뤄진 일이다. 하지만 이번 문제는 그것과는 별개인 또 다른 문제였다. 동일한 ngs3.dll이 두 번 로딩되었는데 플러그 인은 한 군데밖에 없다 보니 한 프로그램에서는 내부 구조의 문제로 인해 플러그 인을 사용할 수 없었다.
이런 문제가 존재할 거라고 전혀 생각을 못 하고 있었는데 결국은 ngs3.dll을 불러들이는 방식을 변경해서 불가피한 경우가 아니면 중복 로딩이 되지 않게 했다.

3. 그럭저럭 내력이 있는 버그: 부팅 전후 외부 모듈의 crash 문제

8.8을 공개한 뒤에 의외로 외부 모듈의 안정성과 관련된 결함이 몇 군데 발견되어 해결되었다. <날개셋> 한글 입력기를 운영체제의 기본 IME로 지정한 뒤 Windows 7 기준으로,
(1) 처음 부팅을 하면 explorer 프로세스에서 오류가 발생할 수 있다.
(2) 시스템을 로그아웃/종료할 때 taskhost 프로세스에서 오류가 남.

(1)의 경우 일반적인 상황에서는 발생하지 않고 날개셋 커널이 로딩되지 못해서 외부 모듈도 아무런 제공 기능 없이 시체 상태로 동작할 때에만 그런다. IME라는 게 live 업데이트가 쉽지 않은 프로그램이다 보니, 설치 후에 재부팅을 제대로 하지 않고 뭐가 꼬이면 커널과 외부 모듈의 버전이 서로 안 맞아서 아주 드물게 저런 상황이 발생할 수 있는 듯하다.
이유야 어쨌든 날개셋 외부 모듈은 시체 상태이더라도 최소한 프로그램을 뻗게 하지는 않아야 하므로, 이는 의도하지 않은 버그이긴 하다.

그리고 (2)는 지난 8.5 버전에서 각종 이벤트 통지 기능이 추가되면서(프로그램 활성화, 글자판 전환 등) 민감한 곳을 건드리다가 생긴 버그이다. 저렇게 짜도 다른 프로그램들은 아무 문제 없는데 유독 저 프로세스만 탈을 일으켰다.
지금까지 잘만 돌아가다가 왜 그 상황에서 있어야 할 오브젝트가 온데간데없이 사라졌고 NULL인지는 정말 '귀신이 곡할' 노릇이고 도무지 알 수 없다. 그냥 결과론적인 안전 점검 루틴을 추가하는 것밖에 대처 방법이 없었다.

게다가 평범하게 문제가 발생하는 게 아니라 로그아웃/시스템 종료를 하는 순간에만 잠깐 발생하고, 그때는 종료를 취소하고 디버거를 띄울 수도 없었기 때문에 더욱 난감했다. 그래도 다행히 그때 예외 처리기 분기와 덤프 파일 생성이 됐기 때문에 이 정보와 pdb 파일을 토대로 당시 스택 프레임을 재구성하고 문제 발생 지점을 찾아낼 수 있었다.

(1)과 (2) 모두 문제가 발생한 곳은 의외로 구닥다리 레거시 imm32 프로토콜 기반의 IME 계층 쪽이었다. TSF 쪽이 아님.

4. 직전 버그: 외부 모듈에서 초성 조합 중에 특수문자 변환이 되지 않는 문제

이번엔 고질병과는 반대로 직전의 8.8 버전에만 존재하는 버그 얘기이다.
개발 연혁이 15년이 훌쩍 넘어가는 프로그램에서 더는 이런 어처구니없는 실수가 없어야 정상이겠지만 안타깝게도 그런 예가 하나 발견되어 이 자리를 통해 알리도록 하겠다.
8.8 버전은 외부 모듈에서 ㄱ~ㅎ 같은 자음을 조합하고 있는 상태에서 후보 변환(한자 같은)을 눌러 특수문자를 입력하는 기능이 제대로 동작하지 않는다.

더 구체적인 문제 발생 조건은, 자음을 호환용 한글 낱자로 바꿨을 때(외부 모듈 환경 또는 최종 변환 규칙을 통해서)이다. 그렇기 때문에 편집기에서 최종 변환 규칙 없이 그냥 자음을 단독으로 입력하고 있을 때는 문제가 없다.

이것은 8.8에서 새로 추가된 '앞에서 뒤로 탐색하여 단어 단위 한자 변환' 기능으로 인해 발생한 부작용이다.
새 기능인 '앞에서 뒤로 탐색'(즉, '토선생'을 변환하면 '선생'이 아니라 '토선'이 먼저 제안되는 것)을 선택했을 때는 그런 부작용이 없고, 예전부터 지원되던 동작인 '뒤에서 앞으로 탐색' 또는 단어 단위 한자 변환을 사용하지 않으면 저렇게 초성+한자 특수문자가 동작하지 않게 된다.

메모장은 TSF 확장 옵션을 사용하지 않으면 어차피 단어 단위 한자 변환이 동작하지 않는 환경인데도 저런 옵션의 영향을 받는다.
사소한 버그이기 때문에 다음 버전에서는 문제가 곧장 고쳐졌다.

5. 기능 추가: 외부 모듈에 키보드 드라이버 배열 미리보기

외부 모듈의 '시스템 - 고급 시스템 옵션' 제어판 페이지에는 지난 8.6때부터 "한글 IME와 연결할 영문 키보드 드라이버" 지정 기능이 추가되었는데, 사용자가 선택한 키보드 드라이버의 글쇠배열을 간단하게 미리 들여다보는 기능이 추가되었다.
<날개셋> 한글 입력기에 키보드 드라이버를 바로 불러오는 기능은 무려 10년 전 4.4 버전부터 존재했다. 그러니 그 기능을 여기에다 연계하지 못할 이유가 없다.

사용자 삽입 이미지

'보기' 링크를 누르면 글쇠배열 그림이 별도의 modal 대화상자의 형태로 뜬다.
좀 더 욕심을 내자면, 옛날에 MS Excel에서 차트 미리보기 기능처럼 뭔가를 누르고 있는 동안만 preview가 뜨고, 버튼에서 손을 떼는 순간 그림이 사라지는 게 내 본래 의도이다.

하지만 그런 기능이 운영체제의 표준 GUI에는 존재하지 않고, 또 키보드 드라이버 변경 기능이 한글 입력과 직접적인 관계가 있으면서 많이 쓰이는 기능은 아니라고 생각되어 그냥 이 정도 기능만 넣는 것으로 그쳤다.

6. 그 밖에

(1) 외부 모듈과 변환기에는 유니코드 5.2 옛한글을 호환성 차원에서 1.1 과거 방식으로 풀어서 표시하는 옵션 내지 기능이 있는데.. 8.8 버전에서는 이 부분의 코드가 리팩터링 되던 과정에서 더 풀어서 표시해야 하는 낱자를 풀지 않고 잘못 표시하는 문제가 들어갔음을 뒤늦게 발견했다.
가령 ㅗㅒ는 ㅗㅑㅣ로 더 풀어야 하고 중성엔 ㅛㅐ, ㅠㅐ, ㅣㅖ, ㅡㅔ, ㅣㅒ, ㆍㅔ 같은 예가 더 있다.
오늘날이야 유니코드 1.1 옛한글은 한양 PUA보다도 인지도가 없고 거의 쓸 일 없으니 당장 대다수 사용자에게는 별 여파는 없는 문제이긴 한데, 이런 문제 자체가 있다는 건 밝힌다. 이번 새 버전에서 곧장 해결되었다.

(2) Metro 앱에서 시스템 계층의 키보드 드라이버 보정 기능이 동작하지 않던 것을 동작하게 했다. (연결되는 키보드 드라이버 자체를 변경하는 것은 여전히 지원 불가) 그리고 지금까지 Internet Explorer 11 내부의 텍스트 입력란(주소 입력란 말고)에서 외부 모듈의 글자판 동기화가 되지 않고 입력 패드도 동작하지 않던 문제를.. 우연한 계기로 드디어 해결했다.
IE는  IME 개발자의 입장에서 굉장한 요물이고 뭔가 자체적인 샌드박스 같은 환경을 갖춘 것 같았는데 메트로만치는 아니어도 어느 정도 샌드박스가 있긴 했다. 이런 부류의 문제들이 하나하나 해결돼 가는 걸 보는 건 내 인생의 낙이다.

(3) 오랫동안 '외장형 후보' 예제 데이터 파일로는 구결밖에 없었는데, 정 재민 님의 제안으로 대법원 제정 인명용 한자 목록 8000여 자를 추가했다. 제1후보를 대체하는 물건으로 활용 가능하다.
이게 의외로 종이 문서나 이미지로만 존재하거나, 글자별 조회만 가능하지 전체 목록을 뽑기가 쉽지 않았는데 일일이 목록을 만든 분이 국내도 아니고 일본에 있었다. (☞ 출처) 참고로 인명용 한자는 한번 정하고 끝이 아니라 계속 추가되는 편이다.

(4) 타자연습의 게임은.. 아예 운영체제의 표준 GUI만 사용하는 다른 연습 UI보다는 비주얼이 낫겠지만, 그래도 요즘 게임 트렌드에 비해서는 기술적으로 너무 뒤쳐진 구닥다리가 됐고 게임 시스템도 좀 바꿔야 할 때가 됐다.
하지만 전면개편을 하기에 앞서..;; 또 사소한 UI를 좀 고쳤는데,

게임 화면 하단은 시스템의 색상과(특히 고대비 검정 같은) 관계없이 언제나 흰 배경에 검은 글자로 찍히게 했다.
그리고 컴퓨터 속도가 2GHz를 넘어간다 싶으면 "256색 전체 화면" 옵션을 없애고 표시하지 않게 했다.
옛날에 Windows 2000/XP 초창기에는 256색 전체 화면이 트루컬러 전체 화면보다 속도가 더 빠르고 진행이 원활한 경우가 있어서 저 옵션을 넣은 것이었지만, 오늘날이야 당연히...;; 아무 차이가 없어졌기 때문이다.
게임도 창 모드로 실행될 때는 자기 별도의 창을 띄우는 게 아니라 프로그램 main 창 내부에서 돌아가게 하고 싶긴 하다.

추신: 외부 모듈이 IME 목록에 나타나지 않는 이유는?

<날개셋> 한글 입력기를 설치하고 나면 외부 모듈도 일부러 제외하지 않은 한 같이 설치되고 운영체제 IME로서 등록된다.
그런데 <날개셋> 한글 입력기가 한 번도 설치된 적이 없던 완전히 새 컴퓨터에다 프로그램을 처음 설치한 경우, IME 목록에 내 프로그램이 제대로 뜨고 있는지 궁금하다.

IME 목록에 곧장 나타나지 않는 경우도 종종 있어서 말이다. Windows 8/10에서 특히 그러하다. 이 경우, 입력 언어 제어판을 꺼내서 '한국어 - 추가'를 누르면 거기에 <날개셋> 한글 입력기가 숨어 있곤 한다. 이걸 수동으로 꺼내야 사용 가능하다.

이것은 기술적으로는 입력 언어의 enable/disable 상태 차이 때문에 그렇다. 그런데, 새로 등록된 내 IME를 enable시키려면 이러이러한 함수를 호출하면 된다고 MSDN에서 시키는 대로 다 했는데도 일부 컴퓨터에서는 설치 직후에 <날개셋> 한글 입력기가 곧장 나타나지 않는 듯하다.
현재로서는 이유를 알 길이 없다. 그럴 때는 딱히 해결책이 없으며, 사용자가 수동으로 내 입력기를 추가해 주면 된다고 도움말에다 써 놓기만 했을 뿐이다.

(下에서 계속됨)

Posted by 사무엘

2017/04/08 08:38 2017/04/08 08:38
Response
No Trackback , 2 Comments
RSS :
http://moogi.new21.org/tc/rss/response/1347

0. 들어가는 말

<날개셋> 한글 입력기와 타자연습이 개발 17년째에도 변함없이 온갖 새로운 기능들로 무장하여 새 버전이 나왔다. 4개월 동안 정말 많은 기능들이 추가되고 개선되었다. 지금까지 올라온 개발 근황글 시리즈만 봐도 이번 버전은 뭔가 심상찮다는 것을 알 수 있을 것이다.

정상적인 개발 사이클이라면 지금보다 더 전에 새 버전이 나오고도 남았을 텐데 이번 버전만 이례적으로 중간 개발 근황글이 많아진 이유는..
8.8의 개발 완료 조건은 따로 있었는데 그게 너무 어려워서 오랫동안 충족되지 못하는 동안, 다른 분야에서 새 기능들이 잔뜩 추가되고 개선 사항이 생겼기 때문이다.

그것들이 새 버전 형태로 석방(release)되지 못한 채 장기간 갇혀 있었다. 지금 새 기능 리스트를 다시 읽어 보면 나로서는 "아니 이건 언젯적 작업 내역인데 8.6에서는 아직 반영이 안 된 상태였구나. 내 프로그램 사용자들은 작년 10월 이후로 시간이 정지해 있었구나!" 싶은 것들이 많다. 그걸 이제야 훌훌 털어내고 밖으로 내보내게 되어 참 기쁘다.

이 글에서는 이번 8.8 버전에서 궁극적으로 추가하려고 했고 시간적으로 제일 마지막에 구현된 '복합 낱자 입력 로직 생성기'에 대해서 소개하도록 하겠다. 이것은 <날개셋> 한글 입력기가 제공하는 '빠른설정' 중의 하나이다.

1. 빠른설정

빠른설정이란 어떤 입력 항목에 대해서 사용자가 선택한 옵션대로 입력 스키마와 문자 생성기를 곧바로 세팅 해 주는 보조 GUI의 총칭이다. 지금 이미 지정돼 있는 입력 설정을 보완· 변경할 수도 있고, 그건 싹 무시하고 완전히 새로운 입력 설정으로 덮어쓸 수도 있다.

요런 개념과 기능은 먼 옛날, <날개셋> 한글 입력기 3.0에서 처음으로 도입됐다. 그리고 역사상 최초로 도입된 빠른설정은 '기본 글자판 설정'이었다. 두벌식, 세벌식, 쿼티, 드보락처럼 사용자가 가장 자주 사용하는 한글과 영문 글자판을 묻지도 따지지도 않고 곧바로 맞춰 주는 중요한 역할을 한다. 한글의 경우 옛한글 사용 여부, bksp의 동작 단위 같은 옵션을 받기도 한다.

그러다 지난 2006년, 3.9 버전에서 빠른설정이 3개가 더 추가되어 4개가 되었으며, 빠른설정은 이렇게 4개가 거의 10여 년 동안 변경 없이 그대로 유지돼 왔다.
먼저, 한글 로마자 입력기. 얘는 기반 영문 글쇠배열(쿼티 or 드보락)과 로마자-한글 매핑 방법 같은 몇 가지 옵션을 받아서 로마자 입력 방식을 설정해 준다. 한글 로마자 입력 방식이라는 건 딱 한 가지만 존재하는 게 아니라 어떤 공통된 사상, 이념, 컨셉에 속하는 다양한 입력 방식들을 찍어 내는 '메타 입력 방식'에 가깝다. 그러니 이런 건 '빠른설정'이 커버하기에 적합하다.

한글 로마자 입력기는 한국어· 한글을 배우는 외국인에게 매우 유용하다. 그래서 <날개셋> 한글 입력기의 영문 페이지는 프로그램의 모든 기능을 영어로 소개하지는 못하는 대신, 입력 설정을 로마자 입력 방식으로 바꾸는 방법만을 간단히 안내해 놓았다.

나머지 빠른설정은 주어진 세벌식 글쇠배열을 표준 두벌식 배열과 합성해 주는 '복벌식 빠른설정', 그리고 한 글쇠에서 초성과 종성이 아니라 중성과 종성을 수식으로 구분해서 합성한 '신세벌식 빠른설정'이 있다. 이들 역시 두벌식과 세벌식을 절충하는 훌륭한 메타 입력 방식이므로 빠른설정 형태로 구현했다.
전자는 타자가 처음에 왼손으로 시작됐으면 두벌식, 오른손으로 시작됐으면 세벌식으로 인식해 준다. 후자는 도깨비불 현상이 없으면서 4단도 사용하지 않는 입력 방식이라는 의의가 있다.

'기본 글자판'과 '한글 로마자 입력기'는 완전히 새로운 입력 환경을 맞춰 주는 빠른설정이지만 복벌식과 신세벌식 빠른설정은 기존 입력 설정에다가 변형을 가하는 형태로 동작한다.
그러다가 제5의 빠른설정인 '복합 낱자 입력 로직 생성기'가 거의 10년 만에 또 추가되었다. 얘 역시 기존 입력 설정을 변형하는 형태로 동작한다. 단, 글쇠배열 같은 입력 스키마 설정은 직접 건드리지 않으며, 문자 생성기 계층의 설정을 건드린다. 뭐, 글쇠배열을 직접 고치지는 않더라도, 필요한 경우 요런 글쇠를 사용자가 직접 배당해서 쓰라고 안내를 해 주긴 한다.

이 로직 생성기는 단순한 편의 기능 이상으로 <날개셋> 한글 입력기의 아주 중요한 핵심 기능이다. 이거 하나만 코드의 양이 2천 줄을 넘어가며, 기존 4개 빠른설정들의 코드를 다 합한 것보다도 분량이 2배 이상 많다.

2. 본 기능 소개

복합 낱자 입력 로직 생성기가 하는 주된 일은.. 초중종성의 낱자 결합 규칙을 편의상 '대결합'과 '소결합'으로 또 나눠서 대결합을 소결합 노가다만으로 몽땅 자동 생성해 주는 것이다.

좀 formal하게 표현하자면, 기존 설정(소결합)과 우리 빠른설정 자체의 설정(대결합) 사이의 cartesian product를 구한다.
그리고 이와 연동해서 같이 움직이는 가상 낱자, 특수 도깨비불, 심지어 한글 치환 규칙을 다 자동으로 맞춰 주며, 대결합과 소결합 사이에 논리적으로 충돌이 있는 것도 감지해서 보여주고 회피해 준다.

PC용 한글 입력 방식이라면 낱자 결합 규칙을 굳이 대결합과 소결합으로 나눌 필요가 없다. 하지만 글쇠 수가 왕창 적은 모바일에서 옛한글 같은 복잡한 한글 입력 방식을 구현한다고 생각하면 저런 추가적인 추상화가 반드시 필요하다.

ㅎ 같은 기본 자모를 "ㅇ+가획"(나랏글) 내지 "ㅅ+ㅅ"(천지인)의 합성으로 입력하는 건 소결합이다. 그러나 ㄴ+ㅎ으로 ㄶ을 입력하고 ㄹ+ㅎ으로 ㅀ을 입력하는 건 대결합이며 어느 입력 방식이든 동일하다. 그러면 이 로직 생성기는 소결합과 대결합을 토대로 ㄶ과 ㅀ을 입력할 때 필요한 중간 상태인 ㄴㅇ, ㄹㅇ도 날개셋의 기존 기능으로 다 표현해 준다는 것이다.

이런 예가 옛한글로 가면 얼마나 많겠는가? 게다가 두벌식의 경우는 한 낱자를 다 입력한 뒤에도 아직 안심할 수 있는 상황이 아니다. 나랏글 기준으로 ㄽ이라는 겹받침을 입력한 뒤에도 ㄹㅈ, ㄹㅉ, ㄹㅊ 같은 임시 낱자를 고려해 줘야 ㄹ 다음에 ㅈ 계열 자음들을 연속 입력을 할 수 있다.

요런 식의 자동화를 종성에 한해서 찔끔 간단하게 구현해 준 것이 바로 6.x 버전 시절에서 추가된 '초-종성 공용 낱자 결합'이었다. 하지만 임시 낱자들의 처리는 여전히 사용자가 해야 하고 한계가 많았다. 그러다가 복합 낱자 입력 로직 생성기가 추가됨으로써 <날개셋> 한글 입력기는 한글 엔지니어링의 영역을 한 단계 넓혔다.

3. 예제

사용자 삽입 이미지

위의 그림은 천지인 입력 방식을 설정한 뒤, 대결합과 소결합 사이의 관계 분석을 통해 종성-초성 사이에 연속 입력이 안 되는 pair들을 프로그램이 찾아 준 것이다. 천지인은 모든 종성에 대해서 연속 입력이 안 되는 초성이 적어도 하나 이상 존재한다. 그 반면, Google 단모음 입력기라면 ㄱ, ㅅ뿐만 아니라 쌍자음이 존재하는 ㄺ, ㄽ, ㅄ 같은 일부 자음만이 이런 조건에 걸린다.

'글자판 입력을 문자열로' 텍스트 필터에는 사용자가 입력한 문자열에 대해서 연속 입력 가능 여부를 판별하는 기능이 있는데, 이 빠른설정은 아예 구조적으로 연속 입력이 불가능한 모든 경우의 수를 찾아 준다는 차이가 있다.

사용자 삽입 이미지

천지인과는 달리 나랏글은 구조적인 모호성이 없기 때문에 로직 생성 결과가 깔끔하다. 나랏글은 소결합을 담당하는 글쇠(가획, 쌍자음)와 대결합을 만드는 타 한글 자모 글쇠가 완전히 분리되어 있기 때문이다. 다만, 생성되는 임시 낱자 수는 나랏글이 천지인보다 더 많다.

중성을 보면 나랏글에서 ㅝ를 입력하기 위해 중간에 거치는 ㅜ+ㅏ를 이 프로그램이 자동으로 처리해 줬다는 말이 뜬다. 사용자가 일일이 대결합에 등록하지 않았더라도 말이다. 그리고 이 경우, ㅜ+ㅏ까지만 입력해도 화면에는 절차를 단축해서 자동으로 ㅝ를 띄워 준다. (대결합의 마지막 단계가 확정되어 다른 선택의 여지가 없을 때)
또한 중성에는 쌍자음(501) 글쇠가 결합용으로 전혀 쓰이지 않았다는 것도 알려 준다.

사용자 삽입 이미지

이건 좀 더 엄청난 장면이다. 천지인의 모음 입력 방식을 옛한글에다가도 적용했을 때 입력 순서가 동일해져서 충돌이 발생하는 쌍을 모두 찾은 것이다. 천지인의 경우 음절 경계에만 모호성이 있는 게 아니라 한 성분 내부에서도 ㅡㆍㆍㅡ를 ㅝ(2:2)로 보느냐 ㆌ (3:1)로 보느냐 같은 문제가 존재하기 때문이다. 단, 이건 세벌식이라도 구조적으로 얼마든지 존재할 수 있는 모호성이다.

인위적인 모호성 보정이 없다면 이 프로그램은 언제나 대결합보다 소결합을 우선시하기 때문에 2:2(ㅝ)가 아닌 3:1(ㆌ)이 채택된다. 이때 모호성은 2가지 방법 중 하나로 회피할 수 있는데, (1) 먼저 사전 구분이다. 2타까지 치고 'ㅜ+보정'을 누르면 이 ㅜ는 ㅠ로 넘어가는 ㅜ가 아니라 ㅜ+ㆍ, ㅜ+ㅓ 등 대결합 경계가 바뀌는 임시 낱자 ㅜ로 바뀐다. 즉, 임시 낱자도 입력을 위한 것과 모호성 보정을 위한 것 두 종류로 나뉜다.

(2) 그리고 사후 변환을 할 수 있다. 이미 ㅠ 또는 ㆌ가 된 상태에서 이 변환을 누르면 ㅜㆍ 또는 ㅝ를 왔다갔다 할 수 있다.
이 프로그램은 입력 순서가 동일한 낱자들에 대해 일정 시점에서 구분자를 넣어서 상태를 분기하는 것을 일종의 binary tree 형태로 표현해서 관리하는데, 사전 구분은 그렇게 가지를 뻗는 것이고 사후 변환은 자신의 가장 가까운 sibling을 왔다갔다 하는 것으로 정의한다.

(1) 또는 (2), 그리고 (1)과 (2)를 모두 사용하는 것도 가능하다. 이 프로그램은 마치 나랏글의 가획/쌍자음처럼 저런 사전/사후 보정용 낱자를 초중종성 공용으로 하나 설정한 뒤, 수식을 생성해서 사용자에게 다음과 같이 안내도 해 준다.

입력 중에 낱자 결합 모호성을 해소하려면 다음 수식을 글쇠배열에 배당하여 사용하십시오.
- 사전 구분:
  F ? H2|0x25800000000 : E ? H2|0x2580000 : D ? H2|0x258 : 0
- 사후 변환:
  F ? H2|0x25900000000 : E ? H2|0x2590000 : D ? H2|0x259 : 0


또한 사후에라도 대결합 적용 방식이 바뀌는 것조차 처리해 준다. 현대 한글에서는 굳이 저렇게 보정을 하지 않아도 ㅠ 다음에 ㅣ가 입력됐을 때 ㅝ로 바로 넘어가게 할 수 있다. ㆌ가 쓰이지 않으므로 모호성이 없기 때문이다.
옛한글의 경우 위의 스크린샷에서 보다시피 소결합 단독으로 처리되던 ㅖ에서 옛한글 ㅕㅑ로 자동으로 넘어가는 것, ㅜㅡ에서 ㅡㅗ로 자동으로 넘어가는 것 등 그런 예가 더 많다.

한글 입력 방식의 고안자는 소결합 수준에서 기본 한글 자모를 입력하는 방법만 생각하면 된다. 이로부터 복합 자모를 입력하고 오류를 찾는 온갖 복잡한 노가다는 이제 컴퓨터 프로그램이 알아서 해 준다!

비록 한글 타자는 마치 알파벳 풀어쓰기처럼 sequential하게 이뤄지지만 한글은 구조적으로 ㄱㄱ과 ㄲ이 동일하지 않고 초성 ㄱ과 종성 ㄱ이 같지 않은 문자이다. 자체적으로 낱자 경계가 있고 음절 경계가 있는데 이것 구분을 한글 입력 오토마타가 implicit하게 자동 처리하게 된다. 이와 관련해서 생각할 수 있는 거의 모든 자동화 절차를 이 빠른설정이 담당해 준다.

작년에 본인이 부산 학회에 가서 발표한 논문(한글 및 한국어 정보 처리 학술대회)이 바로 이런 시스템의 구현에 관한 것이었다. 본인은 박사 졸업 이수요건 충족을 위해 중간에 이렇게 한글 자체에 지극히 특화된 연구를 해서 논문을 투고하고 발표하게 된 것에 자부심을 느낀다.

4. 옵션 대화상자

'복합 낱자 입력 로직 생성기'는 이례적으로 마치 설치 프로그램처럼 단계가 휙휙 진행되는 마법사 형태로 UI가 구현되었다. 1단계는 대결합을 지정하는 단계이며, 마지막 3단계는 지금까지 봐 온 결과 로그 화면이다.
운영체제가 제공하는 마법사 UI는 대화상자의 크기 조절을 지원하지 않기 때문에 마법사 UI를 불가피하게 자체 구현했다. 로그가 분량이 상당할 수도 있기 때문에 크기 조절 기능이 없으면 안 된다. 그리고 마법사 UI는 자체 구현하는 것도 그리 어려운 일은 아니니..

사용자 삽입 이미지

그리고 위의 그림은 바로 중간의 2단계인 옵션 지정 화면이다. 복합 낱자 입력 로직과 관련하여 이 옵션들을 생각해 내고 구현하는 게 지금까지 정말 머리 쥐어 뜯도록 힘든 일이었고, 개념을 도움말에다 설명하는 것도 어려웠다. 내가 누구만치만 머리가 빨리빨리 잘 돌아가기만 했어도..;; 단지 나보다 똑똑한 사람들은 이런 프로그램을 만들 생각 자체를 안 하겠지..

'글쇠배열 종류'를 두벌식이 아닌 세벌식으로 지정하면 음절 경계 체크라든가, ㅂㅉ, ㅂㅊ처럼 종성 연속 입력을 위한 임시 낱자 생성이 생략된다. 세벌식에서는 그런 걸 고려할 필요가 없으니까.

그리고 '옛한글 자모 사용' 옵션을 '끄면', ㄸㅃㅉ 같은 건 종성에 등장이 허용되지 않고 자동으로 다음 글자 초성으로 넘어간다. 이런 지저분 자질구레한 처리까지 가상 낱자와 한글 출력 치환을 이용해서 이 빠른설정이 알아서 다 세팅해 준다.
옛한글을 사용하더라도 정치· 치두음 같은 건 어차피 초성 전용이니 그런 게 종성에 등장하지 않게 처리된다.

'미리 분리' 옵션은 "(갇) ↔ (가ㄸ)" 왕복을 하느냐 "(갇) → 가(ㄸ) ↔ 가(ㄷ)" 왕복을 하느냐 차이를 결정한다. 이런 자음들을 그냥 다음 글자로 보내 버리면 종성에 생성되는 임시 낱자의 개수가 상당수 줄어든다. 세벌식에서는 초성 전용 자음을 처리할 때를 빼고는 이런 옵션이 필요하지 않다.

또한 세벌식에서는 아까 나랏글 중성 ㅜㅏ → ㅝ 단축처럼 종성도 ㄴㅇ까지만 입력하더라도 ㄶ으로 자동으로 단축이 가능하다. 단지 두벌식에서는 허용되지 않을 뿐이다. 진짜 받침 ㄴ + 초성 ㅇ을 의도한 것일 수도 있기 때문이다. 이런 세밀한 처리까지 다 고려해서 동작한다.

로직을 생성해 보니 결합 모호성이 존재하는데도 '모호성 해소 방식' 두 옵션 중 적어도 하나 이상이 선택돼 있지 않으면 일부 낱자는 모호성 때문에 입력할 수 없을 거라고 경고문이 끝에 나온다.
단, "짧은 소결합으로 연장 결합 지원" 옵션을 켜면 일부 낱자는 입력 가능해질 수도 있다. 아까 ㅠ에서 ㅝ로 자동으로 넘어가는 것처럼 말이다.

옵션들에 대한 더 자세한 설명은 대화상자에서 F1을 누르면 볼 수 있다.
8.8의 다음 버전은 올해 6월쯤에 나올 9.0 정도로 잡고 있다. 9.0에서는 이 빠른설정에 '허용 한글 범위' 제한 기능과 연계하는 새로운 기능이 더 추가될 예정이다.

* 마지막 썰: 프로그램 관련 문의는 둘 중 한 곳으로

'복합 낱자 입력 로직 생성기'는 이번 버전의 워낙 독보적인 끝판왕이다 보니 이거 하나만 간략하게만 소개했는데도 글 분량이 벌써 이만치가 됐다. -_-;;
기능 자랑은 이 정도로 하고, 이제 프로그램 관련 공익 광고(?)를 덧붙이며 글을 맺고자 한다.
본인은 여건상 개발자와 사용자 사이의 소통을 위해서 딱히 <날개셋> 한글 입력기 공식 게시판이나 카페 같은 걸 운영하고 있지는 않다. 프로그램 관련 문의는

  1. 공개적으로 하려면 프로그램의 다운로드 페이지에 있는 페이스북 플러그 인
  2. 비공개로 몰래 하려면 본인의 개인 메일(gmail)

둘 중 한 곳으로 하는 것을 가장 권장한다.

블로그에 올라오는 날개셋 한글 입력기 새 버전 공지글의 댓글로는 가능한 한 새 버전에 대한 의견만을 가장 권장한다. 하지만 이전 버전부터 보편적으로 있던 기능에 대한 문의가 올라오는 걸 명시적으로 금지할 것도 없기 때문에 받아들일 뿐이다.

다음으로 블로그 방명록이 있다. 여기도 프로그램 문의 게시판은 아니다. 그렇기 때문에 거기엔 내 블로그 방문 소감이나 안부 인사만 권하지 프로그램 문의는 원하지 않는다. 뭐, 문의글이라고 해서 무슨 스팸 광고글 쓰레기는 아니니, 게시판의 원래 성격에 맞지 않은 글이라고 해서 내가 매정하게 무시 또는 삭제한다거나 하지는 않는다. 답변을 하긴 하지만 그래도 원래 취지와 권고 사항은 저렇다는 거다.

페이스북 플러그 인을 열면서 동시에 내 페이스북 계정도 노출되었는데.. 요 몇 년 간 지켜보니 페이스북 쪽지로 프로그램 문의를 하는 분도 있었다. 하지만 쪽지로는 보내지 마시기 바란다.
페친이 아닌 모르는 사람이 보낸 쪽지는 페이스북이 알림창으로 안내를 하지 않기 때문이다. 그래서 쪽지가 왔다는 것을 내가 즉시 알아채기가 거의 불가능하다. 거의 몇 달 뒤에야 뒤늦게 발견해서 답변을 허겁지겁 했거나 아니면 그 사이에 질문자가 계정을 삭제하여 답변을 못 하게 된 일이 몇 번 있었다.

아무튼, 이 점을 염두에 두고 프로그램 관련 문의는 페이스북 플러그 인 또는 메일 중 한 곳을 이용해서 하셨으면 한다.

Posted by 사무엘

2017/02/15 08:28 2017/02/15 08:28
Response
No Trackback , 17 Comments
RSS :
http://moogi.new21.org/tc/rss/response/1327

다음 버전 개발 근황 3

<날개셋> 한글 입력기의 다음 버전 8.8은 이례적으로 개발 근황글만 무려 3차분까지 올라오게 됐다.
개발 완료 조건은 "원래 생각하고 있던 굉장히 어려운 기능을 다 구현하는 것"인데.. 원래 목표는 달성되지 못한 상태에서 온갖 자잘한 다른 개발 작업만 애드립으로 엄청나게 쌓이고 쌓였기 때문이다.
이것만 감안해도 8.8을 넘어 8.85나 8.9로 가야 하지 않나 고민될 지경이 됐다.

※ 외부 모듈 분야

1. "조합을 자체 처리하는 프로그램에서만 동작" 옵션

<날개셋> 한글 입력기가 외부 모듈이 개발된 이래로 왜 이런 걸 지금까지 생각 못 했을까 싶은 기능이 사용자의 기능 제안 메일과 갑자기 떠오른 아이디어, 발상의 전환을 토대로 하나 추가되었다.
외부 모듈 제어판의 "시스템 계층 - 고급 시스템 옵션" 탭에 있는 "조합을 자체 처리하는 프로그램에서만 동작" 옵션이다.

IME들은 글쇠 입력을 가로채서 한글 같은 조합을 생성 후, 그 결과를 응용 프로그램으로 보낸다. 워드 프로세서나 에디트 컨트롤은 텍스트 입력을 전문적으로 처리하는 프로그램이니, IME가 보낸 문자열을 즉각 본문에다 삽입하여 화면에 직접 표시한다. 그러나 그런 처리를 하지 않는 프로그램에서는 운영체제 또는 IME가 자체적으로 자그마한 창을 꺼내서 조합 중인 문자열을 표시해 준다.

기술적으로 이런 동작의 차이를 IME-awareness라고 표현한다.
그런데 IME가 자체적인 조합 창을 꺼내야 하는(IME-aware하지 않음) 프로그램이라면 십중팔구 한글을 입력할 일이 없고 한글 모드가 존재할 필요가 없는 상황이다. 문자 입력을 받는 상황이 아니며, 각각의 알파벳 글쇠들이 어떤 기능을 수행하는 단축글쇠인 경우가 대부분이다.

저 옵션이 켜져 있으면.. 먼저 조합을 보내 봤는데 프로그램이 조합 문자열을 제대로 표시하지 않고 IME로 되돌려보내는 경우, 조합을 없애고 원래 글쇠를 응용 프로그램으로 다시 보내 준다~!
가령, 그래픽 툴의 경우 B는 브러시, F는 채우기, X는 텍스트, S는 영역 선택인데, 한글 모드라 하더라도 해당 글쇠를 누르면 쓸데없이 ㄹ, ㄴ 같은 조합 창이 생기는 게 아니라 기능 모드가 바뀐다. 그러면서 텍스트 입력은 곧장 한글 모드로 할 수 있게 된다.

물론, 아주 옛날에 만들어져서 국제화 관념 따위 없고 유니코드조차 지원하지 않을 정도인 구닥다리 외국산 프로그램 중에는 무려 텍스트를 입력받는데도 IME-aware하지 않은 경우가 있다. 옛날에 Visual C++ 6의 IDE조차 그러했다. 그런 프로그램에서 한글을 입력하려면 저 옵션을 켜서는 안 된다. 그러나 저 옵션은 요즘 같은 시대엔 거의 모든 상황에서 사용자의 번거로움을 해소해 주는 매우 편리한 기능이 될 것이다.

그리고 반가운 소식이 이것만 있는 게 아니다.
저렇게 조합이 도로 튕겨서 돌아오는지 감시하기 위해서는 약간의 성능 부하가 필요한데, 이걸 해결하는 과정에서 Google Chrome + 하드웨어 가속에서 조합 덧나는 문제도 같이 해결하게 되었다. 외부에 의해서 조합이 강제 중단되는 상황을 감지하는 방법을 추가적으로 알아냈기 때문이다.

물론, 마소 IME가 날개셋과 동일한 방법을 써서 해결한 것 같지는 않기 때문에 이 역시 완전히 근본적이고 원초적인 문제 해결이라고 여기기는 어렵다. 하지만 "조합을 자체 처리하는..." 옵션을 켜면 일단 Google Chrome 문제도 덤으로 해결되긴 한다는 것을 밝힌다.
이렇듯, '고급 시스템 옵션'에는 구현체들 중 오직 외부 모듈에만 적용되는 온갖 기상천외한 옵션들이 들어있다.

2. 긴 조합이 튕기는 문제 자체 보정

TSF B급 프로그램에서 2글자 이상 길이의 조합을 시작했을 때 조합이 끊기는 골치 아픈 문제 말이다.
단순히 이런 문제가 존재한다고 알려 주기만 하고 "운영체제의 이상한 동작이어서 더 어쩔 수 없음. 사용자가 알아서 조심하시고 조합 시작은 언제나 1글자 단위로 시작하게 노력해 보세요"라고 대응하고 끝내던 것이 이번 버전에서 개선되었다.

처음에 2글자 이상 조합을 덥석 만드는 것만이 문제이지, 처음엔 가상의 1글자 조합을 만든 뒤에 곧바로 원래 길이의 긴 조합으로 대체하는 것은 괜찮다는 특성을 이용하여 내부적으로 일종의 회피, 보정 옵션을 구현했기 때문이다.
이제 두벌식 옛한글 입력기에서 '한' 다음에 곧바로 '하 + ㄴ아래아' 같은 글자를 도깨비불 현상으로 만드는 것도 아무 걱정 없이 할 수 있게 됐다.
비록 조합 중인 문자 자체는 한 글자밖에 안 보이고 그거 제어하는 건 애초에 IME의 영역도 아니기 때문에 어쩔 수 없지만, 최소한 조합이 끊어지고 엉뚱한 동작을 하는 문제는 사라졌다.

세상에 이런 간단한 아이디어를 구현할 생각을 왜 지금까지 안 하고 있었나 모르겠다.
사용자가 굳이 이 옵션을 켜지 않더라도 조합이 끊어졌다 싶으면 프로그램이 알아서 이 옵션을 켜며, 켰다는 사실을 사용자에게 알려 준다.

혹시나 해서 다시 말하는데, 이렇게 2글자 이상의 조합 시작을 막는 건 Windows 운영체제가 거의 일부러 저러는 것이다.
한글 IME는 전통적으로 중국어· 일본어 IME와는 달리, 조합 문자열을 밑줄 대신 깜빡이는 네모 cursor로 표시하는 등 내부적으로 처리가 다르게 돼 왔다. 자체 한글을 구현한 도스용 프로그램들의 관행을 마소에서 벤치마킹 해서 현지화에 반영한 것이다.

그런데 그 대신 한글 IME는 중국어· 일본어 IME와는 달리 조합은 언제나 딱 한 글자 단위로만 만들 거라는 assumption도 들어가게 되었고 그게 한동안은 별 문제가 없다가 유니코드 시대에 옛한글을 구현할 때가 되자 문제가 된 것이다. 옛한글은 내부적으로 여러 개의 글자로 구성되니까.
조합이 한 글자뿐이라는 전제조건이 만족되지 않을 경우 제대로 동작하지 않는 프로그램이 있어서 호환성+방어 차원에서 운영체제가 저런 동작을 하는 것이지 싶다.

3. 한영 상태 동기화 기능의 알고리즘 개선

Windows에서 IME는 dll인 관계로 프로그램들(정확히는 스레드)별로 내부 한영 상태가 다~ 따로 노는 형태이다. 그래서 지난 7.7 버전에서 <날개셋> 한글 입력기의 인스턴스들 간에 사용 중인 입력 설정을 한데 동기화해 주는 옵션이 추가되었다. 한 프로그램에서 ‘세벌식 최종’을 선택하면 다른 프로그램에 가도 세벌식 최종이 자동으로 지정되는 식이다. 그 기능이 이번 8.8 버전에서는 동작이 더 개선되었다. 예전에 별 생각 없이, 혹은 시간이 부족해서 대충 구현했던 기능들을 엄밀하게 다듬었다.

첫째, 이미 실행된 프로그램을 전환할 때뿐만 아니라 갓 새로 실행된 프로그램에 대해서도 아까 전까지 설정되어 있는 글자판을 곧장 따라가게 했다. 이 기능은 지금까지 저게 지원되지 않아서 사실상 반쪽짜리 기능에 불과했다. 새로 실행된 프로그램은 기존 설정을 무시할 뿐만 아니라 자기 설정을 덮어쓰기까지 하기 때문에 동기화 상태를 망가뜨리곤 했다.

둘째, 제어판을 ‘확인’을 눌러서 종료해서 설정을 파일로 저장하고 공통 설정을 확인하는 인스턴스들에 대해서만 글자판이 동기화되고, ‘미저장 확인’을 눌러서 자기 혼자만 독자적인 입력 설정을 쓰는 인스턴스에 대해서는 글자판이 동기화되지 않게 했다. 공통 설정을 쓰는 곳에서 글자판을 바꾼 것이 거기로 가지 않을 뿐만 아니라, 저렇게 고립된 곳에서 글자판을 바꾼 것이 밖으로 나가지도 않는다. 이건 프로그램의 논리 구조상 진작에 당연히 취했어야 할 조치이다.

하지만 어느 곳에서든 제어판을 ‘확인’을 눌러서 종료하고 나면 지금까지 고립되어 있던 인스턴스들까지도 전부 입력 설정들이 한데 동기화된다. 이 논리를 이 기회에 완전히 정립했다.
이거 뭐 양파도 아니고, 2017년이 다 되도록 <날개셋> 한글 입력기는 까도 까도 개선할 게 계속 나와서 내가 심히 힘들다. ㅠ.ㅠ 처음부터 이렇게 엄밀하게 만들어 놓으면 좋았을 것을.

※ 제어판 분야

4. 빠른설정과 유형 파일(*.ist) 열기 기능에 Ctrl+클릭 '복사' 추가

<날개셋> 한글 입력기의 제어판에는 빠른설정이라는 게 있어서 특정 입력 항목(입력 스키마+문자 생성기)에 대해 특정 입력 설정을 곧바로 맞추거나 변형하는 기능이 있다. 다시 말해, 이건 현재 선택돼 있는 입력 항목을 변형해서 A로부터 A'를 만드는 기능이다. 뭐, A를 전혀 참조하지 않고 완전히 새로운 B로 바꾸는 것도 가능하다.

그런데, 빠른설정이 제공하는 대화상자를 Ctrl을 누른 채 '확인'을 눌러서 닫으면..
A로부터 A'를 만들되 기존 A는 그대로 두고 A'를 뒤에다 새로 추가하도록, 다시 말해 새로운 입력 항목을 생성하는 동작을 추가했다.
그러니 '기본 글자판 설정'으로부터 세벌식, 두벌식, 쿼티, 드보락 등등을 계속 추가해 넣고 싶으면 매번 번거롭게 '복사본 생성'을 누를 필요 없이 저 빠른설정을 계속 띄워서 확인 버튼을 Ctrl+클릭만 하면 된다.

ist 파일을 여는 기능도 마찬가지다. 그냥 열면 지금 선택된 입력 항목이 파일의 내용으로 바뀌지만, Ctrl+클릭을 하면 파일로부터 생성된 항목이 지금 항목의 뒤에 추가된다. '복사본 생성' 말고도 새 입력 항목을 간편하게 생성하는 방법이 더 생겼다.

자그마한 개선 사항이지만 넣고 보니 굉장히 편하다.
문자표, 낱자 결합 규칙, 사용자 정의 후보 등에 겉으로 티는 안 나지만 Ctrl+클릭 기능이 지금까지 은근히 많이 들어갔다.
버튼에다 자그맣게 * 표시라도 넣든지 해서 일반 클릭과 차이점이 있다는 시각적인 피드백이 있으면 좋겠는데 아직 그것까지는 신경 쓰지 못했다.

5. 입력 항목의 예전 설정 가져오기 기능 개선

지난 7.7버전부터는 제어판의 어떤 입력 항목에 대해서 스키마나 문자 생성기를 변경(기본 ↔ 고급 사이)한 뒤에도 이전의 입력 설정을 최대한 가져와서 유지시키는 기능이 추가되었다. 하지만 이건 지금까지 미세한 버그가 있었다.
한 입력 항목 A에서 입력 스키마를 먼저 변경한 뒤, 다른 입력 항목 B에서 문자 생성기만 변경하고서 '예전 설정 가져오기'를 시키면..
B가 문자 생성기만 예전 것으로 동기화되는 게 아니라 입력 스키마까지 엉뚱한 A의 것으로 바뀌곤 했다. 이 버그를 고쳤다.

한 입력 항목에서 스키마나 문자 생성기를 변경한 것은 일단 내부 버퍼에 저장되며 이건 다른 입력 항목에서 스키마나 문자 생성기를 또 변경하는 순간 정확하게 사라지게 했다. 이건 위에서 열거했던 아이템들보다는 상대적으로 존재감이 덜한 개선 사항이다.

※ 편집기 분야

6. <날개셋> 편집기 창의 이전 위치와 편집 문서 복원은 첫 인스턴스에 한해서만 적용

본인은 평소엔 <날개셋> 편집기에서 '프로그램의 중복 실행 허용' 옵션을 끄고 지낸다. 하지만 편집기는 구닥다리 MDI 프로그램이며, 창 하나만으로는 멀티모니터를 제대로 활용할 수 없다. Visual Studio 201x의 IDE처럼 문서 창을 도구상자의 도킹 기능처럼 프로그램 창 안팎으로 마음대로 붙이고 떼는 기능이 있으면 좋겠지만, 그런 건 내 프로그램의 관심사가 아니다. 그래서 평소에 프로그램의 중복 실행을 허용하는 걸 염두에 두고 편집기의 동작 방식을 살짝 변경했다.

내 프로그램은 기본적으로 예전의 창 위치와 크기를 기억하며, 옵션을 지정할 경우 예전에 편집하던 문서 목록도 기억하고 다음에 다시 불러들여 준다. 그런데 이 기능은 최초로 실행되는 첫 인스턴스일 때만 동작하고, 그렇지 않은 중복 인스턴스일 때는 무시하게 했다. 둘째 이후의 인스턴스에서는 언제나 임의의 위치에 빈 문서창 하나만 달랑 생긴다.

지금까지는 프로그램의 둘째/셋째 인스턴스도 첫 인스턴스와 완전히 동일한 위치에 생기고(첫 인스턴스의 창의 위치와 크기를 일부러 변경하지 않았다면) 문서도 똑같이 다시 로딩되었기 때문에 프로그램이 중복 실행되었다는 것을 알기 어려웠다. 동일 파일을 서로 다른 인스턴스에서 수정하여 수정 내역이 꼬일 위험도 있었다.

그러나 이제는 편집기가 중복 실행되더라도 창이 서로 겹치지 않으며 이미 열어 놓은 문서가 또 열리지는 않는 게 보장되기 때문에 더 부담없이 중복 실행이 가능하다. 이런 간단하고 유용한 조치를 왜 지금까지 취하지 않았었나 자괴감이 들 지경이다.

7. 기존 창의 활성화 방식 개선

사용자가 어떤 대화상자나 창을 열라는 지시를 내렸는데, 이전에 동일한 창을 열어 놓은 게 존재하고 여러 인스턴스를 생성할 필요가 없는 상황이라면 프로그램은 당연히 기존 창을 활성화시켜서 보여준다. 앞의 6번에서처럼 프로그램을 중복 실행하지 않는다거나, 아니면 날개셋 제어판 같은 modeless 대화상자를 열 때 말이다.

그런데, 그 창이 자체적으로 또 modal 대화상자를 열어 놓은 상황이라면 어떨까?
<날개셋> 한글 입력기의 경우 지금까지 이런 경우에 대한 대비가 돼 있지 않았다. (뭐, 입력기라고 썼는데 주 적용 대상은 사실상 편집기밖에 없긴 하다)
그러던 것이 이번 버전에서 드디어 개선됐다. 제어판에서 빠른설정이나 열기 대화상자를 열어 놓은 상태에서 백그라운드로 갔다가 다시 제어판으로 돌아갈 때..

혹은, 편집 화면 설정에서 색상 대화상자를 추가로 열어 놓은 상태에서 본문 편집 화면으로 갔다가 다시 편집 화면 대화상자로 돌아가라는 명령을 내렸을 때.
이제 <날개셋> 편집기는 해당 대화상자에서 제일 겉에 열어 놓은 modal 대화상자로 알아서 복귀한다. 이런 세밀한 UI까지도 싹 개선됐다.

※ 기타

8. 새로운 한글 입력 예제 데이터

비한글뿐만 아니라 한글 분야의 예제 입력 설정 데이터도 보충했다. (1) 먼저, 예전에 코노 노보루(河野 登) 님이 고안하신 "모음 연타 순아래 두벌식"이 참신함이 인정되어 예제로 들어갔다. 초성 쌍자음은 초성 다음에 중성의 2연타로 입력하는 게 매우 기발하다. 중성의 첫 타는 도깨비불 현상을 일으키니 자연스럽게 종성을 초성으로 분리하고, 그 뒤 2타가 초성을 쌍자음으로 바꾸는 것이다.

한 글쇠가 초성과 중성 경계를 오가기 때문에 이런 입력 방식은 내 프로그램에서 타순 분석 같은 게 제대로 안 될 것이다. 그리고 그 특성상 모음은 동일 글쇠 연타로 결합을 할 수 없기 때문에 ㅒㅖ 같은 것은 ㅐㅐ ㅔㅔ 연타가 아니라 반드시 ㅑㅣ/ㅕㅣ로 입력되게 해야 한다. 그래도 이건 Shift를 안 누르면서 딱히 다른 모호성도 없는 두벌식을 만드는 방법 중 하나로 충분히 고려할 만하겠다.

(2) 그 다음으로 타임스페이스 시스템이라는 회사에서 지금으로부터 10몇 년 전에 고안한 '가림토'라는 입력 방식을 예제로 넣었다. 이것은 모음뿐만 아니라 자음에 대해서도 천지인 스타일의 필획 분해를 시도한 것이다. ㄱ은 가로+세로, ㅂ은 세로+세로+가로+가로 같은 식. 모음은 알다시피 ㅡㅣㆍ 세 요소로 분해되는데 자음은 ㅡㅣ 다음으로 ㅅㅇ 이렇게 네 요소로 분해된다.

한글이 꼬부랑 획이 별로 없고 기하학적으로 굉장히 단순하다 보니 이것도 굉장히 참신하긴 하다. 그러나 빨리 치기 좋은 능률적인 입력 방식이라고 볼 수는 없으며 딱히 실용화되지는 못했다. 더구나 자음을 세벌식도 아닌 두벌식으로 만들면 경계의 모호성을 감당할 수가 없게 되며, 실제로 저 방식은 10키 환경 기준으로 ㅇ만 두벌식으로 두고 세벌식으로 만들어졌다. 뭐, 내 예제에서는 어차피 컴퓨터 키보드로 갖고 노는 거니 ㅇ도 초· 종성 구분하여 세벌식으로 집어넣긴 했다만.

얘는 자음의 입력이 처음 시작돼서 아직 가로줄 세로줄 같은 것밖에 없는 초기 상태가 있다. 이런 미완성 낱자는 가상 낱자+낱자 치환을 이용해 표시한다.
또한, 모든 겹모음과 겹받침을 입력 가능한 상태가 아니라 초성과 중성의 기본 낱자만 입력 가능하며, 나머지는 이번 버전에서 들어갈 핵심 중의 핵심 기능인 '복합 낱자 입력 로직 생성기'를 이용해서 합성해서 생성하면 된다. 이런 입력 방식을 분석하면 얼마나 복잡한 규칙이 파생돼 나오고 모호성이 얼마나 발생하는지를 직접 확인할 수 있다.

Posted by 사무엘

2017/02/09 08:37 2017/02/09 08:37
Response
No Trackback , 4 Comments
RSS :
http://moogi.new21.org/tc/rss/response/1325

<날개셋> 한글 입력기를 사용하는 프로그램들은 입력 설정을 바꾸는 UI인 '날개셋 제어판'을 꺼내는 기능이 들어있다. 그 프로그램으로는 편집기, 외부 모듈, 입력 패드, 그리고 타자연습 이렇게 4종류가 있는데, 제어판을 꺼내는 방법은 일반 메뉴, 입력 도구모음줄, 시스템 트레이 우클릭 메뉴, 대화상자의 버튼 이렇게 형태가 제각각 모두 다르다. 어째 이렇게 전부 다를 수 있는지도 궁금한 지경이다.

그런데 사실은 이 프로그램들이 내부적으로 제어판을 운용하는 방식도 전부 다르며, 미세한 차이가 존재한다. 본인은 이와 관련된 코드 리팩터링 작업을 하다가 차이점들을 글로 한데 정리해 보았다.

1. modality

중앙 집권적인 EXE 프로그램인 편집기와 입력 패드는 modeless 형태로 구동된다. 제어판 창을 띄워 놓은 채로 본문의 입력란으로 얼마든지 이동 가능하며, 제어판의 우측 하단에 '적용'이라는 버튼도 응당 존재한다.

그러나 외부 모듈과 타자연습은 modal이다. 외부 모듈의 경우 중앙 집권이 아니라 각각의 프로세스들에 붙어서 돌아가는 일종의 떨이이며, 제어판이 떠 있는 동안 자기가 담당하던 스레드가 없어지는 것을 포함해 갖가지 상황이 밖에서 벌어질 수 있다. 그렇기 때문에 상황 관리의 복잡도를 제어하기 위해서 제어판 창이 뜬 동안은 원래의 입력란으로 돌아갈 수 없게 했다.

타자연습은 외형은 중앙 집권이긴 하지만, 무슨 텍스트 에디터처럼 문자 입력이 상시 가동 중인 채로 제공되는 프로그램은 아니다. (타자 연습 화면은 메뉴에서 뭔가를 선택한 뒤에만 나타남) 그러니 제어판을 띄워 놓은 채로 타자 연습을 한다거나 메뉴로 돌아가는 상황은 생각하지 않으며, 자연스럽게 modal UI를 채택했다. 날개셋 제어판을 열었다면 이것부터 닫아야 이전 단계 화면으로 돌아갈 수 있다.

2. 입력 설정을 읽고 쓰는 방식

사실, 대화상자의 모달 여부나 다른 것보다도 이게 제일 중요하고 본질적인 차이점이다.

(1) 중앙 집권적인 편집기와 입력 패드는 형태가 제일 깔끔하고 단순하다. 그냥 공통 단일 입력 설정 하나만을 읽고 쓰는 걸로 끝이다.
공통 설정은 <날개셋> 한글 입력기 커널이 관리하며, 이걸 파일로 저장한 게 바로 imeconf.dat이다. 그러면 프로그램을 다음에 실행할 때도 예전의 입력 설정들이 고스란히 보존된다.

제어판을 '확인'으로 종료하면 메모리와 파일이 모두 업데이트된다. 그러나 '미저장 확인'이나 '적용'을 누르면 메모리만 업데이트된다. 이 두 버튼은 대화상자를 닫는지 여부의 차이만이 존재한다.

항목 미저장 확인 확인 취소 적용
설정을 메모리 default로 적용 O O X O
설정을 파일 default로 적용 X O X X
대화상자를 닫음 O O O X

(2) 위의 두 프로그램과는 달리 타자연습은 imeconf.dat를 읽거나 쓰지 않으며, 사용자 계정에 있는 자체적인 입력 설정을 사용한다. 그렇기 때문에 공통 설정이라는 개념을 사용하긴 하지만 메모리 수준에서만 사용하지 imeconf.dat를 다루는 파일 수준은 사용하지 않는다. '확인'과 '미저장 확인'의 구분이 존재하지도 않는다.

(3) 끝으로, 외부 모듈은 타자연습과는 또 정반대다. 외부 모듈은 타자연습 같은 독자적인 원천이 있는 건 아니며 필요하다면 imeconf.dat 파일을 읽고 쓰기도 한다. 하지만 그걸 메모리에 보관할 때는 공통 설정을 사용하는 게 아니라 스레드별로 자신만의 고유한 storage를 사용한다.

다시 말해 외부 모듈은 공통 설정 파일만 사용하지 메모리를 사용하지는 않는다. 이렇게 설계된 가장 큰 이유는 외부 모듈이 자신과 동일한 날개셋 커널을 사용하는 프로그램 밑에서 동작하더라도 EXE/DLL 모듈간에 입력 설정 충돌을 일으키지 않고 서로 입력 설정을 따로 관리할 수 있게 하기 위해서이다. 외부 모듈 혼자만 이렇게 남을 알아서 피해 가면 되며, 다른 프로그램들은 굳이 이렇게 동작해야 할 필요가 없다.

외부 모듈에서 연 제어판은 앞서 언급한 이유로 인해 '적용' 버튼은 사용할 수 없다. 하지만 '미저장 확인'은 있는데, 이걸 누르면 지금 맞춘 입력 설정이 외부 모듈을 사용하는 모든 프로그램들에서 한데 동기화되는 게 아니라 지금 실행 중인 프로그램/스레드에서만 잠깐 사용 가능하게 바뀐다. 한글 표현 방식 옵션도 레지스트리에 영구적으로 기록되는 게 아니라 지금 메모리에만 반영된다. 이런 것도 외부 모듈이 스레드별로 독립된 storage를 갖고 있기 때문에 구현 가능하다.

아, 하나 더.. '미저장 확인'은 제어판을 입력 도구모음줄을 통해서 열었을 때에만 나타난다. 운영체제의 제어판/설정이 제공하는 메뉴를 통해서 연 것은 문자 입력 문맥이 아니기 때문에 '미저장 확인'이 가능하지 않으며, '확인'을 눌러서 파일에 기록하는 영구적인 저장만이 제공된다.

3. 외부 모듈과 패드 공통

편집기와 타자연습은 자체 구현된 전용 에디트 컨트롤에다가만 글자를 생성한다. 하지만 외부 모듈과 입력 패드는 타 프로그램에다가 글자를 생성한다. 그렇기 때문에 이들 프로그램에서는 제어판의 시스템 계층에 '한글 표현 방식'이라는 탭이 존재하며, 빠른설정이나 낱자 결합에서 옛한글을 지정하면 "한글 표현 방식부터 맞춰야 옛한글이 실제로 나타납니다"라는 안내문이 나타난다.

또한 텍스트를 보낼 수만 있지 읽어 오고 고칠 수 없는 환경에서는 이런 동작과 관련된 기능과 옵션들이 몽땅 사용 불가 상태가 된다. 앞 글자로 달라붙는 bksp 옵션이나 단어 단위 한자 변환이 대표적인 예이다.
입력 패드는 이런 기능들이 무조건 사용 불가이고, 외부 모듈은 TSF A급 환경에 한해서 그런 기능들을 사용할 수 있다.

4. 외부 모듈 only

외부 모듈에서 제어판을 띄웠을 때는 유일하게 시스템 계층에 '외부 모듈 관리' 탭이 나타나지 않는다. 그 대신 '고급 시스템 옵션'을 갖고 있다.
또한, 구현체들 중 유일하게 외부 모듈만이 Alt가 섞인 단축글쇠를 전혀 인식할 수 없기 때문에 단축글쇠 대화상자에서 Alt를 나타내는 슬라이더가 사용 불가 상태로 바뀐다.

지금까지 논의한 사항들을 또 표로 깔끔하게 정리하면 다음과 같다. 아래의 4개 항목은 자료구조· 알고리즘의 차이가 아니라 그냥 UI 처리 차원에서의 차이일 뿐이다. 타자연습은 특이사항이 거의 존재하지 않아서 단순하고, 외부 모듈은 동작 환경이 변화무쌍하다 보니 조건부로 동작하는 게 굉장히 많음을 알 수 있다.

항목 편집기 외부 모듈 패드 타자연습
설정 data 저장소 공통 스레드별 따로 공통 계정별 따로
공통 설정(메모리) 조작 O X O O
공통 설정(imeconf.dat 파일) 조작 O O O X
'미저장 확인' 지원 O 입력 문맥일 때만 O X
modeless. '적용' 지원 O X O X
옛한글 설정 필요 안내문 X O O X
입력 기능 제약 처리(TSF A 미비) X IME/TSF B 한정 O X
Alt 단축키, 외부 모듈 관리 숨김 X O X X
2글자 이상 조합 제약 안내문 X TSF B 한정 X X

Posted by 사무엘

2016/12/30 19:35 2016/12/30 19:35
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/1311

다음 버전 개발 근황 2

이번 8.8은 이례적으로 다음 버전 개발 근황을 두 차례나 올리게 됐다. 분량을 나눠야 할만큼 작업이 활발하게 진행 중이라는 뜻이다. 번호를 9부터 시작해야 하나 싶은데.. 첫 근황을 올린 지 시간이 몇 주 정도 지났으니 다시 1로 리셋하도록 하겠다.
난 정말 날개셋 한글 입력기 코딩을 할 때가 제일 즐겁고 행복하다.

1. 사용자 정의 조합 편집 관련 기능 개선

10여 년 전 3.9 버전에서 '고급 입력기'가 첫 도입되었다. 원래 있던 '기본 입력기'의 지원 범위는 한글 한 글자의 조합인데(지금은 방점을 임시로 같이 묶어서 표현하는 것까지만 추가로 더 포함), 고급 입력기는 그 한계를 넘어서 한글이 아닌 글자의 조합도 표현하거나, 한글 하나를 여러 글자(한글 또는 비한글 모두)로 풀어서 표현하는 것을 지원한다. 전자를 위해서 '사용자 정의 조합'이 도입되었고, 후자를 위해서 '한글 출력 치환' 기능이 추가되었다. 이로써 조합 상태와 관련된 추상화 계층이 그럭저럭 완성됐다.

이번 버전에서는 그 중 '사용자 정의 조합' 쪽에 편의 기능이 추가되었다. 먼저, 제어판에서 사용자 정의 조합만 단독으로 파일로 저장하고 불러올 수 있게 했다. 바이너리 형태로 저장하는 것은 별 의미가 없다고 여겨져서 XML 형태만 지원한다.

그러니 이제 글쇠배열은 영문 쿼티로 그대로 두고, 알파벳을 기반으로 여러 방식으로 특수문자들을 입력하고 싶을 때 사용자 정의 조합 로직만 교체해서 문자 입력을 할 수 있게 됐다. 이 달 초에 소개했던 새 기능 중, 글쇠배열 이름뿐만 아니라 입력 스키마의 자체적인 이름을 부여하는 기능도 이런 맥락에서 도입된 것이다.

단, 비슷한 기능을 하는 한글 출력 치환은 여전히 단독 저장을 지원하지 않기 때문에 이건 형평성 문제가 될 수 있다. 그럼에도 불구하고 사용자 정의 조합에만 단독 저장과 불러오기 기능이 추가된 이유는.. 불러오기와 관련하여 큰 개선 사항이 또 생겼기 때문이다.

지금까지 사용자 정의 조합 로직을 설계하기 위해서는 w를 눌렀을 때 분기할 상태, 그 뒤에 a를 눌렀을 때 분기할 상태 등등을 숫자를 생각하면서 사용자가 일일이 설계해야 했다. 이런 불편을 덜기 위해 이번 버전에서는 이 프로그램이 내부적으로 사용하는 자료 구조를 그대로 노출하는 XML 스키마 말고, 사용자 친화적인 일명 '쉬운 문법' 스키마도 추가했다.

"wa = わ" 이런 쌍만 쭉 지정해 주면 w와 wa를 입력했을 때의 중간 과정과 상태 번호를 자동으로 매겨 준다는 것이다. 입력 파일 포맷을 구체적으로 어떤 형식으로 짜면 되는지는 물론 예제에다 소개해 놨다. 쉽게 말해 아래 그림에서 왼쪽처럼 만들어 놓으면 자동으로 오른쪽으로 만들어 준다는 뜻이다.

사용자 삽입 이미지

사실, 현재 예제로 제공되는 일본 문자 입력 로직은 히라가나/가타카나 테이블로부터 로직을 자동으로 짜 주는 툴을 내부적으로 돌려서 생성한 것이다. 사람의 손으로 60개가 넘는 state들을 알파벳 순으로 노가다로 생성한 건 물론 아니니까. 그 툴을 <날개셋> 한글 입력기 내부에 정식으로 포함시킨 거라고 생각하면 된다.

물론, 쉬운 문법은 내 프로그램이 인식하고 변환하는 걸 지원한다는 뜻이지, 프로그램이 내부적으로 사용하는 자료구조는 아니다. 그렇기 때문에 불러오기만 지원되지 저장은 안 된다. 쉬운 문법 원본은 사람이 따로 관리하고 갖고 있어야 한다.

또한 제어판 대화상자에서도 어떤 상태에 대해서 'called from 링크'를 찾아서 보여주는 기능을 추가했다. 30이라는 상태가 있으면 그 30이라는 상태로 분기하는 예전 상태.. 가령, 25번 상태에서 a를 누르면 30으로 간다는 걸 보여준다. 현재는 선택막대를 더블 클릭하면 앞으로 나아가는 calls to 링크만 지원되고, 뒤로 돌아갈 수는 없어서 불편했는데 이것 역시 개선됐다.

2. 단어 단위로 한자 변환

단어 단위로 한자 변환을 할 때 지금처럼 '뒤에서 앞으로 탐색'뿐만 아니라 '앞에서 뒤로 탐색'도 가능하게 옵션을 추가했다(제어판 - 편집기 계층). 예를 들어, '토선생'이라는 신조어에 대해서 한자 변환을 하면 '선생'이 아니라 '토선'이 블록이 잡힌 상태가 되며, '토선'을 변환한 뒤에 cursor는 다시 '생' 뒤로 되돌아온다.

지금까지는 조합 중인 글자나 cursor 바로 앞에 있는 글자가 반드시 단어의 마지막 글자에 포함돼 있어야 했지만 이제 그런 제약이 없어진 것이다. MS IME 내지 아래아한글이 동작하는 방식을 내 프로그램도 드디어 제대로 지원하게 됐다.

사용자 삽입 이미지

단어 단위로 한자를 변환하는 기능은 2012년에 나온 6.7 버전에서 '시범적으로' 추가되었다. 어차피 TSF A급 프로그램에서나 제공 가능한 기능이고(이건 MS IME도 마찬가지임), 그저 없는 것보다는 낫다는 차원에서 추가된 액세서리 기능일 뿐이기 때문에 동작 방식이 기존의 한 글자씩 변환하는 기능의 연장선 수준을 벗어나지 못했다. 저렇게 cursor가 통째로 앞으로 갔다가 변환 후에 되돌아오는 것은 <날개셋> 한글 입력기의 기존 프로토콜로 표현할 수가 없었다.

그러다가 그 내부적인 한계는 수 년 뒤, 작년에 나온 8.2에서 프로토콜을 확장함으로써 극복되었다. 입력 패드 구현체에다가도 한자 변환 기능을 구현하면서 작업을 싹 다시 했기 때문이다. 이때 테스트 차원에서 한자어가 굳이 cursor 바로 옆에 있지 않은 변환도 구현 가능한 것까지 확인했다.

하지만 이 코드는 말 그대로 테스트 코드일 뿐, 기존 한자 변환 코드와 융합 가능한 형태가 아니었기 때문에 조건부 컴파일로 기존 코드와 테스트 코드 둘 중 하나만 적용 가능했다. 게다가 테스트 코드는 중간에 ESC를 눌러서 한자 변환을 취소했을 때에도 cursor만 곱게 이동하는 게 아니라 변환 대상 텍스트를 불필요하게 덮어쓰는 등 한계도 있었다.

그러다가 8.8 버전에 와서야 오랜 숙제로 남아 있던 한자 후보 변환 관련 코드를 완전히 다시 작성했다. 한글 조합 상태일 때와 그렇지 않을 때를 불문하고 동일한 로직이 동작하게 했으며, 한 글자 한 글자 답답하게 앞으로 탐색하던 것을, 쿨하게 처음부터 맨 앞 글자들을 최대 30자 가까이 가져온 뒤 후처리를 하는 걸로 과정을 단순화했다. 그러면서 기존의 뒤-앞 탐색 부분에다가 옵션으로 seamless하게 병행하는 차원에서 앞-뒤 검색도 구현해 넣었다.
'초성 지향 도깨비불'(예: '간'을 '가ㄴ'으로)이나 호환용 낱자 변환으로 인해 당장 화면에 보이는 글자와 후보 변환 때 사용되는 글자가 서로 같지 않을 때의 보정 처리도 이 기회에 별도의 추상화 계층으로 싹 분리했다.

앞-뒤로 탐색했을 때 단어 단위 한글-한자 변환이 가능하지 않으면 그냥 지금 조합 중이거나 cursor 앞에 있는 한자 한 글자에 대한 한자 변환이 시도된다. 한글을 조합하던 중에 앞-뒤로 탐색하면 뒤-앞 방식으로 동작할 때와는 달리 지금 조합이 종료된다. 왜냐하면 cursor가 잠시 앞으로 이동해 버릴 수도 있으니 지금 조합 상태가 더 유지될 수 없기 때문이다. 그래도 한자로 변환될 예정인 부분이 블록으로 잠시 highlight가 되기 때문에(외부 모듈) 이 방식이 시각 피드백은 더 우수하다.

이런 뜻깊은 기능의 구현과 리팩터링 작업이 왜 이제 와서야 행해졌는지 모르겠다. 작업에 개인적으로 큰 보람을 느낀다.
그리고 이 작업을 하는 과정에서 덤으로 외부 모듈의 버그도 하나 발견해서 수정했다. TSF A급 프로그램에서 한글을 조합하지 않은 상태에서 한글 뒤에서 도구모음줄의 한자 버튼을 눌렀을 때.. 편집기와 같은 저런 한자 변환이 케바케로 되지 않는 문제가 있었다. 적어도 8.x 버전 내내 존재했으리라 여겨지는 문제이다.

3. 비주얼 관련

깨알같은 사소한 변화이긴 하다만, 지난 8.6에서 외부 모듈에서 추가되었던 '키보드 드라이버 변경' UI에다가 방패 아이콘을 추가했다. 이건 변경을 위해 관리자 권한이 필요하다는 걸 강조하기 위해서이다.
버튼에다가는 옵션 하나만 추가하면 문구 옆에다 방패 아이콘을 간단히 넣을 수 있지만, 콤보박스나 static 컨트롤에다가 방패 아이콘을 넣는 기능은 없는 것 같다. picture 컨트롤을 하나 더 집어넣어야 했다.

사용자 삽입 이미지

Windows는 IDI_ERROR, IDI_QUESTION 같은 몇 가지 기성 아이콘을 제공하기 때문에 응용 프로그램에서는 LoadIcon이나 LoadImage 함수를 통해 이것들을 가져올 수 있다. 메시지 박스에다가는 MB_ICON* 형태의 플래그를 지정해서 집어넣을 수도 있다.
그리고 Vista부터는 사용자 계정 컨트롤에 대한 시각 피드백을 제공하라는 취지로 방패 아이콘도 IDI_SHIELD라는 명칭으로 제공한다. 이들은 모두 내부적으로는 user32.dll의 리소스 형태로 존재한다.

IDI_SHIELD는 그 성격상 32*32 이상의 크기보다는 글자와 어울리는 16*16, 20*20 같은 아담한 형태로 훨씬 더 많이 쓰인다. 그런데 문제는 얘는 LoadIcon이나 LoadImage 같은 재래식 함수로는 제대로 그릴 수 없다는 것이다.

옛날부터 있었던 IDI_ERROR 같은 메시지박스 아이콘들은 최대 크기가 끽해야 48*48이 고작인 반면, 21세기에 추가된 IDI_SHIELD는 무려 256*256 크기까지 존재한다. 구조가 특이해서 그런지 LoadIcon은 물론이고 LoadImage로 크기를 지정해 줘도 작은 크기가 로딩되지 않고 제일 큰 놈으로만 그려진다. 큰 그림을 16*16, 20*20으로 강제로 줄이면 보기가 아주 흉측해진다.

그래서 방패 아이콘은 내 경험상 Vista에서부터 추가된 LoadIconMetric이라는 특수한 함수를 써야만 작은 크기로 보기 좋은 HICON을 가져와서 그릴 수 있다. 이 함수는 user32도 아니고 생뚱맞게 comctl32.dll에 있다. 세월이 흐르면서 API 설계의 일관성이 좀 깨지고 뒤죽박죽이 된 것 같다.

게다가 리소스에 있는 아이콘을 있는 그대로 read-only 공유 형태로 가져오기만 했다면 대개는 DestroyIcon을 할 필요가 없는데 저 함수의 리턴값은 언제나 소멸 처리도 해야 해서 더 불편하다. 뭐, Windows 프로그래밍에는 아이콘 나부랭이 하나 찍는 일에도 이런 복잡한 사정이 있더라.

그리고.. 진짜 사소한 거다만, 도움말에 있는 프로그램 스크린샷들을 드디어 Windows 10 기준으로 다 교체했다.

4. 옛한글 입력 설정이 되지 않았을 때의 알림 메시지

이제 더 고칠 게 없을 것 같은 입력 패드에도 improvement가 있었다.
트레이에 있는 입력 패드 아이콘을 마우스로 가리키고 있으면 현재 선택돼 있는 글자판의 이름이 툴팁으로 뜨는데, 이게 제어판의 실행으로 인해 글자판의 이름이 변경된 것은 같이 업데이트 되지 않는 걸 뒤늦게 발견하여 수정했다.

그리고 외부 모듈과 입력 패드는 옛한글을 입력하기 위해서는 제어판 시스템 계층의 '한글 표현 옵션'부터 먼저 설정해 줘야 한다는 공통점이 있다. 비트맵 자체 글꼴 전용 환경인 편집기와는 달리, 밖에서는 사용자가 옛한글을 지원하지 않는 글꼴을 사용하고 있을 수 있으며, 또 옛한글을 표현하는 방식도 역사적인 이유로 인해 여러가지가 존재하기 때문이다.

하지만 이런 사정을 모르는 사용자의 입장에서는 분명히 옛한글 입력으로 설정을 했는데 옛한글이 찍히지 않는다면 프로그램의 이상이라고 생각할 수 있다. 물론 제어판도 편집기가 아닌 타 환경에서 동작할 때는, 사용자가 빠른설정이나 낱자 결합 규칙을 옛한글과 관련된 것으로 변경할 때 "옛한글을 사용하려면 한글 표현 방식도 맞춰 주세요"라고 짤막한 메시지를 출력하긴 하지만 이것만으로는 좀 부족한 감이 있다.

입력 패드는 키보드 포커스를 건드리지 않고 시스템 트레이에다 말풍선 형태로 메시지를 찍는 아주 편리한 UI를 갖추고 있으니 이런 기능을 추가하는 게 아주 용이하다.

사용자 삽입 이미지

(layered window든 동영상이든 화면에 보이는 건 무엇이건 print screen으로 간단히 캡처하는 시대가 된 지 오래인데, 시스템 트레이의 말풍선 윈도우는 의외로 고전 테마에서는 print screen 캡처가 안 되더라..! DWM이 동작하는 AERO 테마를 띄워야 캡처가 됐음..)

참고로 지금까지 입력 패드는 입력과 관련된 기술적인 에러 메시지를 찍는 기능만 있었다. 권한 차이로 인해서 입력 패드가 메시지를 보낼 수 없는 윈도우일 때, 그리고 해당 윈도우가 IME 컨텍스트가 존재하지 않아서 문자 입력이 가능하지 않을 때 말이다.

다 외부 모듈/IME 말고 입력 패드에서만 존재하는 상황을 가리킨다. 외부 모듈은 애시당초 로그인 화면에서도 동작할 정도로 권한 걱정 따위는 할 필요가 없으며, IME 컨텍스트가 존재하지 않는 윈도우에서는 처음부터 버튼들이 다 흐리게 바뀌고 입력이 차단되기 때문에 사후에야 이런 상황을 알아채고 에러 메시지 처리를 할 일도 없기 때문이다.

사용자 삽입 이미지

다만, 옛한글 설정을 해 달라는 메시지는 입력 패드와 외부 모듈이 공통으로 출력할 명분이 있는 것들이다.
외부 모듈은 어떤 경우에도 시스템 트레이를 건드리지 않고 동작하기 때문에 다소 투박하긴 해도 그냥 메시지 박스를 이용한다.

사용자 삽입 이미지

외부 모듈은 TSF B급 프로그램에서 어쩔 수 없는 기술 한계로 인해 조합이 튕긴 것을 감지해서 메시지 박스를 찍어 주는 게 있었다(처음에 2글자 이상 길이의 조합을 만들 수 없음). 히스토리 문서를 보니 저건 그리 오래 되지도 않은 8.5 버전에서 추가된 기능이다. 이건 IME가 아닌 TSF 프로토콜을 취급하는 외부 모듈에서만 유일하게 발생하는 현상이다. 그런데 이제 이런 식으로 메시지를 찍어 주는 상황이 하나 더 추가된 것이다.

사용자 삽입 이미지

이런 식으로 예전에 만들어 뒀던 체계를 확장하여 유용한 UI가 간단하게 추가되는 건 참 뜻깊은 일이다.

Posted by 사무엘

2016/12/25 19:35 2016/12/25 19:35
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/1309

다음 버전 개발 근황

2016년 12월 현재, <날개셋> 한글 입력기 8.8이 한창 개발 중이다. 내년 2~3월쯤에 나올 예정이다.

1. 제어판에 가상 키코드 변환 기능

지금으로부터 10년도 더 된 먼 옛날, <날개셋> 한글 입력기가 3.41 버전에서 지금과 같은 트리 구조의 제어판이 도입된 이래로, '입력기 계층' 탭은 오랫동안 별다른 UI나 기능이 없는 잉여 공간이었다.
어느 글자판(입력 항목)을 사용하건 공통으로 적용되는 옵션이나 기능들은 '편집기 계층'에 있었지, 딱히 입력 항목들만을 한데 싸잡아서 무슨 공통된 명령을 내릴 만한 건 없었기 때문이다.

그러다가 5.0이 나오면서 이 탭이 잠시 쓰인 적이 있었다.
5.0부터는 입력 설정 데이터의 파일 포맷이 바뀌었다. 그래서 이제 지원되지 않는 옛(3~4 버전용) 설정 데이터가 감지되면 제어판은 그 데이터를 읽지 않고 일단 프로그램 설치 직후의 기본 입력 설정을 내놓은 뒤, 처음에 이 '입력기 계층' 탭을 가리키게 했다. 그리고는 이 탭의 빈 공간에다가 "사용자의 예전 입력 설정은 구버전 방식이기 때문에 변환을 해야 불러올 수 있습니다" 이런 메시지를 임시로 출력시켰다.

사용자 삽입 이미지

5.0의 과도기가 지난 이후로 지금까지 파일 포맷이 또 변경된 적은 없다. 그렇기 때문에 이제는 저런 메시지를 볼 일이 없을 것이다. 그러나 먼 미래에 포맷이 바뀐다면 '입력기 계층' 탭은 또 그런 용도로 쓰일 여지가 남아 있다.

입력기 계층 탭이 이런 legacy 포맷 안내문 말고 일상적인 설정 기능을 갖게 된 것은 7.7 버전부터이다. 글쇠배열(key), 입력 설정(ist), 종합 설정(set)라는 세 계층별로 설명문을 넣을 수 있는데, 종합 설정 단위의 설명문을 넣는 기능이 입력기 계층에 들어갔기 때문이다. 여기에다가는 등록되어 있는 각 입력 항목들의 용도와 의미, 글자판 전환 글쇠들의 로직 같은 총체적인 설명을 집어넣으면 된다.

물론 그래도 하이퍼링크 형태로 '설명문 지정' 한 줄 달랑 들어간 게 전부였으니.. 입력기 계층 탭은 여전히 아주 초라해 보이는 건 사실이었다.

사용자 삽입 이미지

그러다가 이번 8.8 버전부터 이 탭에 그럴싸한 명령이 하나 더 추가되었다. 입력 설정들 중에 가상 키코드가 지정된 것들의 배열을 일괄 변환하는 기능이다. 이 기능이 도입된 배경을 설명하자면 다음과 같다.

사용자 삽입 이미지

<날개셋> 한글 입력기는 지난 8.6 버전을 계기로 운영체제의 어떤 키보드 드라이버와도 잘 연계해서 동작하는 기능이 강화되었다.
기본 입력 스키마가 제공하는 글쇠배열은 그 밑에 쿼티 드라이버를 쓰건 드보락을 쓰건 콜맥을 쓰건 47개 글쇠들의 자기 위치가 불변으로 잘 고정되어 있다. 그러나 그 47키 글쇠배열 말고 다른 방식으로 글쇠를 인식하는 기능들은 가상 키코드 기반이기 때문에 키보드 드라이버의 영향을 받는다.

기본 입력 스키마가 제공하는 '추가 글쇠 인식 기능', 고급 입력 스키마가 제공하는 '고급 글쇠 인식', 그리고 편집기 계층에 있는 단축글쇠들도 다 그러하다. 그렇기 때문에 S라는 글쇠를 인식하라고 하면 쿼티에서는 왼손의 A 오른쪽에 있는 글쇠이지만, 드보락에서는 오른손 새끼손가락으로 누르는 글쇠가 된다.

이 문제를 해결하기 위해서는 굳이 글쇠의 인식 방식을 바꾸는 모험을 하기보다는 모든 입력 항목들의 설정에 대해서 저렇게 가상 키코드에 의존하는 부분을 다른 글쇠배열의 동일한 위치 기준으로 값을 변환해 주는 기능을 넣는 게 좋겠다는 결론을 내렸다. 그리고 이 기능이 들어가기 딱 좋은 위치가 바로 '입력기 계층' 탭인 것이다.

내가 지금 드보락 드라이버를 사용하고 있는데 입력 설정은 쿼티 기준이다 싶으면, '변환' 버튼을 누른 뒤 글쇠배열을 '한국어/Korean'이나 'US Qwerty' 같은 걸 선택하면 된다. 즉, from과 to 중에 from만 지정하면 된다. to는 지금 <날개셋> 제어판을 구동한 프로그램이 사용하고 있는 글쇠배열로 자동으로 결정된다.
그리고 to뿐만 아니라 from에 해당하는 글쇠배열도 운영체제에 설치돼 있어야 한다. 이 프로그램은 운영체제가 제공하는 기능을 사용해서 변환하기 때문이다.

사용자 삽입 이미지

이거 한 방이면 입력 항목들뿐만 아니라 편집기 계층의 단축글쇠까지도 변환된다. from이 쿼티, to가 드보락이라면 A,S,D,F 라는 글쇠는 드보락에서 동일 위치에 해당하는 A,O,E,U로 바뀐다. 반대로 from이 드보락, to가 쿼티라면 H,T,N이 J,K,L로 바뀐다. 이런 식이다.

설명문도 마찬가지이지만, '입력기 계층' 탭에서 건드리는 범위는 편집기 계층을 일부 포함할 수도 있다. 그러나 입력기 계층까지 명백하게 포함하는 개념이기 때문에 이것은 편집기 계층 대신 입력기 계층으로 분류된다.

옛날에는 텅 비어 있었지만 지금은 그럭저럭 공간이 채워진 탭들의 선례를 살펴보면 다음과 같다.

(1) 사실은 입력기 계층뿐만 아니라 '편집기 계층'과 '시스템 계층' 탭도 다른 탭들에 비해 널널하긴 마찬가지이다.
편집기 계층은 한자 후보 변환 관련 기능만 빼면, cursor의 이동 방식이라든가 '삽입/겹침' 같은 건 따지고 보면 1.0부터 있었던 기능이 전부이다. 이 방면으로 딱히 기능이 더 추가될 여지가 없었던 듯하다. '단축글쇠'와 '최종 변환'이라는 세부 카테고리 역시 3.0 이래로 지금까지 더 추가된 게 없다.
다음으로 시스템 계층도 글꼴 본뜨기 같은 액세서리밖에 없다가 최근에는 키보드 드라이버 보정 기능이 여기에 추가돼 들어갔다.

(2) 기본 입력 스키마의 '글쇠 인식 옵션' 탭.
오랫동안 유의미한 옵션이라고는 사실상 '빈 입력 스키마와 호환되게' 옵션밖에 없던 안습의 극치였다. 몇 가지 옵션들을 구상해서 넣은 건 있었으나 실제로 구현되지 않아서 사용불가 상태였다. 그러니 탭을 없애고 글쇠배열 탭에다 합병을 해 버려도 할 말이 없었으나... 그 옵션 자체는 엄연히 글쇠배열이 아닌 입력 스키마의 영역이었고, 미래의 기능 추가에 대비해서 탭을 유지하고 있었다.
실제로 후대 버전에서는 변수 인식과 관련된 여러 옵션들이 추가되었으며, 결정적으로 임의의 단축글쇠 리스트를 꾸미는 기능도 추가되면서 이 페이지 역시 꽉 차게 되었다. 옛날에 구상했던 기능들은 대부분 고급 스키마의 형태로 오늘날 실현되었다.

(3) 외부 모듈의 '고급 시스템 옵션' 탭.
4.82 버전에서 'TSF 지원 확장' 옵션 딱 하나가 추가된 걸로 아주 초라하게 시작했으나, 그 뒤로 각종 한영 상태 동기화 옵션과 기본 IME 지정 명령처럼 <날개셋> 외부 모듈이 IME로서 운영체제/타 프로그램과 소통하는 방식을 지정하는 고유한 옵션들이 많이 추가됐다.
최근에는 자신과 연결할 키보드 드라이버를 지정하는 옵션까지 추가되어 페이지가 빈틈이 없이 꽉 찼다. 나중에 옵션을 한두 개 더 추가하려면 'TSF 지원 확장'에 딸려 있는 안내문을 없애거나 분량을 줄여야 할 것이다.

가상 키코드 변환 기능 덕분에 인제 '입력기 계층' 탭은 별도의 독립된 도움말 페이지도 할당받았고 버튼도 두 개나 생겼다.
미래에는 이 탭이 지금보다 더 풍성해지는 날이 오기를 기대해 본다.

2. 글쇠배열의 이름과 별도로 입력 스키마에도 고유한 이름

얘기가 갑자기 딴길로 많이 샜구나. 다시 본론으로 들어오도록 하겠다.
3.0대 버전 이래로 지금까지 굉장히 어정쩡한 관계이긴 했는데.. 어떤 입력 항목에 대해서 '글쇠배열의 이름'과는 별개로 입력 항목 차원에서 고유한 이름을 사용자의 필요에 따라 지정할 수 있게 했다. 입력 항목의 이름이란, <날개셋> 한글 입력기의 여러 구현체들에서(편집기, 외부 모듈 등) '한글 세벌식', '영문 쿼티'처럼 "글자판을 선택하세요" 목록 내지 메뉴에 나타나는 이름들을 가리킨다.

지금까지 입력 항목의 이름이란, 곧 입력 스키마가 갖고 있는 글쇠배열의 이름과 동일했다. 어떤 입력 방식에서 글쇠배열이 차지하는 비중이 워낙 큰 게 사실이니 이런 접근 방식이 지금까지 큰 문제는 없었다.

그러나 글쇠배열은 여느 한글 또는 영문 배열과 다를 바 없고 오토마타나 사용자 정의 조합만 달리해서 여러 입력 방식을 만들어 낸다면 지금 같은 체계는 좀 문제가 있다. 글쇠배열을 바꾼 건 없는데 글쇠배열 탭에 가서 이 입력 방식 특성을 표현하는 이름을 입력해야 하기 때문이다.

이제 8.8버전부터는 제어판을 열어서 입력 항목을 가리키면, 지금까지 읽기 전용이던 이름 입력란에다 이름을 입력할 수 있다.
이게 공란이면 예전처럼 글쇠배열의 이름이 입력 항목의 대표 이름으로 유지된다(회색 글자). 그러나 저기에 문자열이 입력되면 그 문자열이 대표 이름이 된다.

사용자 삽입 이미지

그러므로 쿼티 영문 글자판을 기반으로 한글 로마자 입력 방식을 구현했거나 사용자 조합 기능을 추가해서 다른 문자 입력 체계를 구현했다면, 그걸 나타내는 새로운 이름을 입력 항목 차원에서 써 주면 된다. 이렇게 하면 글쇠배열의 이름을 굳이 건드리지 않고도 자기가 만든 입력 방식이 대외적으로 식별되는 명칭을 새로 지정할 수 있다.

입력 항목의 대표 이름은 설명문과 비슷한 형태로 저장된다. '빈 입력 스키마'는 원래부터 아무 옵션이 없고 아무 동작도 안 하는 스키마이기 때문에.. 설명문과 대표 이름을 모두 지정할 수 없으며, 대표 이름도 그대로 '빈 입력 스키마'로 언제나 고정된다.

저걸 구현하느라 난생 처음으로 에디트 컨트롤에다 EM_SETCUEBANNER 기능을 써 봤다. 이게 지원되지 않는 운영체제에서는 그냥 저 회색 디폴트 텍스트가 나타나지만 않고 다른 영향은 없다. 원래 cue banner는 '여기에 이름을 입력하세요' 같은 고정된 UI 가이드/힌트를 출력하라고 있는 텍스트이기 때문에 저렇게 런타임 가변적인 텍스트를 찍는 건 약간 이질적인 활용이긴 하다.

저 기능이 최초로 추가된 건 Windows XP의 공용 컨트롤 6.0부터다. 수식의 변수 도움말을 출력하기 위해 진작부터 사용해 온 풍선 도움말(balloon text)과 도입 시기가 동일하다. 그런데 참 희한하게도 이 기능은 한중일 동아시아 언어권 에디션 또는 MUI 팩이 설치된 XP에서는 버그로 인해 동작하지 않았다고 한다. 우리 같은 사람은 Vista와 그 이후에서나 cue banner를 구경할 수 있게 됐다.
반대로, Windows XP에 도스용 QBasic이 영미권에서는 삭제됐지만 동아시아 에디션에서는 있었다고 하니 이것도 신기한 노릇이다.

3. 문자표

문자표 대화상자에도 약간의 변화가 생겼다.
맨 위에 '종류'라는 콤보박스가 추가되어, 단순히 글꼴이 존재하는 모든 문자들을 코드값 순으로 나열하기만 하는 게 아니라 다른 임의의 문자표를 제공할 여지를 마련했다. 사실, 이 용도로는 MS Word나 아래아한글의 문자표 대화상자처럼 탭 컨트롤을 쓰는 것도 좋으나 그것보다 더 구현하기 쉽고 만만한(..) 콤보박스를 사용했다.

이것이 예전 무려 3.0 시절부터 있던 'KS X 1001 문자표' 체크박스를 대체했다.
사실, 완전히 다른 문자표를 출력하는 기능이 무슨 옵션인 것처럼 체크 형태로 있던 건 굉장히 이상한 UI 디자인이긴 했다.
마치 성별을 입력받는 UI가 남/녀 라디오나 콤보박스로 있는 게 아니라, "[X] 여자" 체크박스로 달랑 주어지는 것처럼 말이다. 내부적으로 표현되는 정보량이 1비트라고 해서 체크박스가 모든 상황에서 적합한 건 아니다.

체크박스가 콤보박스로 바뀌었는데 문자표가 여전히 두 종류밖에 없으면 좀 심심하니 "모든 한글 자모"라는 문자표를 하나 더 넣었다. 이것은 유니코드에 존재하는 모든 한글 낱자들을 초중종별 사전 순으로 표시해 준다. 여러 영역에 뿔뿔이 흩어져 있는 한글 자모들을 한데 열람하고 옛한글을 문자표로 입력할 때 큰 도움이 될 것이다.

사용자 삽입 이미지

이제 사용자가 별도의 리스트로 작성한 custom 문자표를 뒤에 줄줄이 추가하는 기능도 생각할 수 있으나, 일단 미래의 과업으로 미루기로 한다.

4. 방점 지원

<날개셋> 편집기가 드디어 한글의 뒤에 붙은 방점(U+302E, U+302F)을 한글의 왼쪽에다 제대로 표시해 준다. 또한 cursor의 이동· 삭제 단위를 판별할 때 방점은 앞의 한글과 같이 한 묶음으로 처리된다. 안 그래도 <날개셋> 편집기는 세로쓰기도 지원하니, 방점이 이렇게 세로로 찍혀 나오면 문서가 더욱 볼 만할 것이다.

사용자 삽입 이미지

다만, 방점은 자신만의 고유한 폭을 차지하는 게 아니라 한글 16*16 공간 안에 같이 삽입된다. 그렇기 때문에 한글 글꼴 자체가 큼직하다면 방점이 제대로 보이지 않을 수 있다. 방점과 잘 어울리는 약간 홀쭉한 옛한글 글꼴이 좀 있어야 할 것 같다. 그나마 '한메가는본문'이 이런 범주에 드는 글꼴 같지만 얘는 옛한글을 지원하지는 않는다.

한글 한 글자를 구성하는 덩어리에 초중종성에 이어 방점까지 옵션으로 붙을 수 있다니 이건 무슨 픽셀에서 RGB에 이어 알파채널까지 붙는 것과 비슷해 보인다. 그렇다고 이거 지원을 위해 <날개셋> 한글 입력기의 내부에서 한글 하나를 나타내는데 제4의 성분을 통째로 다 집어넣은 건 아니다. 그런 무모한 짓을 한 건 아니고 그냥 한글 입력 오토마타의 내부 구조만 살짝 확장했다.

내가 처음에 한글을 입력할 때야 그 조합 내부에다가 방점을 같이 넣을 수 있지는 않다. 방점은 입력되는 순간 한글 조합을 종료시켜 버린다. 단지, 이미 방점이 곁들어진 한글에다 달라붙을 때 그 방점을 임시로 유지한 채로 자모를 고치거나 추가로 입력할 수만 있게 했다.
그리고 이 상태에서 bksp를 누르면 언제나 방점부터 먼저 지워지고 그 뒤에 한글 자모가 지워진다. cursor가 이동하는 단위하고 bksp로 글자를 지우는 단위, 그리고 앞에서 뒷글자를 지울 때와 뒤에서 앞글자를 지울 때 동작에 차이가 발생할 수도 있어서 꽤 어려울 수도 있는 작업이었는데 결국 문제를 이런 식으로 깔끔하게 해결했다.

5. 텍스트 필터 추가

"한글 형태 정규화" 필터에는 NFC와 NFD 정규화 둘만 있었는데, 거기에다가 "NFD부터 적용 후 NFC"라는 제3의 동작 옵션을 추가했다.
이렇게 하면 '가ㅿ'처럼 종성이 없는 현대 한글 자모 + 채움 문자 없는 종성 한글 낱자가 한데 이어져서 정규화가 잘못되어 있던 한글이 현대 한글 또는 옛한글로 한데 합쳐진다.

예전 방식으로 이런 문자열을 NFC 정규화 하면 '가'는 그대로 있고 ㅿ는 채움 문자가 추가되어 두 글자가 서로 완전히 분리되곤 했다. 새로 추가된 옵션은 그보다 더 융통성 있게 동작할 것이다.

사용자 삽입 이미지

사실, 텍스트 필터들은 옛날에 6.x 버전 때 잔뜩 추가되고 나서 그 뒤로 변화가 거의 없었다. 그런데 이번엔 "문자 코드값 산술 치환"이라는 새로운 필터가 추가됐다.
그냥 모든 글자들에 대해 코드값을 나타내는 변수 A에 대한 수식을 실행해서 그 수식값으로 문자를 바꿔 준다. 0을 지정하면 그 문자를 지운다. surrogate는 자동으로 처리되기 때문에 A>=0x10000이라고 생각하면 된다.

쉽게 말해 이 기능은 <날개셋> 편집기에 이미 들어있는 '문자 영역 찾기' 기능의 '바꾸기' 버전이라 할 수 있다. 앞뒤 글자를 가리키는 P와 N 변수를 사용할 수 있으며, 여기서 글자를 변경했다고 하더라도 뒷글자의 수식에서 P변수에는 바뀌기 전 앞글자의 코드값이 들어간다.
A - (A>='a' && A<='z' ? 32:0) 이런 수식을 주면 알파벳 대문자를 소문자로 바꿀 수 있으며 전/반각 변환도 그냥 수식으로 처리할 수 있다. 그리고 정규화된 한글 낱자에서 특수 처리를 위해 외형상 잘 보이지 않는 채움 문자만 제거하고 싶을 때도 이 필터를 사용하면 된다.

6. Windows 10 + 구글 크롬에서 발생하는 외부 모듈의 이상한 문제

본인은 근래에 한 사용자로부터 아주 괴이한 현상에 대한 신고를 받았다.
Windows 10 (일단은 64비트) + 구글 크롬의 주소창에서 한글을 입력한다. 그리고 조합이 있는 상태에서 그대로(예: '가' 입력 중) 마우스로 그 주소 입력란을 클릭한다. 그러면 외관상 당연히 조합이 종료돼야 한다.
그런데 그 상태에서 한글을 입력하면 아까 조합 중이던 한글이 덧나서 '가강' 내지 '가가ㄴ'처럼 된다.

<날개셋> 한글 입력기가 개발 짬밥이 몇 년인데 저런 미개하고 원시적인 버그가 있다는 건 말이 안 되는데? 게다가 다양하게 실험을 해 보니 이 버그는 다음 조건 중 하나만 만족해도 발생하지 않는다. 혹시나 해서 말인데, 모든 테스트는 64비트 기준임.

  • 일단 날개셋 말고 MS IME는 어디서든 별 이상 없음.
  • 크롬에서 '가능한 경우 하드웨어 가속 사용' 옵션을 끄면 날개셋 역시 저런 문제 없이 조합 종료 처리가 옳게 됨. 아놔 웹 페이지 렌더링에서 가속을 받는 것하고 IME 프로그램의 동작이 도대체 무슨 상관이냐? -_-;;
  • Windows 10 중에서도 1주년 업데이트를 갓 받은 버전 1607, 빌드 14393.xx대에서만 확실하게 발생하며, 그 이전(버전 1511, 빌드 10586) 내지 이후(버전 1607, 빌드 14971) 버전에서는 발생하지 않는 듯함.

크롬에서 발생하는 문제이긴 하지만 날개셋 + 운영체제 + 크롬이 삼박자로 모두 정밀한 조건을 기가 막히게 만족할 때만 발생하기 때문에 이건 도대체 어떻게 처리해야 할지 모르겠다. Windows 10은 시도 때도 없이 업데이트가 너무 자주 되고 있기 때문에, 만약 후대 빌드에서 문제가 발생하지 않는다면 이건 그냥 '알려진 문제'에다 언급만 하고 넘길 가능성이 높다.

7. 예제 데이터와 도움말

예제 입력 데이터도 몇 개 더 추가하고 Samples 아래에 디렉터리를 더 세부적으로 구분했다. key와 ist 중 한글 입력과 관계 있는 것은 Hangul로, 한글 입력이 아닌 것을 Non-Hangul로 나눴다.
그리고 아직은 예제가 각각 하나씩밖에 없지만 후보 데이터는 Candidate로, 한글 표현 영역 데이터는 Range로 이동해서 배치했다. 확장자가 다 같은 txt이어서 분간이 안 되기도 하니 말이다.
이제 Samples 디렉터리 자체에는 제어판 내장값 예제 데이터인 scheme.xml만 있다. 여기에는 용도가 고정된 파일들만 있을 것이다.

Non-Hangul들은 평범하게 글쇠배열이나 오토마타 수식이 아니라 '날개셋 고급 입력기' 문자 생성기가 제공하는 기능들을 활용해서(사용자 정의 조합과 후보, 출력 치환) 외국 문자나 각종 알파벳 변형 문자들을 입력한다. 알파벳+성조 번호로 성조가 붙은 알파벳을 입력하는 한어병음, X를 덧붙여서 악센트 부호 알파벳을 찍는 에스페란토, 심지어 베트남어 VIQR 입력 방식까지 있다. 내가 만든 건 아님.

그리고 도움말엔 부록의 "한글 낱자 코드 참조표 - 자음" 부분과, 기본 자료 구조의 "한글이 표현되는 방식"에 설명을 보강했다. KS X 1026에서 종성 ㅇ 겹받침이 옛이응 겹받침으로 전격 변경된 것과 관련된 내용을 추가했으며, 현행 한글 코드에 대한 비판에 대한 해명도 넣었다. 한글 11172자와 수백 자의 옛한글 낱자가 유니코드에 일일이 배당된 것이 뭔가 잘못된 것처럼 생각하는 분들이 있는데 본인은 그렇게 생각하지 않는다고 말이다.

이렇듯, 개발 2개월째를 맞는 차기 버전 8.8은 핵심 기능을 제외하고도 겉의 UI와 데이터에 유의미한 변화들이 잔뜩 추가되었다. 다음으로 타자연습 얘기를 하겠다.

8. 타자연습

(1) <날개셋> 타자연습은 현재 최신 버전(입력기 8.6 + 타자연습 3.51)에 중대한 버그가 있다는 걸 이 자리에서 먼저 밝힌다. ‘글쇠 익힘’에서 ‘글자 단위 연습’을 사실상 할 수가 없다. 상자에 있는 글자를 그대로 따라 쳐서 완성하는 순간 프로그램이 뻗어 버리기 때문이다.

이건 타자연습은 잘못이 없고 입력기가 한창 새 기능들이 추가되던 와중에 어이없는 실수가 들어갔기 때문이다. 처음부터 있었던 버그는 아니고 8.5~8.6쯤에서 들어간 것으로 추정된다. 세벌식 커뮤니티에서는 오래 전부터 나돌던 이슈였던 것 같은데 본인은 지금까지 이걸 알지 못했다.

(2) 오랫동안 존재했을 것으로 추정되는 굉장히 어처구니없는 버그를 사용자의 제보 덕분에 발견하여 수정했다. <날개셋> 타자연습에는 사용자 계정 이름을 변경하는 기능이 있는데 그게 사실상 거의 쓸 수 없는 무용지물이었다. 계정을 갓 생성한 직후에는 개명이 가능하지만, 나중에 그걸로 본격적으로 로그인을 한 뒤에는 개명 기능이 동작하지 않았기 때문이다. 이 문제 역시 확인된 즉시 해결했다.

(3) 지난 3.5버전부터 연습글을 관리하는 체계가 리스트 xml이 아닌 디렉터리 기반으로 간소화되었는데.. 이 때문에 지금까지 제공되던 성경 본문 tc 파일을 곧장 사용하는 게 불가능해졌다.
다음 버전에서는 사용자가 지정한 연습글 디렉터리에다 tc 파일이 있으면 그 tc 파일에 있는 모든 연습글들을 별도의 꾸러미에다 자동으로 몽땅 등록해 주는 기능이 들어갈 것이다. 골치 아프게 ProgramData\YmSoft\NgsType 이런 디렉터리 찾을 필요 없이, 자기가 쓰는 연습글 디렉터리에다가 파일을 넣기만 하면 문제가 해결된다.

(4) 문장 연습 중에 현재 사용 중인 글자판의 이름을 표시하는 기능이 추가되었다. 연습 중에는 어차피 화면 좌측 하단의 ‘환경설정’ 버튼에 접근할 수가 없어지니 이 버튼을 아예 숨겨 버리고 여기에다가 <날개셋> 편집기의 상태 표시줄처럼 글자판의 이름이 표시되게 했다.

<날개셋> 타자연습은 세벌식 최종 전용 타자연습(= 한글 전용)을 표방하고 있어서 전통적으로 이런 쪽을 신경쓰지는 않고 있었는데, 이것도 표시하는 기능이 없는 것보다는 있는 게 좋아 보인다. 게임의 경우 글자판이 바뀌면 바뀐 글자판 이름이 화면 좌측 하단에 잠시 떴다가 사라진다.
사실은 앞서 언급했던 입력 스키마 이름과 글쇠배열 이름을 분리하는 기능 역시, 타자연습의 이 작업을 하던 중에 아이디어가 떠올라서 추진한 것이다.

이 정도면 타자연습의 다음 버전도 단순히 3.52 수준이 아니라 3.6 정도로 너끈히 갈 수 있을 듯하다.

Posted by 사무엘

2016/12/08 08:30 2016/12/08 08:30
Response
No Trackback , 6 Comments
RSS :
http://moogi.new21.org/tc/rss/response/1303

날개셋 한글 입력기 8.6

이번에는 으레 관례적으로 하던 중간 보고(다음 버전 개발 근황) 없이 곧장 새 버전 소식을 전하게 되었다. <날개셋> 한글 입력기 8.6이 나왔다.
이번에도 예외없이 왜 2016년이 다 돼서 인제야 도입됐나 싶은 새로운 기능들이 많이 도입되었다. <날개셋> 한글 입력기는 8.5 때보다 더욱 완전함을 향해 나아가게 되었다.
앞으로 최대 두세 번 정도 더 버전업 해서 9.0 정도는 갈 수 있을 듯하다. 무슨 작업을 더 할지 로드맵은 이미 다 잡혀 있다.

※ IME와 연결되는 키보드 드라이버를 변경하는 기능

<날개셋> 한글 입력기에서는 글쇠배열 편집을 통해 드보락이나 콜맥 같은 다른 외국어 글자판을 같이 쓸 수 있다.
그러나 외부 모듈의 경우, 이것은 IME 방식으로 글쇠를 인식하지 않는 환경에서는 무용지물이다. 단축키나 암호 입력을 그런 영문 글자판으로 할 수는 없으며, 잘 알다시피 IME가 동작하지 않는 모드로서 '쿼티 자판' 내지 '빈 입력 스키마'가 언제나 반드시 추가돼야 했다. 이것 때문에 불편하다고 지금까지 사용자로부터 문의도 많이 들어왔었다.

물론 외부 모듈은 IME로서 자기 영역만 책임지면 되지 굳이 키보드 드라이버의 영역까지 개입할 필요는 없다. 하지만 이번 8.6 버전에서는 한글 IME와 연결되는 키보드 드라이버를 간단하게 바꿀 수 있는 UI가 추가됐다. native 빈 입력 스키마 상태에서 드보락 내지 콜맥을 한글 글자판과 병용하는 사용자에게 굉장한 유용한 기능이 될 것으로 보인다.

사용자 삽입 이미지

이제 외부 모듈에서 제어판을 연 뒤 "시스템 계층 - 고급 시스템 옵션"을 가 보면, "한글 IME와 연결할 영문 키보드 드라이버"라는 콤보 상자가 나타나 있다.
디폴트는 한국어 키보드 드라이버인 kbdkor로, 맨 앞에 있다. 자주 사용하는 걸로 판단되는 드보락과 콜맥은 곧장 2~3순위이며, 나머지 외국어 드라이버들은 이름의 알파벳 순으로 등재돼 있다. 운영체제에 존재하는 모든 키보드 드라이버 DLL들을 자동으로 탐색한 것이다.

이걸 변경한 뒤 제어판을 '확인'으로 닫으면.. 외부 모듈이 직접 레지스트리를 고치는 게 아니라 운영체제의 레지스트리 편집기를 통해서 간접적으로 고친다. HKEY_LOCAL_MACHINE 레지스트리 값을 변경하기 위해서는 관리자 권한이 필요한데, 외부 모듈은 자기가 독립적인 프로그램이 아니라 DLL이기 때문이다. (권한이 없을 수도 있음)

확인 질문에 '예'로 대답한 뒤 운영체제 로그인만 다시 하면 바뀐 글자판이 적용된다. 단, 당장 로그인 암호를 입력하는 기준 영문 글자판부터 바뀌기 때문에 절대 주의해야 한다. 잠시 암호를 없애거나 숫자 기반으로 변경할 것을 권함.

한국어 이외의 다른 외국어 키보드 드라이버에서는 (1) 한국어 키보드에 존재하는 고유한 한영/한자 글쇠를 인식하지 못하므로 단축글쇠 차원에서 Shift+Space 같은 다른 방법을 써야 한다.

(2) 또한, Windows XP 이전의 운영체제에서는 <날개셋> 한글 입력기의 기반 드라이버만이 바뀌지만 Vista 이후부터는 모든 한글 IME들의 기반 드라이버가 이걸로 바뀌어 버린다. 내 프로그램은 문제가 없지만 MS 한글 IME의 경우 한글 글쇠배열까지 영문 글쇠배열을 기준으로 뒤죽박죽 바뀌어 버리기 때문에 타 한글 IME를 사실상 제대로 쓸 수 없게 된다는 점을 주의하기 바란다.

※ 키보드 드라이버의 글쇠를 UI에서도 유동적으로 인식

위의 작업은 그 자체만으로는 그냥 일부 매니아 유저가 손으로 레지스트리를 일일이 고쳐야 했던 것을 더 편하게 해 주는 UI 껍데기를 추가한 것에 불과하고..
더 중요한 건 이제부터다. 이 김에 키보드 드라이버와 관련된 추가적인 연구를 진행했다.
<날개셋> 변환기가 콜맥 키보드 드라이버 드라이버를 불러오려 하면 리가처(일명 dead key) 테이블 쪽에서 버퍼 overflow가 나서 죽던데 이 문제를 해결했다. 해당 드라이버가 리가처들을 이례적으로 잔뜩 갖고 있어 보이긴 했지만, 내 프로그램도 어떤 경우든 당장은 죽지 않아야 하므로.

그리고 획기적인 건.. 제어판 포함하여 내 프로그램에서 글쇠배열를 보여주는 부분에서 기준 글쇠배열이 단순 쿼티 고정이 아니라 지금 사용 중인 드라이버의 배열을 보여주게 했다.
다음 그림을 보면 확실하게 감이 올 것이다. 사용자가 배당한 검은 글자 말고 위의 흰 글자들.. <날개셋> 한글 입력기 1.0 이래로 지금까지 이건 무조건 쿼티 고정이었다. 그러나 현재 키보드 드라이버가 드보락과 연결돼 있으면 이제는 드보락 배열로 표시된다. 세벌식 최종 기준으로 초성 ㅇ은 쿼티의 J 자리에 있지만 드보락에서는 H 자리이다.

사용자 삽입 이미지

키보드 드라이버라는 게 그 본질은 스캔코드와 가상 키코드 사이의 대응 규칙에다가 각종 dead key 조합을 담고 있는 '테이블'이다. 실행 가능한 기계어 코드나 매크로· 스크립트가 들어있어서 보안 문제를 걱정해야 하고, 신뢰성 보장을 위해 디지털 서명이라도 받아야 하는 그런 물건은 아니다. 그래서 Windows 9x 시절에는 키보드 드라이버는 실제로 *.kbd라는 형태의 그냥 데이터 파일이었다.

그러나 NT 계열에서는 키보드 드라이버는 그냥 static한 구조체 포인터를 되돌리는 함수를 구현한 DLL 형태이다. 무슨 다국어 UI DLL처럼 리소스/데이터만 들어있는 DLL도 아니고 엄연히 함수 실행 부분이 일단은 있다. 같은 테이블을 되돌리더라도 각 아키텍처에서 메모리로 직통으로 올릴 수 있게 구조체 멤버 같은 건 적절히 align/padding이 처리돼 있어야 한다.

그리고 바로 이런 이유에서.. 같은 32비트 x86용 드라이버라 하더라도.. 순수 32비트 OS용과, x86-64 OS에서 64비트하고 같이 운용되는 32비트 드라이버는 서로 호환이 되지 않는다. 본인은 이걸 이제야 알게 됐다. 후자는 비록 포인터가 4바이트이더라도 구조체의 포인터들은 32비트가 아닌 64비트 단위로 듬성듬성 padding돼 있어야 하더라. 어쩐지 그래서 콜맥 드라이버도 받아 보면 i386, amd64뿐만 아니라 wow64가 따로 있었구나. 통상적인 DLL을 만들 때는 그걸 구분할 필요는 없었는데 굉장히 흥미로웠다.

※ 단항 연산자

다음 버전에서 추가하네 마네 하면서 떡밥만 날렸던 ++ -- 단항 연산자를 그냥 이 기회에 추가해 버렸다. 덕분에 손 놓은 지 꽤 오래 됐던 복잡한 수식 해석 코드들을 다시 실컷 복습했다. 하지만 작업은 생각만치 복잡하거나 어렵지 않았다.
++얘는 문자열로 표현할 때 +가 두 개 있는 것과 형태를 구분하기 위해, 우선순위 조정이 아닌 다른 사유로 괄호가 필요한 첫 사례가 되었다.
물론 공백만 삽입해 줘도 되긴 하지만, 괄호로 확실하게 구분하는 게 더 보기 좋아서 괄호를 사용하기로 했다.

2008년부터 현재까지 쓰이고 있는 5.0 방식 입력 설정 포맷은 구조 확장으로 인해 더 쓰이지 않는 데이터 청크라든가, 호환성 유지를 위해 누더기 땜질식으로 확장된 청크가 늘어나고 있다. 특히 5.0 이후로 backspace 동작 관련 옵션들은 판이하게 확장되었으며 저장 방식도 바뀌어 왔다. 거기에다 연산자의 추가는 레거시 파일 포맷의 무질서도(?)를 더욱 키웠다.

하지만 파일 포맷을 또 변경하는 건 유니코드에 한글 자모가 더 추가되는 정도의 이변이 발생하지 않는 한, 아직까지는 최대한 억제하고 있다. 이건 우리나라 경제로 치면 화폐 개혁을 하는 것과 같은 급의 파격적인 변화이기 때문이다.
<날개셋> 변환기가 이제 오랜만에 대공사를 해야 할 것이다. 지금처럼 3~4.x를 5.x 포맷으로 바꾸는 게 아니라 5~8.x 포맷을 새 포맷으로 바꾸는 일을 해야 할 것이다.

※ UI

사소한 UI 쪽으로 가면, 모든 대화상자들의 외형을 총체적으로 재검토해서 버튼들의 크기와 간격을 최대한 일관성 있게 재조정했다.
마소에서는 Windows 표준 GUI 가이드라인 차원에서 명령 버튼들의 크기(특히 '확인'과 '취소')를 50*14로 할 것을 권하고 있다. (단위는 픽셀이 아니라 dlu라고 대화상자 내부에서만 쓰이는 추상적인 단위임) 내 프로그램은 그건 준수하지 않고 45*16을 쓰고 있으며, 이번에 크기를 다 그걸로 통일시켰다.

달랑 '확인', '취소' 두 글자.. 영어로 표현해도 OK와 Cancel에 불과한 그 단어를 집어넣기에는 50*14는 너무 납작하기 때문이다. 가로만 너무 길고 세로는 짧다. '맑은 고딕'은 그나마 글꼴 metric의 종횡비가 좀 개선됐지만, 과거 굴림의 경우 그 정도가 더 심하다.
요건 내 프로그램이 의도적으로 Windows 표준 GUI와는 약간 다른 정책을 취하는 부분임을 밝힌다. 사실, 국내에 애초에 그런 것까지 일일이 다 신경쓰고 만들어지는 Windows용 프로그램 자체도 별로 없지만.

그리고 오랫동안 암묵적으로 남아 있는 버그라면 버그인데..
잔상이 생기는 문제를 두 군데 해결했다.
하나는 날개셋 제어판 창을 가로로 쭉 키웠을 때, 날개셋 에디트 컨트롤에만 non-client의 테두리 부분에 남는 성가신 잔상이다. (아래 그림에서 오른쪽을 보라)

사용자 삽입 이미지

난 그리라는 이벤트가 왔을 때 그린 잘못밖에 없는데 왜 이런 현상이 생기는지는 개인적으로 잘 모르겠다.
그리고 또 하나는 일단은 고전 테마에서만 존재하는 문제 같은데, 대화상자 우측 하단에 있는 크기 조절 손잡이가 인근의 버튼 영역을 덮어써서 생기는 잔상이다.

사용자 삽입 이미지

근본 원인을 해결했다기보다는 그냥 경험적으로 문제를 피해 간 것에 가깝긴 하지만, 그래도 예전보다는 UI 경험이 더 개선됐을 것이다. 이 두 잔상은 기술적으로 문제를 피해 간 방식도 서로 완전히 달랐다.

※ high-DPI 지원, 기타

그리고 모든 구현체 프로그램들에 내부적으로 high-DPI aware 플래그를 추가했다. 이건 마소가 제시하는 표준을 준수했다는 점에서 장점이 될 수 있지만 일부 사용자에게는 단점 및 악재가 될 수도 있다.
125% 같은 high-DPI에서 대화상자들이 뿌옇게 확대+보정된 저해상도로 나오는 게 아니라 깔끔한 고해상도로 나올 테니 그건 장점이다. 하지만 편집기의 경우 어떤 DPI에서도 본문 글꼴이 무조건 16*16 픽셀로 찍히기 때문에 고해상도 + 대형 모니터에서는 이제 글자가 너무 작아서 알아보기 어려울 수도 있다.

이건 자체 비트맵 글꼴을 사용하는 내 프로그램의 근본적이고 고질적인 문제이므로 당장 쉽게 해결 가능하지는 않다. 요 특정 윈도우만 확대+보정해서 출력하는 기능이라도 써야 하지 않나 싶다. 호환성의 왕중왕인 Windows API 중에 뭔가 있을 것 같으나.. 높은 우선순위로 살펴보겠다고는 장담을 못 하겠다. 앞서 얘기했듯이 <날개셋> 한글 입력기는 문자 입력 관련 기능만 연구하기도 갈 길이 너무 먼 상태여서 말이다.

저것들 말고도..

  • 외부 모듈에서 문자표 대화상자가 가끔 제대로 동작하지 않던 것을 개선했다.
  • 기본 입력 스키마의 추가 인식 글쇠를 수정하면 처음에 날개셋문자 값이 무식한 10진수로 찍혀 나오는 엄청난 버그를 왜 인제 발견했는지.. 당장 고쳤다.
    사용자 삽입 이미지
  • 제어판의 글쇠배열 편집 페이지에서 '상태변수' 수식은 문법이 틀려도 종료 시에 에러가 찍히지 않게 했다. (어차피 설정 파일에 저장되지도 않고.. 창을 닫는 마당에 에러 체크 따윈 전혀 필요하지 않음)
  • 언제부터 이런 어처구니없는 버그가 들어갔는지 모르겠는데.. 편집기가 0바이트인 파일을 아예 열지 못하고 에러 처리하던 버그를 모 사용자로부터 제보 받아서 즉시 개선했다.
  • 현재 편집기는 파일을 저장할 때는 원래 있는 파일의 날짜와 크기를 체크해서 내 프로그램이 아닌 외부에서 변경되었으면 그걸 사용자에게 확인시킨다. 그런데 그 다음으로, 열었던 파일을 아무 변경 없이 그냥 닫더라도 파일이 외부에서 변경되었으면(날짜 크기 변경, 삭제) 재저장할지 사용자에게 확인시키게 했다. 단, 애초부터 읽기 전용으로 열지 않았고 하드디스크에 있는 파일에 한해서이다. (네트웍, 이동식 드라이브에서 연 파일은 제외)
  • Google 단모음 키보드를 예제 입력 방식으로 추가했다. 기존 두벌식에서 겹자음과 ㅑㅕㅛㅠ만을 제거한 간소화 버전인데 나름 모바일에서의 가성비가 좋다. '하꾜'는 연속 입력이 되지만 '학교'는 중간 딜레이가 필요하다. 천지인처럼 모든 종성에서 타이머를 줘야 하는 게 아니라 ㅂㅈㄷㄱㅅ 요 자음에 대해서만 주면 되는데, 그 값을 글쇠배열 수식에서 소문자 변수를 통해 지정하게 했다.

이렇게 사소하게 고치고 더한 아이템들이 더 있다.
두벌식에서 글쇠 수를 지금보다 더 늘리지 않고 shift도 쓰지 않고 쌍자음 음절 경계 구분 문제를 해결하는 방법은.. 어쩔 수 없이 (1) 타이머를 쓰거나, 아니면 (2) 초성은 다음에 이어지는 모음의 특성을 추가로 이용해서 쌍자음을 구현하는 것 정도가 전부인 듯하다.

※ 타자연습

끝으로 타자연습의 경우, 입력기 프로그램들과 마찬가지로 high-DPI 플래그를 넣었으며 이 외에도,

  • 도움말의 '세벌식 만물상 → 운영체제에서 두세벌식 전환을 어떻게 하죠?'에.. Windows 8~10 기준으로 글자판을 전환하는 방법이 지금까지 너무 오랫동안 빠져 있는 것을 확인하여 설명을 추가했다. 확실히 운영체제의 버전이 올라갈수록 전환하는 방법이 더 복잡해져 왔다.
  • 좀 심각한 문제이던데, 타자연습을 종료한 뒤에도 잔여 프로세스가 완전히 사라지지 않고 남아 있던 문제를 해결했다. 구형 운영체제에서는 이런 일이 없는 것 같던데 10에서는 문제가 있었다. Windows에서 프로세스는 단순히 실행을 끝내고 리턴만 하는 게 아니라 ExitProcess를 호출해 줘야 어디서나 확실하게 종료되는 듯하다.
  • 문장/글 연습에서 사용자가 추가한 디렉터리에 있는 연습글들은 우클릭했을 때 해당 연습글을 (1) 바로 편집하거나 (2) 파일이 있는 곳을 탐색기로 열어서 바로 찍어 주는 명령을 메뉴에 추가했다.

지난 3.5부터는 사용자 연습글을 추가하는 방식이 XML 기반에서 디렉터리-파일 기반으로 확 바뀌었기 때문에 이제 사용자가 연습글 리스트 XML을 직접 고칠 일은 거의 없을 것이다. 그렇기 때문에 인제 와서 큰 의미는 없겠지만, 이번 버전에서는 연습글 경로에서 내부 압축 꾸러미 이름을 식별하는 구분자를 @에서 *로 전격 변경했다.
별표는 파일 시스템 차원에서 절대로 들어갈 수 없는 문자이기 때문에 이제 *.tc 파일 자체가 경로 중간에 @가 섞여 있더라도 이제는 아무 문제 없이 취급 가능하다.

※ 맺는 말

<날개셋> 한글 입력기에 대해 대외적으로 들어오는 의견은 크게 다음과 같은 것들이 있다.

  1. 일반 사용자: 타 플랫폼 포팅도 좀 해 달라.
  2. 일반 사용자: 요런 요런 상황에서 외부 모듈이 제대로 동작하지 않는다. 심하면 뻑나기까지 한다.
  3. 좀 컴덕후 기질이 있는 분들: 오픈소스화해 달라.

그런데 잘 알다시피 이것들은 모두 나로서는 전혀 현실성이 없으며, 예측 가능한 미래에 가능하지 않은 것들이다.

1. 리눅스, 맥 OS, 심지어 안드로이드까지 하나씩 골고루 다 요청을 받았었다. 특히 안드로이드는 그냥 화면 터치만 지원하는 게 아니라 외부 키보드를 연결할 수도 있다. 그렇기 때문에 PC 키보드 지향 입력 시스템인 내 프로그램도 이제 충분히 진입할 여지가 있다.
하지만 알다시피 <날개셋> 한글 입력기는 여러 플랫폼을 지원하는 프로그램이 아니라 반대로 단일 플랫폼에서 여러 구현체(편집기, 외부 모듈, 입력 패드)를 제공할 정도로 Windows에만 특화돼 있다. 한 플랫폼에 올인하면서 입력 기능 연구만 하기에도 본인은 시간이 부족하다. 포팅은 나 혼자서 할 수 있는 일이 아니다.

2. 이런 신고는 십중팔구가 내 자리에서 재연이 안 되는 것들이다. 내 프로그램도 외부 모듈의 짬밥이 이미 10년 가까이 돼 가는데, 기본적인 안정성은 이미 충분히 확보했다. 한글 입력이 전혀 안 되거나 아예 crash가 발생할 정도의 치명적인 문제는 내 프로그램 단독이 아니라 같이 돌아가는 백신이나 보안 프로그램과의 충돌 때문에 발생한다. 그리고 본인은 백신 같은 거 전혀 안 쓰는 사람이다.
내 프로그램이 디지털 서명이 된 채로 배포된다면 이런 문제가 더 줄어들 수 있겠지만 이 역시 아마추어 개인 개발자 차원에서 가능한 일은 아니다. 디지털 서명을 발급받으려면 돈이 드는 건 둘째치고라도 신원 보증을 위해 사업자 등록증 같은 것도 있어야 한다. =_=;;

3. 전에도 한번 입장을 밝힌 바 있지만, 무슨 전세계 오픈소스 진영의 해커 덕후들이 다 한글과 세벌식 자판을 쓰기라도 하지 않는 이상, 오픈소스화한다고 해서 누가 내 프로그램을 타 OS로 짠 포팅해 준다는 보장도 없다. 또한 내 노력에 대한 보상이 돌아오는 것도 아니다. 명예 보상쯤이야 지금 같은 클로우즈드 소스 체계에서도 이미 충분히 받고 있다.
내 프로그램은 심하게 갈라파고스화된 1인 독재 체제에서 폐쇄적으로 개발되고 있긴 하지만, 현실적으로는 이게 최선의 조치이다.

Posted by 사무엘

2016/10/08 08:33 2016/10/08 08:33
Response
No Trackback , 12 Comments
RSS :
http://moogi.new21.org/tc/rss/response/1281

« Previous : 1 : 2 : 3 : 4 : 5 : 6 : 7 : 8 : 9 : ... 14 : Next »

블로그 이미지

그런즉 이제 애호박, 단호박, 늙은호박 이 셋은 항상 있으나, 그 중에 제일은 늙은호박이니라.

- 사무엘

Archives

Authors

  1. 사무엘

Calendar

«   2024/04   »
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30        

Site Stats

Total hits:
2663834
Today:
1009
Yesterday:
1553