디시인사이드 갤러리

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

갤러리 본문 영역

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

나르시갤로그로 이동합니다. 2025.09.27 17:14:09
조회 66 추천 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 - -
2892484 여자 불러서 술맥여서 강간하던 새끼들이 정상적으로 학교다니고 [2] ㅆㅇㅆ(124.216) 09.27 75 0
2892483 리버싱할때 어셈 분석해보면 루도그담당(58.239) 09.27 65 0
2892482 유동아 아직도 미짜 불러서 술맥이고 따먹냐. 정신차리고 살아 새끼야 ㅆㅇㅆ(124.216) 09.27 46 0
2892481 성인들도 유딩처럼 불꽃놀이에 카메라 들이대고 [5] 헬마스터갤로그로 이동합니다. 09.27 69 0
2892480 나를 울갤에서 봤니마니하는데 내가 울갤서 싸운건 술마셔서 미짜 따먹던 [1] ㅆㅇㅆ(124.216) 09.27 69 0
2892479 류도그<<임마 신기한게 임마 남 괴롭힐때마다 다중이 유동 ㅆㅇㅆ(124.216) 09.27 61 0
2892478 류도그가 병신인건 LLM을 써서 만들건 코딩을 타이핑하건 ㅆㅇㅆ(124.216) 09.27 51 0
2892476 오늘 하루종일 분석만 했다 [1] 루도그담당(58.239) 09.27 78 0
2892475 슬슬 류도그 또 나왔구만 ㅆㅇㅆ(124.216) 09.27 48 0
2892474 사기꾼은 ㅆㅇㅆ지 프갤러(210.217) 09.27 76 3
2892473 애초에 모든 학문의 근간은 암기서 시작함 ㅆㅇㅆ(124.216) 09.27 45 0
2892472 52Hz ♥냥덩이♥갤로그로 이동합니다. 09.27 40 0
2892471 애새끼좀 더 번식해라 이기이기 ㅋㅋㅋㅋ 타이밍뒷.통수한방(1.213) 09.27 41 0
2892470 개발 암기 잘할수록 유리함 애초에 대부분 프로그램 패턴이 정해져있어서 ㅆㅇㅆ(124.216) 09.27 62 0
2892469 파워 a.s q.n.a 넥도리아(220.74) 09.27 45 0
2892468 git 커밋 로그 영어로 써 줘 ㅋㅋ [1] 나르시갤로그로 이동합니다. 09.27 71 0
2892466 시발거 존나 뻥뻥거리네 프갤러(49.165) 09.27 62 0
2892465 코드에 문제가 있는지 확인해. [2] 나르시갤로그로 이동합니다. 09.27 77 0
2892464 지금 개발판 사기꾼 바닥임 [6] 프갤러(220.93) 09.27 120 0
2892460 아 씨발 개발자 포기할려니까 할만한게 딱히 없음 [9] ㅇㅇ갤로그로 이동합니다. 09.27 108 0
2892459 민생쿠폰10만원받았는데 식비로도 10만원 넘게필요하지않음?? 타이밍뒷.통수한방(1.213) 09.27 39 0
2892458 XIM 통신 구현에서 공용체 union 사용 예시 나르시갤로그로 이동합니다. 09.27 40 0
2892456 저번 프붕이 통신 프로토콜 질문에 대한 실제 예시 코드 ㅋㅋ 나르시갤로그로 이동합니다. 09.27 42 0
2892455 공채 합격률이 상채 합격률보다 더 높은가? ㅇㅇ갤로그로 이동합니다. 09.27 36 0
2892453 프붕이들 깜놀랄 프로토콜 설계 ㅋㅋ [5] 나르시갤로그로 이동합니다. 09.27 74 0
2892452 고수분들은 코테 준비 어케 했음? 코테>>약간 후기도 있음 프갤러(114.205) 09.27 205 0
2892443 다음과 같은 에러가 났다. 어떻게 해결하는 것이 좋겠는가? [1] 나르시갤로그로 이동합니다. 09.27 65 0
2892442 다음 코드의 형변환에 문제 없지? 나르시갤로그로 이동합니다. 09.27 53 0
디자인 = 설계, 오늘 제미니 제안 사항 나르시갤로그로 이동합니다. 09.27 66 0
2892437 쓰레기통에 재활용하기에는 방의물건이 200-300 가치다 책포함. [2] 넥도리아(220.74) 09.27 36 0
2892434 내 자신의 디자인적 능력이 너무 덜떨어져있다 [4] ㅆㅇㅆ(124.216) 09.27 58 0
2892433 ■램16기가면 윈도우는 쓰지 말아야함? OS추천좀 [4] ㅇㅇ갤로그로 이동합니다. 09.27 84 0
2892431 주말이나 휴가때 즐기는 취미나 휴식활동 있음?? [3] ㅇㅇ(223.39) 09.27 56 0
2892430 알고리즘 강의 들을만한 사람 없음? 프갤러(114.205) 09.27 37 0
2892429 오늘도 코딩하다보면 정신나갈것같군. ㅆㅇㅆ(124.216) 09.27 58 0
2892424 책샀어요. 옆에는 기억이 안나는 SSD 넥도리아(220.74) 09.27 63 0
2892423 이미 메신저 앱 겁나 많아요. 위챗이 카톡의 최대 경쟁자입니다 [5] 나르시갤로그로 이동합니다. 09.27 72 0
2892422 몇%정도 점유율 뺏겨야 나머지 사람들도 움직이려나 프갤러(45.64) 09.27 37 0
2892419 지금 메신저앱 나오면 빈집털기 ㅆㄱㄴ인데 ㅇㅇ갤로그로 이동합니다. 09.27 46 0
2892418 카톡한데 서버 이중화 왜 안 했냐고 열라 까던 조센징 정부 [2] 나르시갤로그로 이동합니다. 09.27 118 0
2892417 분석계획실행피드백 [2] 공기역학갤로그로 이동합니다. 09.27 69 0
2892414 우체국은 서버 이중화도 안 한거냐?? 대박인걸 나르시갤로그로 이동합니다. 09.27 101 0
2892413 우체국 화재) 한국 IT가 이정도로 개판이다. [3] 나르시갤로그로 이동합니다. 09.27 132 0
2892412 카카오뱅크 욕했던 조센징들 보셈 나르시갤로그로 이동합니다. 09.27 62 0
2892410 뜌.. 뜌땨잇!! [2] ♥냥덩이♥갤로그로 이동합니다. 09.27 67 1
2892409 역시 착착 진행중이었구만 ㄷㄷ ㅇㅇ갤로그로 이동합니다. 09.27 62 0
2892407 인지과학조져라 손발이시립디다갤로그로 이동합니다. 09.27 43 0
2892406 노인들이 주장하는 노력과 운이라는 말 존나 좇같음 타이밍뒷.통수한방(1.213) 09.27 42 0
2892405 카톡 점유율 보아할 때 카톡은 착한 편 [1] 나르시갤로그로 이동합니다. 09.27 53 0
2892403 구글씨발 애미뒤진새끼들 광고존나덕지덕지줘패고싶다 [1] 밀우갤로그로 이동합니다. 09.27 42 0
뉴스 '싱어게인4-무명가수전' 본선 진출 81인 최초 공개! 디시트렌드 10.01
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

뉴스

디시미디어

디시이슈

1/2