디시인사이드 갤러리

갤러리 이슈박스, 최근방문 갤러리

갤러리 본문 영역

디자인 = 설계, 오늘 제미니 제안 사항

나르시갤로그로 이동합니다. 2025.09.27 17:14:09
조회 67 추천 0 댓글 0

기존에 나는 Cim 이라는 것을 디자인(설계)했다...

beep를 추가하고 싶었지.

그런데 API가 개떡같아지는게 싫었어

제미니한테 질문을 하니..

제미니가 이것 저것 고려하더니 최적의 API를 설계함.

ㅋㅋㅋ


두둥~~~


그 코드는 IME 서버측 코드이다. nimf_service_ic_call_beep (target);을 통하여 클라이언트 측으로 전달된다. 그런데 그 방법이 깔끔하지 않아 보인다.

왜냐하면, CimCallbacks 구조체의 멤버로 compose_cancelled를 추가하는 것이 부적절해 보이기 때문이다.


typedef struct _CimCallbacks CimCallbacks;

struct _CimCallbacks {

  void (*preedit_start)     (CimIcHandle ic, void* user_data);

  void (*preedit_end)       (CimIcHandle ic, void* user_data);

  void (*preedit_changed)   (CimIcHandle ic,

                             const CimPreedit* preedit,

                             void* user_data);

  void (*commit)            (CimIcHandle ic,

                             const char* text,

                             void* user_data);

  /* Do not free CimSurround and its text */

  const CimSurround* (*get_surround) (CimIcHandle ic, void* user_data);

  bool (*delete_surround)   (CimIcHandle ic,

                             int32_t  offset,

                             uint32_t n_chars,

                             void*  user_data);

  /* candidate */

  void (*candidate_show)     (CimIcHandle ic,

                              uint32_t n_rows,

                              uint32_t n_cols,

                              bool show_aux,

                              void* user_data);

  void (*candidate_hide)     (CimIcHandle ic, void* user_data);

  void (*candidate_changed)  (CimIcHandle ic,

                              const CimCandidate* candidate,

                              void* user_data);

  void (*candidate_selected) (CimIcHandle ic,

                              const CimSelection* selection,

                              void* user_data);

  /* reserved */

  void* reserved[6];

};


서버측에서 compose_cancelled 콜백을 별도로 호출하는 방식으로 할까?


제시하신 내용은 IME 아키텍처의 중요한 설계적 트레이드오프(trade-off)를 정확히 지적하고 있습니다. compose_cancelled 콜백을 추가하는 것이 부적절해 보인다고 느끼는 이유는 그것이 API의 특수성을 높여 전반적인 일관성을 해칠 수 있기 때문입니다.

현재 방식과 제안하신 방식을 분석하고 더 나은 대안을 제시하겠습니다.


## 현행 방식 (beep 호출) 분석

이 방식은 서버가 클라이언트에게 수행할 동작을 직접 **명령(Command)**하는 구조입니다.

  • 방식: 서버가 컴포즈가 취소되었으니, 경고음을 울려라라고 결정하고 클라이언트에 beep 명령을 내립니다.
  • 장점:
    • 단순성: 클라이언트는 이유를 알 필요 없이 명령만 수행하면 되므로 구현이 간단합니다.
    • 재사용성: beep 콜백은 컴포즈 취소 외 다른 종류의 경고 상황에서도 재사용될 수 있습니다.
  • 단점:
    • 낮은 유연성: 클라이언트가 경고 방식을 변경할 수 없습니다. 예를 들어, 사용자가 경고음을 끄고 화면 깜빡임으로 대체하고 싶어도 서버가 beep을 명령하기 때문에 불가능합니다.
    • 관심사 분리 위배: 입력 로직을 처리해야 할 서버가 UI 피드백(경고음)까지 결정하여 클라이언트의 역할을 침범합니다.

## 제안 방식 (compose_cancelled 콜백) 분석

