← 목록
AI 2026-07-11 10KB 읽기 11분

CrownyAI 브라우저 한/영 — 앱 전용 토글 폐기, macOS 입력소스 추종

개요

CrownyAI 브라우저(native/crowny-browser.m) 네이티브 앱뷰(CrownyAppView, 메모/터미널 등)의 한/영 판정을 앱 전용 Ctrl+Space 토글에서 macOS OS 입력소스 추종으로 전환했다. 사장님 확정 설계: 조합(자모→음절)은 크라우니 한글조합기.toau(헌법 — 맥 IME 조합 비의존)를 그대로 쓰되, "지금 한/영 어느 쪽인가"라는 판정만 OS에 묻는다.

배경 — 왜 바꿨나 (실측)

기존 구현은 CrownyAppView.한글모드 플래그를 keyDown에서 Ctrl+Space로 토글했다. 그런데 macOS는 Ctrl+Space를 시스템 "이전 입력기 선택" 단축키로 이미 선점하고 있어 이벤트가 애초에 앱까지 오지 않는다 — 사용자 실측: 눌러도 배지가 안 바뀜. 즉 "앱 전용 한/영 모드"라는 설계 자체가 macOS 표준 단축키 정책과 충돌하는 구조적 오류였다.

확정 설계

  • 판정 = OS 입력소스 추종. 사용자가 평소 쓰는 맥 한영키(⌘Space 계열 또는 사용자 지정
단축키)·Caps Lock 그대로 쓰면 앱 배지/조합 모드가 따라간다.
  • 조합 = 크라우니 조합기 유지. 한/영 판정만 OS에서 가져오고, 자모를 음절로 합치는
로직은 기존 appRunComposeCmd("JAMO"/"COMMIT"/"BS") 경로 그대로 — macOS TSM/IME 조합에 의존하지 않는다(헌법 — 외부 의존성 최소화).

구현 (native/crowny-browser.m)

  1. TIS 감지 헬퍼 cbIsKoreanInputSource() (crowny-browser.m:686 부근, cbWriteInputMode
직후) — Carbon TISCopyCurrentKeyboardInputSource() + kTISPropertyInputSourceID로 현재 입력소스 ID를 얻어 "com.apple.inputmethod.Korean"(2벌식/3벌식/390 등 macOS 내장 한국어 IME 전부 이 접두사) 또는 방어적으로 "com.apple.keylayout.Korean"(하드웨어 레이아웃형) 접두사면 한글로 판정.
  1. 변경 감지 — 두 경로 병행
- ① kTISNotifySelectedKeyboardInputSourceChanged 분산 알림을 NSDistributedNotificationCenter로 구독(initWithService:에서 등록, - (void)onInputSourceChanged:가 핸들러). TIS 알림은 Darwin 배포센터 (CFNotificationCenterGetDistributedCenter) 경유로 발행되고, NSDistributedNotificationCenter가 같은 이름으로 수신 가능 — 사용자 실제 한영키 입력 시 즉시 배지 갱신. - ② keyDown 진입 시마다 cbIsKoreanInputSource() 재확인(알림 유실 대비 보험, TIS 호출은 저비용이라 매 키 입력 부담 무시 가능 실측). - 둘 다: 값이 바뀌면 조합세션이 있으면 먼저 COMMIT, cbWriteInputMode()/tmp/입력모드.psv 갱신, renderAndReload.
  1. Ctrl+Space 토글 제거keyDown의 기존 토글 분기(구 :1051~1059)를 삭제하고
위 ②의 재확인 블록으로 대체.
  1. 초기값_한글모드를 서비스별 하드코딩(메모=한글 기본/터미널=영문 기본)에서
cbIsKoreanInputSource() 단일 판정으로 통일(서비스 무관, OS가 유일한 진실).
  1. 키 처리 매트릭스 (코드 주석에도 명시, crowny-browser.m keyDown 내):
