libhangul / ibus-hangul

The hangul engine for IBus
GNU General Public License v2.0
64 stars 18 forks source link

preedit text대신 surrounding text 사용 #69

Open choehwanjin opened 6 years ago

choehwanjin commented 6 years ago

리눅스의 한글 입력기 관련한 문제 중 가장 곤란한 것이 있다면 preedit text 관리일 것입니다. Focus out이나 Reset 에서 늦지 않게 preedit text를 commit해야 하는데 문제가 좀 있습니다.

ibus의 경우 reset 상황에서 뒤늦게 commit signal이 도착하므로 reset 이후 commit되어 잘못된 위치에 입력될 수 있습니다. 또 클라이언트 구현에 버그가 있어서 reset이 제때 안불리는 경우가 있을 수 있습니다.

이런 여러가지 문제점을 고려할때에 한국어 입력기 구현의 패러다임을 좀 바꾸는 것이 어떨까 생각중입니다. 한국어 입력기는 preedit text를 하드하게 사용하여 구현되어 있는데요. 이것이 좀 불안합니다.

그래서 preedit text대신 surrounding text를 사용하게 되면 모든 텍스트가 이미 입력 완료된 상태가 되므로 텍스트를 잃어 버리거나 텍스트가 옮겨지는 문제가 없어질 것으로 예상합니다.

대신 사용자는 조합중인 글자 상태를 알 수 방법이 없어지게 됩니다. 또 surrounding text를 지원하지 않는 클라이언트들(예전 XIM 클라이언트들)은 문제가 그대입니다.

요즘 드는 생각은 이 단점보다 reset, focus 관련 문제가 더 심각하므로 surrounding text를 사용하여 입력을 처리하는 것을 고려해볼 필요가 있는 것 같습니다.

관심있는 분들의 의견 바랍니다.

sebuls commented 6 years ago

surrounding text 개념 질문이요... "한글" 이라고 입력하는 과정에서 ㅎ 하 한 한ㄱ 한그 한글 이런식으로 나타나지 않고, ㅎㅏㄴ 까지 입력하면 "한"이 나타나고, ㄱㅡㄹ 입력하면 "글" 이 나타나는 건가요?

madang01 commented 6 years ago

저는 "surrounding text" 에 대해서 반대 입장입니다.

GUI 는 사용자가 화면을 보면서 반응하는 인터페이스입니다.

하여 한글 입력시 한글은 초성 중성 종성 조합하는 문자로 그 과정이 보이지 않는다면

GUI 가 아니게 됩니다.

반대 이유가 해법 제시가 아니여서 속상하고 대안등등을 원하시는데 이미 문제점으로 인식한 내용으로 반대를 하니 죄송하기도 하네요.

choehwanjin commented 6 years ago

surrounding text는 이미 입력된 텍스트를 입력기가 수정하기 위한 방식입니다. 이미 입력된 텍스트를 수정하면서 보여주겠다는 뜻입니다.

사용자에게 조합 과정은 나타나지만, 역상으로 나타나지 않고 완성된 글자처럼 보이게 됩니다. 지금은 rk까지만 입력했다고 하면 '가'가 역상으로 나타나 조합중인 영역이 어디까지 인지 알수 있지만 surrounding text를 사용하면 역상이 아닌 글자 '가'로 보이게 됩니다.

madang01 commented 6 years ago

"강" 자를 2벌식에서 친다고 하면 rkd 를 연속해서 누르게 됩니다.

그러면 "surrounding text" 에서는 "d" 가 남겨진 rk 까지 누른 상태에서 "가" 자가 보이는건가요?

보이지 않는다는건가요?

이게 보인다면 GUI 는 사용자가 화면을 보면서 반응하는 인터페이스에 부합되므로

"surrounding text" 를 반대할 하등의 이유는 없습니다.

"surrounding text" 를 설명하실때 "조합중인 글자 상태를 알 수 없다" 라고 말씀을 하셨습니다.

저는 이를 rkd 에서 rk 까지 글자를 친 상태에서는 "가" 자가 보이지 않는다로 이해를 했습니다.