이 방식은 서버가 클라이언트에게 특정 **이벤트(Event)**가 발생했음을 알리는 구조입니다.

  • 방식: 서버가 컴포즈가 취소되었다라는 이벤트만 클라이언트에 알립니다. 경고음을 울릴지, 다른 피드백을 줄지는 클라이언트가 결정합니다.
  • 장점:
    • 높은 유연성: 클라이언트는 compose_cancelled 이벤트를 수신하여 설정에 따라 경고음을 울리거나, 화면을 깜빡이거나, 아무것도 하지 않는 등 자유롭게 반응을 결정할 수 있습니다. 관심사 분리(Separation of Concerns) 원칙에 더 부합합니다. ?
    • 명확한 의미: 콜백 이름(compose_cancelled)만으로 어떤 상황이 발생했는지 명확하게 알 수 있습니다.
  • 단점:
    • API 복잡도 증가: compose_cancelled와 유사한 특정 이벤트가 생길 때마다 콜백을 추가하면 CimCallbacks 구조체가 비대해지고 관리하기 어려워집니다. 이것이 바로 부적절해 보인다고 느끼신 핵심적인 이유입니다.

## 결론 및 추천 대안

beep 명령 방식은 유연성이 부족하고, 개별 이벤트 콜백 방식은 API를 비대하게 만들 위험이 있습니다. 이 두 방식의 장점을 모두 취하는 더 나은 대안은 **일반화된 이벤트 콜백(Generalized Event Callback)**을 도입하는 것입니다.

CimCallbacks 구조체에 compose_cancelled 대신 다음과 같은 단일 콜백을 추가하는 것을 권장합니다.

typedef enum {
  CIM_NOTIFICATION_COMPOSE_CANCELLED,
  CIM_NOTIFICATION_INPUT_ERROR
  /* ... future notification types ... */
} CimNotificationType;

// CimCallbacks 구조체에 추가할 멤버
void (*notify) (CimIcHandle ic,
                 CimNotificationType type,
                 void* user_data);
  • 동작 방식: 서버는 compose_cancelled 상황이 발생하면 notify 콜백을 CIM_NOTIFICATION_COMPOSE_CANCELLED 타입과 함께 호출합니다. c // 서버측 코드 예시 case XKB_COMPOSE_CANCELLED: nimf_system_keyboard_update_preedit (lingua, target, c_strdup ("")); nimf_service_ic_call_notify (target, NIMF_NOTIFICATION_COMPOSE_CANCELLED); // beep 대신 호출 break;
  • 장점:
    1. 확장성: 앞으로 INPUT_ERROR 등 새로운 알림 유형이 추가되어도 CimCallbacks 구조체를 변경할 필요 없이 CimNotificationType 열거형만 확장하면 됩니다. API의 안정성을 유지할 수 있습니다.
    2. 유연성: 클라이언트는 notify 콜백 내에서 type을 확인하여 각 상황에 맞는 최적의 피드백(beep, 시각 효과 등)을 제공할 수 있습니다.
    3. API 간결성 유지: 콜백 구조체에 단 하나의 멤버만 추가되므로 API가 비대해지는 것을 막을 수 있습니다.

따라서, 일반화된 notify 콜백을 도입하는 것이 장기적인 관점에서 가장 깔끔하고 확장 가능한 설계입니다.


너 판단에는, CimCallbacks 에 notify 멤버를 추가하는 방법과, cim_ic_set_notify_callback 함수로 notify 콜백을 등록하는 방법 중 어느 것이 나아보이는가?

제 판단으로는, CimCallbacks 구조체에 notify 멤버를 추가하는 방법이 더 나은 선택입니다.

API 설계에서 일관성(Consistency)은 매우 중요한 원칙이며, 이 기준에서 두 방법을 평가하면 결론이 명확해집니다.


## CimCallbacks notify 멤버 추가 (권장)

이 방법은 현재 cim.h에 이미 확립된 설계 패턴을 그대로 따릅니다.

  • 최고의 장점: API의 일관성 유지

    • 클라이언트는 이미 cim_ic_set_callbacks 함수를 통해 모든 콜백을 등록하는 방식에 익숙합니다. notify 콜백도 같은 방식으로 등록하게 되면, API를 배우고 사용하는 것이 매우 직관적입니다. Cim의 콜백은 CimCallbacks 구조체를 통해 등록한다는 단 하나의 규칙만 기억하면 됩니다.
  • 부가적인 장점: API 간결성

    • 새로운 public 함수(cim_ic_set_notify_callback)를 추가할 필요가 없어 API가 불필요하게 커지는 것을 막습니다. 모든 설정은 기존의 cim_ic_set_callbacks로 통일됩니다.
    • CimCallbacks 구조체의 reserved 필드를 활용하면 ABI 호환성을 유지하면서 새 멤버를 추가할 수 있습니다.