- 한국어 소스 + 호환자모(U+3131~U+3163) 수신 → 이미 조합 대상 자모(2벌식 등은 TSM 없이도 물리키가 자모 문자를 직접 냄) → injectJamo 직행, 이중 처리 금지. - 한국어 소스 + 라틴 수신(레이아웃/엣지케이스로 커밋 방식이 다른 경우) → usKeyToJamo()로 두벌식 환산 후 injectJamo. - 영어 소스 → 자모 매핑 스킵, 라틴 직행(injectKey). - 이 구조 자체는 기존 코드(라인 순서)와 동일 — 달라진 것은 한글모드가 이제 "OS가 한국어 소스인가"를 뜻한다는 점뿐.
  1. 배지 문구src/터미널앱.한선: "A · Ctrl+Space 한/영""A · 한/영=맥 한영키",
한글 모드는 "한 · 한/영=맥 한영키". 상태 파일 설명 주석도 "브라우저 한/영 토글이 기록" → "브라우저가 OS 입력소스 추종값을 기록"으로 정정.
  1. Makefilecrowny-browser.m을 링크하는 타깃(기본 LDFLAGS, crownyonly 인라인
프레임워크 목록)에 -framework Carbon 추가. standalone(별도 소스 crowny-browser-standalone.m)은 이번 작업 범위 밖 — 미변경.

검증

  • 빌드: make web(기본 CrownyBrowser) exit 0, Carbon.framework 링크 확인
(otool -L/System/Library/Frameworks/Carbon.framework/...). 경고는 기존부터 있던 무관한 1건(crownyButlerRoot unused)뿐, 신규 에러/경고 0. make public universal crownyonly 3변종도 전부 exit 0(crownyonly는 WebKit 링크 0 유지 확인 — otool grep).
  • 3곳 배치: 빌드 산출물을 스크래치 임시경로에 cp한 뒤 각 목적지로 mv(제자리 cp
금지 규칙 준수) → native/CrownyBrowser, CrownyAI.app/Contents/MacOS/CrownyBrowser, CrownyBrowser.app/Contents/MacOS/CrownyBrowser 3파일 SHA1 전부 동일: 45c6a413579da8d40a3e4943eca3f231107b8037.
  • TIS 감지 단독 헤드리스 테스트: crowny-browser.mcbIsKoreanInputSource()
로직을 그대로 복제한 소형 CLI(tis_probe.m, Cocoa+Carbon만 링크, GUI 불요)를 스크래치에 빌드·실행 — 이 세션 진행 중 실제 맥 현재 입력소스 판정:
  입력소스ID=com.apple.inputmethod.Korean.2SetKorean
  한글여부=YES
  
접두사 매칭 로직이 실제 macOS 2벌식 입력소스 ID를 정확히 한글로 판정함을 확인.
  • 터미널앱.한선 컴파일+배지: hanseonc_high 컴파일 exit 0(4604토큰, 12439큐브).
/tmp/입력모드.psv모드|영문/모드|한글로 바꿔가며 crownyc run cmd 스트림을 헤드리스로 검사 — 두 경우 모두 exit 0, 배지 TEXT 명령이 각각 A · 한/영=맥 한영키 / 한 · 한/영=맥 한영키로 정확히 렌더됨(색상도 130/125/115↔ 201/169/97로 정상 스위칭).
  • GUI 실측(맥 한영키 눌러 배지·입력 실제 전환)은 사용자 몫 — 헤드리스로는
실제 물리 키 입력 이벤트/OS 알림 파이프라인 종단간을 재현할 수 없음. 확인 방법: CrownyBrowser 앱을 열어 메모/터미널 탭에서 맥 한영키(또는 Caps Lock 설정 시)를 눌러 우상단 배지가 A↔한으로 바뀌는지, 이어서 타이핑 시 한글/영문이 실제로 맞게 들어가는지 확인.

크라우니코드 보고

  • lookup-first 조회: crownycode-learn.sh search "입력소스 한영" / "TIS 키보드"
MISS(0건, Objective-C 네이티브 감지 로직은 학습DB에 없었음).
  • 생성: TIS 판정 헬퍼 1건(cbIsKoreanInputSource) 직접 작성.
  • 학습: crownycode-learn.sh add tis입력소스한영추종 "<코드>" → 학습완료.
  • 크라우니코드: lookup HIT 0건(재사용) / MISS 2건(생성) / learn 추가 1건.