하여 조합중인 글자 상태를 알 수 없으니

GUI 는 사용자가 화면을 보면서 반응하는 인터페이스에 부합하지 않는다라고 반대를 한것입니다.

그런데 제가 잘못 이해를 한건가요?

sebuls commented 6 years ago

https://developer.gnome.org/gtk3/stable/GtkIMContext.html 에 surrounding 및 preedit 얘기가 있습니다. 영어라서 좀 어렵네요... surrounding 및 preedit에 관해 궁금하신 분은 참고하세요.

changwoo commented 6 years ago

반전이나 밑줄 표시가 없고 무조건 커서 앞에 있는 글자가 조합되는 건데 사용자 느낌이 달라지므로 좋지 않다고 생각합니다.

그리고 문제를 깔끔히 해결할 방법도 되지 않는다고 생각합니다. 현재 ibus와 툴킷의 문제에서는 surround text로 가더라도 다른 문제가 일어날 수 있지 않을까요? 예를 들어 | 표시가 커서라고 하고 surround text로 입력한다고 하면,

ghost commented 6 years ago

조합 중인 글자가 보이지 않는다고 하더라도 나머지 버그가 없는 입력기가 있다면 개인적으로는 써보고 싶습니다. 아직까지 nabi 쓰는 1인.

dontdieych commented 5 years ago

hexchat irc 클라이언트 입력 창이 이런 식으로 동작 하던데요. 윈도우즈에서 처럼요. 지금 처럼 역상으로 표시되는 것 보다 훨씬 편안했습니다.

번쩍 거리는게 너무 싫어요 ㅜㅜ.

hedone21 commented 5 years ago

surrounding text를 사용하는 것에 대해 동의합니다. 현재 고질적인 끝글자 문제를 해결할 좋은 방안 같습니다.

sebuls commented 5 years ago

질문. surrounding text 쓰면 끝글자 문제 해결되나요? 저는 아니라고 생각하는데요...

hedone21 commented 5 years ago

질문. surrounding text 쓰면 끝글자 문제 해결되나요? 저는 아니라고 생각하는데요...

끝글자 버그는 preedit(버퍼) 상태에 있는 글자가 윈도우 포커싱 변환 등이 발생하였을 떄, 기존 윈도우에 flush(기록) 되지 않아 발생하는 현상입니다. surrounding text는 기록 후 수정 방식이라 문제가 해결될것이라 기대됩니다.

왜 문제가 해결되지 않을 것이라 생각하시나요?

ghost commented 5 years ago

지금도 수많은 불편을 감수하고, 배포판마다 앱마다 문제없는 입력기 조합을 찾아내쓰고, 입문자들은 맨날 한글입력 질문이 올라오고 있는 상황이라서.... 이러나 저러나 어차피 매한가지 뭔가 불편을 감수해야한면... 메인 주류는 못되어도 이런 타입의 입력기가 나온다면 은근히 많이 쓰일것 같아요. 개인적으로 두벌식 세벌식 전환이 편하고, 립한글 업글만 하면 신세벌식 자판이 바로 인식이 되고, 트레이아이콘도 입력기 중 가장 이뻐서 저는 지금도 나비를 쓰고 있는데요. 다만 나비에서 두벌 세벌 전환처럼, 현재 타입과 서라운드텍스트방식을 손쉽게 오고 갈 수 있는 세팅이 가능하다면 진짜 유용할 것 같습니다. 최고~~~

sebuls commented 5 years ago

질문. surrounding text 쓰면 끝글자 문제 해결되나요? 저는 아니라고 생각하는데요...

끝글자 버그는 preedit(버퍼) 상태에 있는 글자가 윈도우 포커싱 변환 등이 발생하였을 떄, 기존 윈도우에 flush(기록) 되지 않아 발생하는 현상입니다. surrounding text는 기록 후 수정 방식이라 문제가 해결될것이라 기대됩니다.

왜 문제가 해결되지 않을 것이라 생각하시나요?