## cim_ic_set_notify_callback 함수 추가

이 방법은 유연성을 제공하지만 API의 일관성을 해치는 비용을 치릅니다.

  • 단점: 설계 원칙의 불일치

    • 이 방식을 채택하면 클라이언트 개발자는 혼란에 빠질 수 있습니다.  commit이나 preedit_changed 같은 콜백은 구조체로 한 번에 등록하는데, notify 콜백만 별도의 함수로 등록해야 하는가?라는 의문이 생깁니다. 이처럼 동일한 종류의 작업을 다른 방식으로 처리하게 만드는 것은 API 설계를 복잡하게 만드는 요인입니다.
  • 장점: 동적 변경의 유연성

    • 런타임 중에 notify 콜백만 독립적으로 변경할 수 있다는 장점이 있지만, IME의 콜백이 그렇게 빈번하게 동적으로 변경되어야 할 필요성은 일반적으로 높지 않습니다. 일관성을 희생하면서까지 이 유연성을 얻는 것이 더 큰 이득이라고 보기는 어렵습니다.

## 최종 결론

결론적으로, CimCallbacks 구조체에 notify 멤버를 추가하는 방법을 강력히 추천합니다.

이 방법은 API의 일관성과 예측 가능성이라는 장기적인 가치를 지키는 선택입니다. 좋은 API는 사용자가 고민 없이 당연하게 사용할 수 있어야 하며, 일관성은 이를 위한 가장 중요한 요소 중 하나입니다. ?


 notify의 종류로 앞으로 추가가 예상되는 것들이 있을까? 현재 xkb_compose_cancelled가 있다.

네, xkb_compose_cancelled 외에도 일반화된 notify 콜백을 통해 전달하면 유용한 여러 상태 변화 및 이벤트가 있습니다. IME(입력기)의 특성을 고려할 때, 앞으로 다음과 같은 종류의 알림들이 추가될 수 있습니다.

이벤트들을 성격에 따라 몇 가지 범주로 나눌 수 있습니다.


## 1. 사용자 입력 피드백 (User Input Feedback)

사용자의 키 입력에 대한 직접적인 반응 중, 문자 입력이나 preedit 변경이 아닌 미묘한 상태를 알립니다.

  • INVALID_KEY_PRESS

    • 설명: 현재 입력 상태에서 아무 기능도 하지 않는 키가 눌렸을 때 발생합니다. 예를 들어, 한글 조합 중에 갑자기 Page Up 키를 누르는 경우입니다. 클라이언트는 이 알림을 받아 경고음이나 시각적 효과로 사용자에게 유효하지 않은 입력임을 알릴 수 있습니다. COMPOSE_CANCELLED 조합 시퀀스의 실패를 알린다면, 이것은 단일 키 입력의 무효함을 알립니다.
  • SELECTION_WRAPPED

    • 설명: 후보창 목록에서 마지막 항목 다음에 아래 방향키를 누르거나, 첫 항목 이전에 위 방향키를 눌러 선택이 순환될 때 발생합니다. 클라이언트는 이를 인지하여 사용자에게 미묘한 소리 피드백 등을 제공할 수 있습니다.

## 2. 상태 및 모드 변경 (State and Mode Changes) ?

