디시인사이드 갤러리

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

갤러리 본문 영역

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

나르시갤로그로 이동합니다. 2025.09.27 17:14:09
조회 68 추천 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 - -
공지 프로그래밍 갤러리 이용 안내 [96] 운영자 20.09.28 47604 65
2893664 중국인이 찍은 최근 조선 사진 발명도둑잡기(118.235) 03:44 5 0
2893663 “엡스타인, 정보기관과 연관됐나” 의혹 여전… 美 정부는 침묵 발명도둑잡기(118.235) 03:36 5 0
2893655 흐름 상징 발명도둑잡기(118.235) 02:54 17 0
2893649 한국 국회, 정부, 법원은 여전히 미군위안부같은 정치를 하고 있다 발명도둑잡기(118.216) 02:42 8 0
2893644 사실 세대론으로 비판하면 안되고 생산수단 가진자를 비판해야 발명도둑잡기(118.235) 01:57 12 0
2893642 오늘의 소설, 영화 실마리: 성매매자 데이터베이스가 외국 정보기관에 발명도둑잡기(118.235) 01:52 9 0
2893641 엠스타인 명단 공개 예정인 의원 발명도둑잡기(118.235) 01:38 10 0
2893639 형님들 스타트업은 원래 조용한가요? [3] ㅇㅇ(106.101) 01:16 40 0
2893638 이직 하고 싶은데 물경력이라 방법이 없다.. ㅇㅇ(175.197) 01:16 24 0
2893637 BTS (방탄소년단) 'Dynamite' 발명도둑잡기(118.216) 01:07 14 0
2893636 먹고 살려고 안해본 일이 없는데, IT 프리랜서 장점은 ㅆㅇㅆ(124.216) 01:06 27 0
2893635 내가 느끼는게 랜딩 페이지 하나 작성에 15만 ㅆㅇㅆ찡갤로그로 이동합니다. 00:59 21 0
2893634 프리로 협업 몇번해봤는데 항상 느끼지만 ㅆㅇㅆ찡갤로그로 이동합니다. 00:56 24 0
2893632 어차피 개발하다보면 서로 지식의 빈곳이 있을수밖에 없어서 [3] ㅆㅇㅆ찡갤로그로 이동합니다. 00:48 39 0
2893631 신해철, 싸이-Dear America [1] 발명도둑잡기(118.216) 00:38 21 0
2893629 우리나라가 소프트웨어 강국이 되려면 ㅇㅇ(121.168) 00:30 19 0
2893628 한국 10년뒤엔 러스트충들 국비찍어될듯 타이밍뒷.통수한방(1.213) 00:29 21 0
2893627 일하면 그냥 현타 존나옴 [25] ㅇㅇ갤로그로 이동합니다. 00:24 86 0
2893626 오늘의 작사 실마리: 관세전쟁 [3] 발명도둑잡기(118.216) 00:24 17 0
2893625 진짜 돈 모아서 C드라이브랑 메인보드 교체해야할듯 [2] ㅆㅇㅆ(124.216) 00:20 26 0
2893624 이거 교정 방법 잘못 고른건가? 발명도둑잡기(118.216) 00:18 11 0
2893622 후 아뮤튼 러스트 배워두십시오. 지능이 향상됩니다. [1] 프갤러(110.8) 00:12 25 0
2893620 밀레니얼로서 난 X세대보다 더 행복한 유년기에 꿀빨았다고 생각해 ㅇㅇ(121.168) 00:12 19 0
2893619 간식을 먹는데 입 안에 자꾸 찔려서 눈물이 저절로 난다 발명도둑잡기(118.216) 00:10 14 0
2893618 문화생활 깊이있게 하려면 무조건 일본에 의지 할 수 밖에 없음 [2] ♥냥덩이♥갤로그로 이동합니다. 00:10 25 0
2893616 sm은 원래 현업보다 it팀이 더 업무 프로세스를 잘 앎? [1] 프갤러(182.230) 00:02 24 0
2893615 서울에서 자란 친구들은 공부 못하면 부모가 ADHD의심해? ㅇㅇ(121.168) 00:01 17 0
2893614 이 시절 그리우면 개추 [3] ♥냥덩이♥갤로그로 이동합니다. 00:00 32 1
2893613 야야야야양야 진짜 발견. 계란국에 페퍼론치노 넣으니까 더 맛있음 ㅇㅇ(223.39) 10.02 13 0
2893612 성매매 국내 최고 DB 다크웹에 나와서 각국 정보기관이 샀을 것 발명도둑잡기(118.216) 10.02 24 0
2893611 나 금 산 거 며칠 전에 드디어 100% 넘었다 발명도둑잡기(118.216) 10.02 17 0
2893610 프갤에 모모와 김희철의 사랑 소설 써볼까 발명도둑잡기(118.216) 10.02 15 0
2893609 낼 봐야징 ♥냥덩이♥갤로그로 이동합니다. 10.02 13 0
2893608 ㅆㅇㅆ새끼 뭣좀 해볼려고 우울증갤러리,업소 프갤러(210.217) 10.02 29 2
2893607 최근에 있던 회사에서 얻은 교훈은 ㅇㅇ(121.168) 10.02 16 0
2893606 나님 글 슬거리 생각났당 ♥냥덩이♥갤로그로 이동합니다. 10.02 11 0
2893605 곧 죽을 때가 됐나보구만 [2] 프갤러(110.8) 10.02 27 0
2893603 34살에 국비로 취업했는데 [6] ㅇㅇ(175.197) 10.02 54 0
2893601 338621 맞대응) 프듀48 주작과 S엔터 ㅇㅇ(110.70) 10.02 36 0
2893600 근데 궁금한게 업소가는 애들은 자기 신상 팔리는거 안무섭나 [3] ㅆㅇㅆ(124.216) 10.02 37 0
2893599 추석 연휴 업소 가는 형들 꿀팁 반값 꿀팁 풀게ㅅㅅ ㅇㅇ(211.246) 10.02 15 0
2893598 오늘 당산에 연극보러 갔는데 어제랑 똑같은거드라 발명도둑잡기(118.235) 10.02 11 0
2893597 모모 추석맞이 김희철과 선물 교환하고 발명도둑잡기(118.235) 10.02 16 0
2893596 그날 인류는 떠올렸당⭐+ ♥냥덩이♥갤로그로 이동합니다. 10.02 20 1
2893595 옳지.. 옳지 잘한당.. 그랭그랭.. [9] ♥냥덩이♥갤로그로 이동합니다. 10.02 53 0
2893593 기술인들이 잘되려면 창업 성공률이 높아야 하고 ㅇㅇ(121.168) 10.02 15 0
2893591 si 추노 후기 [4] 프갤러(222.121) 10.02 55 0
2893589 늦잠자지마라 애들아 [3] 루도그담당(58.239) 10.02 36 0
2893587 자취방 정리하고 나 지금 본가임 [5] ㅆㅇㅆ(124.216) 10.02 32 0
뉴스 '마이 유스' 이주명, 서지훈 눈물에 어깨 토닥! 설레는 변화 디시트렌드 10.02
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

뉴스

디시미디어

디시이슈

1/2