추가 메뉴

macOS 기본 한글 입력기도 홈 어드밴티지가 많지는 않나보군요
DINKIssTyle

Lv.1 DINKIssTyle (61.♡.73.102)

2026년 5월 8일 PM 02:34

조회 399 공감 0

DKST macOS용 한글입력기 피드백들이 들어오면서..

혼자 신이나며 쓸때 몰랐던 문제점들을 제보받았습니다.

그래서 애플은 이 상황에 어떻게 대처하나 구경하다보니...

확인해보니 우리 상황과 꽤 닮은 지점이 있습니다. 핵심은 Apple 기본 한글 입력기도 “항상 marked text”가 아니라, 기본은 직접 인라인 입력을 시도하고 실패하면 marked text/inline fallback 쪽으로 전환하는 구조라는 점입니다.

제가 본 포인트:

- IMKActiveCompositionController가 따로 있음

Apple 쪽은 KIMController가 바로 insertTextsetMarkedText를 처리하기보다, IMKTextDocumentTextInputAdaptorIMKTextInputTextDocumentAdaptor를 사이에 두고 입력 클라이언트를 감쌉니다. 우리 코드보다 클라이언트 상태 추적 계층이 하나 더 있습니다.

- 활성화 시점에 Safari 특수 문자열은 안 보임

activateServer: 근처에서 bundle id를 확인하는데, 명시적으로 보이는 건 com.apple.Terminal입니다. Terminal일 때 alwaysShowsComposingTextAsMarkedText 플래그를 다르게 넘기는 흔적이 있습니다. Safari/WebKit을 marked text로 강제하는 흔적은 이 파일 기준으로는 못 찾았습니다.

- 기본값은 “inline/direct 입력 유지”에 가까움

updateShouldForceInlineshouldForceInline = YES, showsInline = shouldForceInline처럼 설정합니다. 즉 Apple 기본 입력기도 기본적으로 inline을 강하게 선호합니다.

- 실패 감지 후 fallback이 있음

insertNewText:updateContentsWithoutInline:에서 insertText:replacementRange:selectedRange가 예상 위치와 다르면 setShouldForceInline:YES, setShowsInline:YES로 돌리고, bundle id를 modelessUnsupportedApps에 추가합니다. 우리 코드의 “직접 입력 후 커서 위치가 이상하면 marked text 강제”와 매우 비슷한 패턴입니다.

- selectedRangeattributedSubstringFromRange:는 필요할 때만 호출

Apple도 한자 변환이나 inline 검증에서는 호출합니다. 다만 활성화 직후 무조건 정책 판별용으로 selectedRange를 두드리는 구조라기보다, adaptor 구성 후 실제 입력/검증 경로에서 호출하는 쪽에 가깝습니다.

그래서 결론은 이렇습니다: 지금 우리가 마지막에 고친 방향, 즉 “Safari는 marked text로 강제하지 않고 직접 입력 유지, 활성화 직후 eager sync만 줄이기”가 Apple 쪽 구조와 더 가깝습니다. 다만 Apple처럼 더 안정적으로 가려면 다음 단계는 앱별 고정 목록보다 “직접 입력 시도 → 커서/삽입 결과 검증 → 실패한 bundle만 fallback 기록” 구조를 조금 더 정교하게 만드는 쪽이 좋아 보입니다.

Q. 애플 한글 입력기가 그러면 언딘가에 실패 목록을 저장하고 있습니까?

네. 다만 “어딘가에 저장”이라기보다는 프로세스 메모리 안의 static set에 bundle id를 추가하는 형태로 보입니다. 영구 저장 파일이나 defaults에 기록하는 흔적은 이 범위에서는 못 봤습니다.

근거는 [IMKActiveCompositionController modelessUnsupportedApps]입니다. 이 메서드가 static NSMutableSet을 만들고 반환합니다.

그 set에 추가하는 흐름이 두 군데 보입니다.

  • insertNewText:에서 직접 삽입 후 selectedRange가 예상 위치와 다르면 setShouldForceInline:YES, setShowsInline:YES를 하고, bundleIdentifier를 가져와 modelessUnsupportedApps에 addObject: 합니다.

  • updateContentsWithoutInline:에서도 비슷하게 내용/커서 검증이 어긋나면 bundle id를 같은 set에 추가합니다.

그래서 제가 말한 “실패한 bundle만 fallback 기록”은 정확히는:

직접 인라인 입력을 시도했는데 결과 검증이 실패한 앱의 bundle id를 런타임 set에 넣고, 이후 inline 강제/모델리스 비지원 앱처럼 취급하는 방식

입니다.

우리 코드의 _forcedMarkedTextBundleIDs와 개념적으로 비슷하지만, Apple 쪽은 이름이 modelessUnsupportedApps이고, 영구 설정이 아니라 입력기 프로세스 생명주기 동안 유지되는 캐시처럼 보입니다.


여기도 열심히 예외 추가하고, 우회하고.. 그러나 봅니다.

구단주가 적극적으로 지원해줄 생각이 없으면... 혼자 뛰어야죠 ㄷㄷ

근데 만약 정말 매 프로세서 켜질때마다 메모리에 실패를 기록한다면,

다음번 부팅하고 나서, 부팅하고 처음 켠 앱의 첫 조합에 자소 풀리며 실패하는 건 매우 지극히 당연한 문제네요.

부팅 되어 있는 상태에서도 입력기 프로세서가 강종 당해서 다시 켜져도 마찬가지고요??

DKST 한글입력기 사용자 분들 중 코멧, 사파리 쓰는 분들을 위한 임시 베타 릴리즈를 준비했습니다.

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/DINKIssTyle/DINKIssTyle-IME-macOS/main/install-beta.sh)"

댓글 (2)

  • 날씨는어때

    날씨는어때 Lv.1

    05.08 · 149.♡.254.10

    아유.. 정말 수고가 많으십니다~
    감사합니다!!

    굳이 자동으로 처리를 전환해서 복잡해지는것보다 차라리 지금처럼 앱별 고정 목록을 사용하는게 더 안정적일지도 모르겠습니다.

    아무튼 수고가 정말 많으십니다!

  • DINKIssTyle

    DINKIssTyle Lv.1 작성자

    05.08 · 61.♡.73.102

    아... 인라인을 포기해야 하는것인지.. 이렇게 수정하고 Adobe 쪽에 문제가 생기네요 ㅂㄷㅂㄷ

댓글을 작성하려면 이 필요합니다.