일명 끝글자버그로 불리는 현상은 입력기뿐 아니라 응용프로그램과 관련되어 있어서, 응용프로그램에서 제대로 처리하지 않으면 입력기 차원에서 해결할 수 없는 문제로 알고 있습니다.

hedone21 commented 5 years ago

질문. surrounding text 쓰면 끝글자 문제 해결되나요? 저는 아니라고 생각하는데요...

끝글자 버그는 preedit(버퍼) 상태에 있는 글자가 윈도우 포커싱 변환 등이 발생하였을 떄, 기존 윈도우에 flush(기록) 되지 않아 발생하는 현상입니다. surrounding text는 기록 후 수정 방식이라 문제가 해결될것이라 기대됩니다. 왜 문제가 해결되지 않을 것이라 생각하시나요?

일명 끝글자버그로 불리는 현상은 입력기뿐 아니라 응용프로그램과 관련되어 있어서, 응용프로그램에서 제대로 처리하지 않으면 입력기 차원에서 해결할 수 없는 문제로 알고 있습니다.

현재 끝글자 버그는 마우스의 focus_out이 실행될 때, preedit text가 올바르게 flush / reset 되지 않기 때문에 발생하는 문제 입니다. (이는 preedit은 중일과 같은 완성형 글자를 위해 디자인 된 것인데, 한글과 같은 조합형 글자에는 맞지 않는 디자인이기 때문에 해결하기 어렵습니다.) 해당 문제를 예전 호동님처럼 ibus의 sync 방식을 바꿔서 해결할 수 있지만, 이는 ibus의 핵심 동작을 바꾸는 문제로 다른 입력기들에 영향을 줄 수 있어서, ibus 쪽에서 반영을 안한 것으로 알고 있습니다. 실제로 구현된 결과를 보아야 알겠지만, surrounding text는 먼저 입력(flush 포함)을 한 이후, 입력한 글자를 수정하는 방식으로 동작할 것으로 예상됩니다. 즉, 이미 입력을 마쳤기 때문에, 마우스의 focus를 포함하여 현재 작성중인 im context의 영향을 받지 않을 것입니다.

일명 끝글자버그로 불리는 현상은 입력기뿐 아니라 응용프로그램과 관련되어 있어서, 응용프로그램에서 제대로 처리하지 않으면 입력기 차원에서 해결할 수 없는 문제로 알고 있습니다.

혹시 구체적으로 응용프로그램에 어떤 점과 관련되어 있는지 알려주실수 있나요?

ghost commented 5 years ago

저는 surrounding text 에 반대하는 입장입니다. 제가 파악한 끝글자 버그는 몇 가지 종류가 있습니다.

  1. ibus, fcitx 등 비동기 통신 방식으로 인한 입력기 자체 버그
  2. 응용 어플리케이션 자체 버그 2-1 마우스를 클릭할 때 입력 메소드를 리셋하지 않는 경우; scintilla 응용 어플(geany), eclipse, libreoffice(XIM) 2-2 포커스 아웃 신호를 발생하지 않아서 리셋되지 않는 경우; libreoffice(XIM) 2-3 응용 어플에서 preedit 를 그리지 않아서(또는 그리는 부분에 버그가 있어서) 끝글자 버그가 발생하는 경우, wine, krita, inkscape

surrounding text 은 1번, 2-3번을 해결할 수 있지만 또 다른 버그를 생산합니다. 수정(편집) 중인 글자를 알 수 없다는 것. 그게 일종의 버그입니다.

그리고 응용 어플이나 툴킷(gtk, qt) 또는 XIM 이 surrounding text 를 버그 없이 처리할지는 해봐야 알 수 있습니다.(XIM 스펙에 surrounding text 가 있는지 없는지 모르겠습니다.)