IME 엔진의 내부 상태나 입력 모드가 변경되었음을 알립니다. 클라이언트 UI를 동기화하는 데 매우 중요합니다.

  • INPUT_MODE_CHANGED
    • 설명: 한/영 키 입력 등으로 입력 언어 모드(예: 한글 ↔ 영어)가 변경되었을 때 발생합니다. 클라이언트는 이 알림을 받아 트레이 아이콘이나 상태바의 언어 표시를 에서 EN으로 바꾸는 등의 UI 업데이트를 수행해야 합니다.
  • HANJA_MODE_ACTIVATED
    • 설명: 한자 키 입력으로 한자 변환 모드가 활성화되거나 비활성화될 때 발생합니다.
  • FULL_WIDTH_MODE_CHANGED
    • 설명: 전각/반각 변환 키 입력으로 문자 폭 모드가 변경되었을 때 발생합니다.
  • COMPOSITION_CLEARED_AUTOMATICALLY
    • 설명: 사용자가 직접 지운 것이 아니라, 포커스 이동 등의 이유로 엔진이 내부적으로 조합 중인 글자(preedit)를 초기화했을 때 발생합니다. 클라이언트가 자체적으로 관리하는 상태와 동기화할 때 유용할 수 있습니다.

## 3. 엔진 및 시스템 이벤트 (Engine and System Events) ⚙+

엔진의 동작이나 외부 설정과 관련된 이벤트를 알립니다.

  • CONFIG_RELOADED
    • 설명: 별도의 설정 프로그램 등에서 사용자가 IME 설정을 변경하여, 실행 중인 엔진이 해당 설정을 다시 불러왔을 때 발생합니다. 클라이언트가 설정과 관련된 UI를 가지고 있다면 이를 갱신할 수 있습니다.
  • DICTIONARY_UPDATED
    • 설명: 사용자 사전이 추가/변경되었을 때 이를 알립니다.

## 4. 오류 및 경고 (Error and Warning Conditions) ⚠+

단순한 입력 실패보다 더 심각한 오류 상황을 알립니다.

  • DICTIONARY_LOOKUP_FAILED
    • 설명: 한자 변환 등을 위해 사전을 조회해야 하는데, 사전 파일이 손상되었거나 접근할 수 없을 때 발생합니다. 클라이언트는 사전 파일을 찾을 수 없습니다와 같은 구체적인 오류 메시지를 사용자에게 보여줄 수 있습니다.
  • MAX_PREEDIT_LENGTH_REACHED
    • 설명: 엔진이 허용하는 최대 조합 글자 수(preedit)에 도달했는데 사용자가 입력을 계속 시도할 때 발생합니다.

## 종합 예시 (Enum Definition Example)

이러한 아이디어들을 종합하면 CimNotificationType 열거형은 다음과 같이 정의될 수 있습니다.

typedef enum {
  /* User Input Feedback */
  CIM_NOTIFICATION_COMPOSE_CANCELLED,
  CIM_NOTIFICATION_INVALID_KEY_PRESS,
  CIM_NOTIFICATION_SELECTION_WRAPPED,

  /* State and Mode Changes */
  CIM_NOTIFICATION_INPUT_MODE_CHANGED,
  CIM_NOTIFICATION_HANJA_MODE_ACTIVATED,
  CIM_NOTIFICATION_FULL_WIDTH_MODE_CHANGED,
  CIM_NOTIFICATION_COMPOSITION_CLEARED_AUTOMATICALLY,

  /* Engine and System Events */
  CIM_NOTIFICATION_CONFIG_RELOADED,
  CIM_NOTIFICATION_DICTIONARY_UPDATED,

  /* Error and Warning Conditions */
  CIM_NOTIFICATION_DICTIONARY_LOOKUP_FAILED,
  CIM_NOTIFICATION_MAX_PREEDIT_LENGTH_REACHED

} CimNotificationType;










최종 결과는 다음과 같다.

ㅋㅋㅋ



typedef struct _CimCallbacks CimCallbacks;
struct _CimCallbacks {
  void (*preedit_start)     (CimIcHandle ic, void* user_data);
  void (*preedit_end)       (CimIcHandle ic, void* user_data);
  void (*preedit_changed)   (CimIcHandle ic,
                             const CimPreedit* preedit,
                             void* user_data);
  void (*commit)            (CimIcHandle ic,
                             const char* text,
                             void* user_data);
  /* Do not free CimSurround and its text */
  const CimSurround* (*get_surround) (CimIcHandle ic, void* user_data);
  bool (*delete_surround)   (CimIcHandle ic,
                             int32_t  offset,
                             uint32_t n_chars,
                             void*  user_data);
  /* candidate */
  void (*candidate_show)     (CimIcHandle ic,
                              uint32_t n_rows,
                              uint32_t n_cols,
                              bool show_aux,
                              void* user_data);
  void (*candidate_hide)     (CimIcHandle ic, void* user_data);
  void (*candidate_changed)  (CimIcHandle ic,
                              const CimCandidate* candidate,
                              void* user_data);
  void (*candidate_selected) (CimIcHandle ic,
                              const CimSelection* selection,
                              void* user_data);
  void (*notify) (CimIcHandle ic,
                  CimNotificationType type,
                  void* user_data);
  /* reserved */
  void* reserved[5];
};



