한글 입력 문제: setCompositionEnabled, isCompositionEnabled, XIMPreeditEnable, XIMPreeditDisable

cogniti3의 이미지

안녕하세요.
jetbrains 제품에서 jbr(JetBrainsRuntime) 을 사용할 때 한글 입력에 문제가 좀 있다는 얘기가 있어서 확인 중에 있습니다. 관여되는 코드를 찾아보았습니다.

JetBrainsRuntime

https://github.com/JetBrains/JetBrainsRuntime/blob/master/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c

OpenJDK

https://github.com/openjdk/jdk/blob/master/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c

Java_sun_awt_X11InputMethodBase_isCompositionEnabledNative()
Java_sun_awt_X11InputMethodBase_setCompositionEnabledNative()

JetBrainsRuntime, OpenJDK 코드를 확인해보니 별 차이가 없습니다.
위 함수가 자바에 setCompositionEnabled(), isCompositionEnabled() 함수(메소드, 이하 함수라 칭하겠습니다)에 대응되는 c 코드인 거 같습니다.

setCompositionEnabled(), isCompositionEnabled() 함수에 대한 설명은 아래에 나와 있습니다.

https://docs.oracle.com/javase/8/docs/api/java/awt/im/InputContext.html#setCompositionEnabled-boolean-

https://docs.oracle.com/javase/8/docs/api/java/awt/im/InputContext.html#isCompositionEnabled--

그런데 제가 이해하기로는 setCompositionEnabled() 함수는 입력기가 (키) 이벤트를 언어 문자(한국어, 중국어, 일본어, 베트남어 등)로 변환하게 하느냐, 아니면 변환하지 않게 하느냐 이렇게 이해하고 있습니다. 간단히 말하자면, 입력기로 (키) 이벤트를 보내면, 입력기가 그걸 처리를 하도록 하느냐, 처리하지 않도록 하느냐로 이해하고 있습니다.
그런데 JDK 에서 Java_sun_awt_X11InputMethodBase_isCompositionEnabledNative(), Java_sun_awt_X11InputMethodBase_setCompositionEnabledNative() 함수 구현에
XIMPreeditEnable, XIMPreeditDisable 을 사용했던데,
https://www.x.org/releases/current/doc/libX11/libX11/libX11.html 문서를 보면

If a value of XIMPreeditEnable is set, then input preediting is turned on by the input method.
 
If a value of XIMPreeditDisable is set, then input preediting is turned off by the input method. 

이렇게 되어 있단 말이죠. 입력기가 조합문자열(preedit text)를 그리느냐 그리지 않느냐를 의미하는 것 같습니다. XIMPreeditDisable 이면 입력기가 작은 창을 만들어서 조합문자열(preedit text)을 그려줘야 한다고 이해하고 있습니다.
https://developer.gnome.org/gtk3/stable/GtkIMContext.html#gtk-im-context-set-use-preedit 이런 것이라 이해하고 있습니다.

X 응용 어플이 XSetICValues() 를 호출하면, nimf 에서는
https://gitlab.com/nimf-i18n/nimf/-/blob/master/modules/services/xim/nimf-xim.c#L60
nimf_xim_set_ic_values() 함수가 작동합니다.

        case XIMPreeditEnable:
          nimf_service_ic_set_use_preedit (ic, TRUE);
          break;
        case XIMPreeditDisable:
          nimf_service_ic_set_use_preedit (ic, FALSE);
          break;

jetbrains idea 는 XIMPreeditDisable 을 입력기로 보냅니다.
그래서 nimf 는 nimf_service_ic_set_use_preedit (ic, FALSE); 를 호출하여 nimf 가 작은 창을 만들어서 조합중인 한글(preedit text)을 그려줍니다.
참고로 ibus, fcitx 소스코드에서는 XIMPreeditEnable, XIMPreeditDisablegrep 명령으로 검출되지 않았습니다.

그래서 저는 이 문제가 수십년 된 케케묵은 자바 jdk 구현상의 버그가 아닌가.... 그런 생각이 듭니다.

cogniti3의 이미지

제가 아래 설명을 잘못 이해하고 있을 지도 모릅니다.

If a value of XIMPreeditEnable is set, then input preediting is turned on by the input method. If a value of XIMPreeditDisable is set, then input preediting is turned off by the input method.

제 생각에는 아래 함수는 간단히 말해서 입력기를 disable/enable 하는 함수로 이해하고 있습니다.

Java_sun_awt_X11InputMethodBase_isCompositionEnabledNative()
Java_sun_awt_X11InputMethodBase_setCompositionEnabledNative()

이들 함수에 구현상의 버그가 있다고 생각합니다. 그래서 관련 내용을 openjdk 측에 전달하여 토의가 시작되어야 할 것 같고, 위 함수를 openjdk 측에서 제대로 구현한다고 해도, jetbrains 제품에 있는 한글 버그는 해결되지 않습니다.

jetbrains 제품에 있는 한글 버그 해결책은,

1. jetbrains 제품은 preedit 를 그릴 수 있는 기능이 이미 갖추어져 있으므로 jetbrains 제품에서 setCompositionEnabled(false) 이렇게 호출하지 말아야 합니다. setCompositionEnabled() 함수를 호출하지 않으면 기본값이 true 로 되어 있으므로 setCompositionEnabled(true) 라고 호출할 필요도 없죠.

2. nimf-xim 을 수정하여 Ignore XIMPreeditDisable (기본값: OFF) 옵션을 만들어 놓고, jetbrains 한글 버그를 회피하기 위해서는 Ignore XIMPreeditDisable 옵션을 ON 하도록 안내하는 방법이 있습니다.

참고로 ibus, fcitx 는 XIMPreeditEnable, XIMPreeditDisable 을 처리하는 코드가 없어서 jetbrains 제품에서 setCompositionEnabled(false) 이렇게 호출하여도 그 코드가 작동하지 않습니다. ibus, fcitx 에 버그가 있는데 그 버그로 인하여 jetbrains 제품의 버그가 드러나지 않았던 것이죠.