1번의 이유 때문에 surrounding text 를 사용하기 보다는 ibus 에 있는 버그를 해결하는 것이 맞습니다. ibus 의 비동기 통신 방식을 동기식으로 바꾸기 어렵다는 거 압니다. ibus 개발자가 바꾸려는 의지가 있다면 10년 동안 방치하지는 않았겠죠. 그래서 surrounding text 를 사용하자는 논의는 이해하는데, 그것보다 ibus 의 구조를 약간 변경하는 것이 어떨까 합니다. 한국어만 라이브러리 방식으로 처리하도록 말이죠. 한자 사전 쿼리 부분을 한번만 초기화하도록 하면(한자 사전만 싱글톤 방식으로) 한국어 im context 가 1000개가 생성된다할지라도 메모리 소비가 크지 않을 겁니다. (eclipse 를 사용하면 eclipse 자체 버그로 인하여 im context 가 1000개 정도 생성될 수도 있습니다.)

ibus 비동기 통신 방식을 동기 통신 방식으로 바꿀 수 없거나 바꿀 의지가 없다면 한국어만이라도 비통신 방식인 라이브러리 방식을 사용하자는 의견입니다. 우리가 일반적으로 사용하는 라이브러리 함수 호출이 동기 방식입니다. thread 또는 polling 등의 방식으로 의도적으로 비동기화하지 않는 이상 말이죠.

비통신 라이브러리 동기 방식으로 변경한다고 해도 문제가 또 남아 있습니다. gtk, qt 는 마우스 클릭을 입력기가 알 수 있습니다. 그러나 XIM 의 경우 마우스 클릭을 입력기가 알 수 있는 방법이 없는 것 같습니다. 그래서 X 어플의 경우 어플이 reset 을 호출하지 않으면 끝글자 버그가 그대로 노출됩니다. XIM 의 경우 키이벤트를 어플측에 되돌려 줄 수 있습니다. XIM 스펙에 surrounding text 가 있는지 없는지 모르겠고, 입력기 자체에서 surrounding text 또는 이와 비슷한 것을 구현하여 이미 완성된 형태로 X 어플에 넘겨주고 ... 그렇게 해도 마우스 클릭했을 때 입력기에서 편집을 완료해야하는데 그걸 알 수 없어서 마우스로 클릭한 지점에서 조합 버그가 발생하겠군요.

결국에는 원칙대로 해야 버그가 해결된다는 것입니다. 원칙대로 하지 않아서 발생한 버그 때문에 workaround 코드를 추가하면 그것 때문에 부작용이 발생하고 그 부작용을 없애기 위해 workaround 코드를 또 추가하는 등의 방식은 바람직하지 않습니다.

ghost commented 5 years ago

입력기 (프레임워크)를 통신 방식으로 설계하는 이유는 다음과 같습니다.

현재 실행 중인 어플이 10개 있다고 가정합니다. 어플 1개당 3개의 im context (ic) 를 생성하여 사용한다고 가정합니다. 한,중,일의 3종 입력법을 사용한다고 가정합니다. ic 당 10KB 사용한다고 가정하고, 한자 사전 1MB, 중국어 사전 20MB, 일본어 사전 20MB 사용한다고 가정합니다. 편의상 candidate window 는 상정하지 않습니다. im context 는 입력 방법 문맥입니다. C언어로 struct 이라 간주하시면 되고 객체 지향 언어로는 class 라고 간주하시면 됩니다.

  1. 메모리 사용량 감소 어플 10개에서 사용하는 ic 는 10(어플 개수) 3(어플에서 사용하는 ic 개수) 3(언어 엔진 개수) = 90개. 입력기가 통신 방식이면서 싱글톤 방식이면 1개 셋트의 ic 로 대응할 수 있습니다. 입력기측 ic 1셋트 메모리 소비량은 10KB * 3개언어 + 1MB(한) + 20MB(중) + 20MB(일) 대략 41.03MB 입니다.

  2. 입력기 또는 언어 엔진에서 SEGFAULT 에러가 발생해도 응용 어플이 죽지 않음.

이 이유 때문에 통신 방식으로 구성하는 것입니다.