(본 작업은 기존 Objective-C 네이티브 인프라 파일 직접 수정이 지시 범위 — .한선 신규 로직이 아니라 macOS Carbon API 연동이라 한선씨 동반 대상 아님. 단 로직을 학습DB엔 패턴으로 등록해 재사용 가능하게 함.)

윈도우 대응 방법론 (조사만 — 구현은 별도 에이전트 담당)

macOS TIS의 Win32 대응:

  • 현재 IME 언어 감지: WM_INPUTLANGCHANGE 메시지(윈도우가 입력 언어 변경 시 수신,
lParam=새 HKL)를 훅해 실시간 갱신하거나, 폴링 시 GetKeyboardLayout(threadId)로 현재 HKL을 얻고 LOWORD(hkl)(Language Identifier)을 MAKELANGID(LANG_KOREAN, SUBLANG_KOREAN)(0x0412)과 비교해 한국어 여부 판정. 단, 같은 "Korean" 키보드 레이아웃 안에서 IME 켬/끔(한/영 전환)이 별도 상태로 존재하는 경우가 많아 — 이 경우 ImmGetContext(hwnd) + ImmGetConversionStatus()로 IME conversion mode(한글 입력 on/off)를 추가로 확인해야 정확하다(레이아웃=언어, IME conversion=한/영 실제 스위치, 둘이 분리된 개념).
  • 조합은 OS IME에 맡기지 않고 크라우니 조합기 사용: WM_IME_COMPOSITION/
WM_IME_CHAR를 받으면 이미 OS가 조합을 끝낸 결과라 크라우니 조합기와 이중 처리 충돌이 남. macOS와 동일한 원칙(OS 조합 비의존)을 지키려면 ImmAssociateContext(hwnd, NULL)로 해당 윈도우의 IME 컨텍스트를 분리해 원시 WM_KEYDOWN(VK 코드)이 그대로 넘어오게 한 뒤, usKeyToJamo()와 동일한 VK→두벌식 자모 매핑 테이블(예: VK_R→ㄱ, VK_S→ㄴ 등, US QWERTY 물리 배치 기준)로 크라우니 조합기(JAMO/COMMIT/BS)에 그대로 이벤트를 넘기면 macOS 경로와 대칭 구조가 된다.
  • 결론: 감지=WM_INPUTLANGCHANGE+GetKeyboardLayout(+필요시 ImmGetConversionStatus),
조합=ImmAssociateContext(hwnd,NULL)로 OS IME 비활성화 후 VK 매핑 경유 크라우니 조합기 — macOS TIS+자체조합 구조와 1:1 대응.

관련 파일

  • /Users/ef/CrownyBrowser/native/crowny-browser.mcbIsKoreanInputSource(),
initWithService:(초기값+알림 구독), onInputSourceChanged:, dealloc, keyDown:(토글 제거+재확인+매트릭스 주석) 수정.
  • /Users/ef/CrownyBrowser/native/MakefileLDFLAGS / crownyonly 타깃에
-framework Carbon 추가.
  • /Users/ef/CrownyBrowser/src/터미널앱.한선 — 배지 문구·주석 정정.
  • /Users/ef/CrownyBrowser/native/CrownyBrowser,
/Users/ef/CrownyBrowser/CrownyAI.app/Contents/MacOS/CrownyBrowser, /Users/ef/CrownyBrowser/CrownyBrowser.app/Contents/MacOS/CrownyBrowser — 재빌드 배치(SHA1 45c6a413579da8d40a3e4943eca3f231107b8037 동일).

잔여 이슈

  • GUI 실측(실제 맥 한영키 전환 시 배지·입력 변화)은 미실증 — 사용자 확인 필요.
  • 크라우니앱뷰어.m(/Users/ef/CrownyBrowser/native/)은 같은 Ctrl+Space 토글 패턴을
별도로 갖고 있음(라인 142/169/301 부근, grep 확인) — 이번 작업 범위(crowny-browser.m 한정)에서 제외했으나, 같은 macOS 단축키 충돌 함정을 안고 있어 후속 세션에서 동일 패턴 적용 검토 필요.
  • crowny-browser-standalone.m(standalone 빌드 타깃 소스)도 별도 파일이라 이번
수정 미반영 — 필요 시 동일 패턴 이식.