추천 비추천

0

고정닉 0

0

댓글 영역

전체 댓글 0
본문 보기

하단 갤러리 리스트 영역

왼쪽 컨텐츠 영역

갤러리 리스트 영역

갤러리 리스트
번호 제목 글쓴이 작성일 조회 추천
설문 우리나라를 대표해서 UN 연설자로 내보내고 싶은 스타는? 운영자 25/09/29 - -
AD 프로게이머가 될테야!! 운영자 25/10/01 - -
2892864 태연 ㅇㅅㅇ 헤르 미온느갤로그로 이동합니다. 09.29 34 0
2892863 하루 한 번 헤르미온느 찬양 헤르 미온느갤로그로 이동합니다. 09.29 57 0
2892861 3500억 $ -> imf -> 알짜기업 팔림 -> 망국 프갤러(175.197) 09.29 111 0
2892860 지드래곤 ♥냥덩이♥갤로그로 이동합니다. 09.29 61 0
2892859 귀염 ♥냥덩이♥갤로그로 이동합니다. 09.29 36 0
2892858 프랑스 사태 보면 나님 예지몽 ㄹㅇ 인듯 ♥냥덩이♥갤로그로 이동합니다. 09.29 55 1
2892857 프갤 켜니 화면주사율이 일정해짐. 다른거 하면 이상해지네.. DVI소프펌 넥도리아(220.74) 09.29 54 0
2892856 다카이치 사나에 - 닥터때바라 닮음 (둘다 빌런대장) ㅇㅇ(175.197) 09.29 39 0
2892855 앱히키 씨발년아 뒤져라 [1] ㅇㅇ(222.108) 09.29 59 0
2892854 인지과학조져라 손발이시립디다갤로그로 이동합니다. 09.29 61 0
2892853 자고 일어나서 빌드하면 드디어 타로 일일 운세까지는 완성하겠네 [2] ㅆㅇㅆ(124.216) 09.29 52 0
2892852 AMI를 vmdk로 추출 후 vmware에서 부팅해본사람 ㅇㅇ갤로그로 이동합니다. 09.29 35 0
2892849 스레드가 뭔지도 모르는 새끼가 왜 비동기로 개념싸움 거는거야 [2] ㅇㅇ(106.241) 09.29 79 1
2892843 밥버러지... 고기도 익고... 명절한상 1주 시작. 넥도리아(220.74) 09.29 74 0
2892842 파이썬 질문인데 sha256 체크섬이 일치하지 않는다고 뜨는데.. [1] 프갤러(125.249) 09.29 68 0
2892841 ㅅㅂ... 알콜중독인가 잠이안와서 갈비탕 한그릇에 맥주깠다 ㅇㅇ(223.38) 09.29 35 0
2892840 밥 언재끔 커피 뿌려주었는데... 넥도리아(220.74) 09.29 76 0
2892839 밥짓는중. 넥도리아(220.74) 09.29 35 0
2892834 운영체제 충 돼서, 운영체제 모르면 개발이 불가능하다 생각하는데 ㅇㅇ(106.241) 09.29 63 0
2892832 저희는 가짜 프로그래머입니다. [1] 프갤러(110.8) 09.29 90 0
2892830 여기서 좀 정상적인 글쓰면 저능아들 꼬이는 그게 문제긴함 [1] ㅆㅇㅆ(124.216) 09.29 71 0
2892829 님들 진짜 프로그래머 맞나요 [3] Fjeoeieie갤로그로 이동합니다. 09.28 124 0
2892828 드이어 야구 동영상 옮긴다. 외장 볼륨있게 넥도리아(220.74) 09.28 40 0
2892824 나님 월 마일리지 인증 [7] ♥냥덩이♥갤로그로 이동합니다. 09.28 129 0
2892823 나님 이민 전략 칼럼 하나 쓰긴 써야하는데 [3] ♥냥덩이♥갤로그로 이동합니다. 09.28 92 0
2892804 나님 한국자격증 다 외국자격증으로 바꾸는중 [5] ♥냥덩이♥갤로그로 이동합니다. 09.28 112 0
2892788 클로드랑 GPT 물어봐서 앱 만들었어요 [2] zian갤로그로 이동합니다. 09.28 81 0
2892783 얼룩젖소무늬의 비밀 [1] ♥냥덩이♥갤로그로 이동합니다. 09.28 60 0
2892772 ❤+ [3] ♥냥덩이♥갤로그로 이동합니다. 09.28 100 0
2892769 오늘은 뭐할까 고민되네 ㅠㅠ 나르시갤로그로 이동합니다. 09.28 39 0
2892766 병신찐따 영포티 ㅋㅅㅋ ♥냥덩이♥갤로그로 이동합니다. 09.28 78 0
2892764 어흥! 호피무늬 모모링❤ [4] ♥냥덩이♥갤로그로 이동합니다. 09.28 117 0
2892761 인텔 ddr6 램64 10코어 이상 15w 미만 소비전력 아니면 안사줌 ♥냥덩이♥갤로그로 이동합니다. 09.28 42 0
2892754 주기적으로 컴퓨터, 노트북, 폰 포맷하는데 이상하나 ㅇㅇ(106.241) 09.28 37 0
2892753 웹개발 관련 여기서 물어봄? [2] Noitamina갤로그로 이동합니다. 09.28 80 0
2892747 ❤✨☀⭐⚡☘⛩나님 시작합니당⛩☘⚡⭐☀✨❤ ♥냥덩이♥갤로그로 이동합니다. 09.28 27 0
2892746 AI 시대 최고 수혜 주식은? [4] 나르시갤로그로 이동합니다. 09.28 73 0
2892739 자바로 뭐 할수있음? [8] ㅇㅇ갤로그로 이동합니다. 09.28 100 0
2892737 ㅆㅇㅆ 모기 새끼 프갤러(210.217) 09.28 66 5
2892735 아 조만간 연휴구나 [2] 루도그담당(58.239) 09.28 58 0
2892732 모기떄문에 짜증난다. 프갤러(210.217) 09.28 51 4
2892729 게임쪽은 계속하고 싶은데 돈이 없다. ㅆㅇㅆ(124.216) 09.28 54 0
2892726 게임쪽 창업<<이거 씨발 사기만 안먹었어도 계속했는데 [4] ㅆㅇㅆ(124.216) 09.28 99 0
2892725 if문에서 3일 걸리는 애들도 있네 [6] 루도그담당(58.239) 09.28 121 0
2892720 매일 4~5시간 자니까 건강이 엉망되었네 ㅎㅎ 나르시갤로그로 이동합니다. 09.28 33 0
2892719 ㅆㅇㅆ 이사람 요즘 뭐함? [2] ㅇㅇ갤로그로 이동합니다. 09.28 78 3
2892718 SM이 기술력이 낮다? 규모도 기술력이란걸 간과하지마 프갤러(219.115) 09.28 37 0
2892708 나님두 부천Bj 하구 싶당 야차 뜨실 분 구함 ♥냥덩이♥갤로그로 이동합니다. 09.28 55 0
2892697 하... 할 일들은 많고 시간은 없고 마음만 조급하고 후달린다... ㅇㅇ(223.38) 09.28 69 0
2892691 게임 같은거 만들 때, 컴하하스러운 내용 넣으면 어떤거 같음? [1] ㅇㅇ(106.241) 09.28 35 0
뉴스 10주년 맞은 ‘시흥시청소년동아리축제’ 전국 최대 규모로 18일 개최 디시트렌드 10.02
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

뉴스

디시미디어

디시이슈

1/2