만약 라이브러리 방식을 설계한다고 가정하면,

  1. 모두 싱글톤 방식일 때, 메모리 소비량은 어플 10개 * 입력기측 ic 1셋트 대략 410.3MB 소비됩니다.

  2. 사전만 싱글톤 방식, ic 는 멀티플 인스턴스 방식일 때 메모리 소비량은 어플 10개 3 (어플 1개당 ic 개수) 10KB 3 (언어 개수) + (1MB + 20MB + 20MB) 10 대략 410.9MB

  3. 멀티플 인스턴스 방식일 때 (일반적인 방식) 메모리 소비량은 어플 10개 3 (어플 1개당 ic 개수) 입력기측 ic 1세트 대략 1230.9MB 소비됩니다.

테스크탑 환경에서는 사용자가 어플을 실행하지 않아도 환경에 따라 자동 실행되는 어플들이 있습니다. 그게 5개에서 10개 정도입니다. 그래서 사용자가 이것 저것 실행한 경우, 떠 있는 어플이 20개 정도는 될 겁니다. 위의 라이브러리 소비량에서 * 2 하면 메모리 소비량이 엄청나게 증가하게 됩니다. 다국어 입력기를 라이브러리 방식으로 설계하면 입력기에서 기본적으로 소비하는 메모리가 2, 3GB는 됩니다.

하지만, 중국어, 일본어는 그대로 둔 채, 한국어만 라이브러리 방식으로 설계하면 얘기는 달라집니다. 대략 사전 1M 라 가정하고(아마 1MB 보다 더 클 것 같습니다.), ic 를 10KB 라 가정하면, 사전만 싱글톤 방식으로 하고 ic 는 멀티플 방식(일반적인 방식)으로 했을 때, 어플이 20개에 각각 3의 ic 를 생성한다고 하면, 20 1MB + 20 3 * 10KB 대략, 20.6MB 메모리를 소비하게 됩니다. 어플이 200개 실행된다면 대략, 206MB 메모리를 소비하게 됩니다.

현대의 컴퓨터로 libhangul 및 한자 사전의 메모리 소비량을 충분히 감당할 수 있는 정도이고 libhangul 때문에 응용 어플이 죽는 일이 없을 정도로 libhangul 라이브러리는 매우 안정적이기 때문에 ibus 측에 한글 엔진만이라도 라이브러리 방식으로 구성하자고 일단 의견을 제안해보는 것이 좋을 것 같습니다.

ghost commented 5 years ago

그리고 ibus 의 경우 끝글자가 다른 창에 찍히는 경우가 있습니다. 이 경우는 ibus 의 비동기 방식 때문에 발생하는 것 같지는 않습니다. focus-in, focus-out 신호는 동기적이지 않고 focus-in, focus-out 이 비동기일 수 있습니다. focus-in 또는 focus-out 신호가 발생하면 입력기에서 reset 을 수행하게 되는데 입력기에서 클라이언트의 icid 를 명시하지 않으면 엉뚱한 곳에 글자가 찍힐 수 있습니다. 코드를 봐야 정확히 알 수 있겠으나 ibus 의 동작으로 봐서는 아마 icid 를 명시하지 않을 것 같습니다. 그래서 surrounding text 방식을 사용한다고 하더라도 우리가 의도한대로 동작하지 않을 수 있습니다.

changwoo commented 5 years ago

그리고 ibus 의 경우 끝글자가 다른 창에 찍히는 경우가 있습니다. 이 경우는 ibus 의 비동기 방식 때문에 발생하는 것 같지는 않습니다. focus-in, focus-out 신호는 동기적이지 않고 focus-in, focus-out 이 비동기일 수 있습니다. focus-in 또는 focus-out 신호가 발생하면 입력기에서 reset 을 수행하게 되는데 입력기에서 클라이언트의 icid 를 명시하지 않으면 엉뚱한 곳에 글자가 찍힐 수 있습니다. 코드를 봐야 정확히 알 수 있겠으나 ibus 의 동작으로 봐서는 아마 icid 를 명시하지 않을 것 같습니다. 그래서 surrounding text 방식을 사용한다고 하더라도 우리가 의도한대로 동작하지 않을 수 있습니다.

이 경우는 surrounding text로 해결이 됩니다. reset이 될 때 입력기에서 커밋을 할 필요가 없고 그대로 놔두면 되거든요. iOS의 입력 API도 preedit가 없고 앞글자 읽어온 다음에 지우고 새로운 글자 넣는 식인데, 어쨌든 좀 부자연스러울 수는 있는데 구현을 못 하지는 않아요.

choehwanjin commented 5 years ago

이 기능을 사용해 볼수 있도록 구현을 추가했습니다. (1a4acc3) 기본 값은 아니고 dconf-editor로 옵션을 설정해야 합니다. /org/freedesktop/ibus/engine/hangul/preedit-modenone으로 설정하면 사용 가능해집니다.

위 옵션을 켠다면 "use-event-forwarding" 옵션을 false로 설정해도 입력이 잘 되어야 합니다. 많은 클라이언트를 테스트해보지는 못했지만, 아마도 qt/gtk의 기본 입력 모듈을 사용하는 곳에서는 별 문제 없이 동작할 것 같습니다.

IBusEngine::set_capabilities 를 체크하여 surrounding text 기능을 지원하지 않는 경우에는 위 옵션을 none으로 설정해도 기존 방식으로 동작하게 됩니다.

그래도 reset method를 제대로 호출하지 않으면 문제가 발생하는 것은 똑같습니다. 입력 중에 마우스로 캐럿을 움직이면 글자 자체가 따라가지는 않습니다만, 입력 상태가 종료되지 않으므로 엉뚱한 곳에서 조합이 일어나게 될 수 있습니다. 이를 피하기 위해서 입력전에 캐럿 앞 글자를 비교해보는 코드를 넣었는데, 대강 문제를 회피할 수 있긴 합니다. 그러나 이전 위치와 동일한 글자가 있다면 그 글자가 편집되기 시작하는 문제가 있습니다. 위에서 류창우님이 이미 지적하신 문제입니다.

changwoo commented 4 years ago

그래도 reset method를 제대로 호출하지 않으면 문제가 발생하는 것은 똑같습니다. 입력 중에 마우스로 캐럿을 움직이면 글자 자체가 따라가지는 않습니다만, 입력 상태가 종료되지 않으므로 엉뚱한 곳에서 조합이 일어나게 될 수 있습니다. 이를 피하기 위해서 입력전에 캐럿 앞 글자를 비교해보는 코드를 넣었는데, 대강 문제를 회피할 수 있긴 합니다. 그러나 이전 위치와 동일한 글자가 있다면 그 글자가 편집되기 시작하는 문제가 있습니다. 위에서 류창우님이 이미 지적하신 문제입니다.

아래와 같이 master 브랜치 (GTK4) 쪽에는 click하면 reset하도록 적용이 되어서 이 문제는 릴리스되는대로 시간 문제일 것 같네요.

https://gitlab.gnome.org/GNOME/gtk/-/commit/b859407620ed45d6d762e0cbfb9ee389d4dbed01

bsjeon commented 2 years ago

commit 1a4acc36 로그 메세지 보고 찾아왔습니다. 메시지에 링크가 여기에 걸려 있으므로, 새로 이슈로 등록하지 않겠습니다.

commit 1a4acc36 를 보면 word-commit 옵션이 PREEDIT_MODE_WORD 로 대체되었음을 알 수 있습니다. 그런데 기능을 다른 옵션으로 바꾸고서 org.freedesktop.ibus.engine.hangul.gschema.xml 및 ibus-setup-hangul 에 word-comit 항목은 수정하지 않았기 때문에 word-commit 옵션 설정만으로는 기능이 동작하지 않는 문제가 있습니다.

이 커밋 이후로 몇번 릴리즈가 있었는데, 새로 이슈로 언급되지 않은 걸 보면, 대부분 word-commit 옵션이 필요하지 않거나, 필요한 분들은 알아서들 PREEDIT_MODE_WORD 를 설정해서 쓰고 있는 걸로 판단됩니다. 서라운트 텍스트 사용 여부와는 관계없이, 이제 word-commit 관련해서 정리가 필요하다고 생각합니다.