본문 바로가기
C.W.K.
Stream
Lesson 01 of 05 · published

타깃을 먼저 스냅샷해

~11 min · target-capture, accessibility, wrong-app-guard, focus

Level 0불씨 없음
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"단어를 손에 쥘 즈음이면 커서가 옮겨갔을 수 있어. 그러니 어디 있었는지 기억해 둬."

멈춤 전에 잡아

삽입이 하는 첫 일은 단어가 한 글자도 전사되기 전에 벌어져. 단축키가 눌리는 순간, 오버레이가 뜨기 전에, Firekeeper 가 타깃을 스냅샷해. 최전면 앱의 번들 id 와 프로세스 id, 포커스된 접근성 요소, 선택된 텍스트와 범위, 그리고 타깃이 뭔지 분류한 값까지. 브라우저인지 에디터인지 터미널인지 채팅인지 이메일인지 비밀번호 필드인지, 아니면 모르겠는지. 오버레이는 일부러 비활성화(non-activating) 로 만들었어. 그래야 오버레이를 띄워도 타이핑하려던 필드에서 포커스를 안 빼앗아.

스냅샷이 중요한 이유

단축키를 누른 시점과 삽입 시점 사이엔 초 단위 시간이 흘러. STT 가 돌고 정리가 도니까. 그 창에서 포커스는 얼마든지 흘러갈 수 있어. 다른 창을 보거나, 앱이 다이얼로그를 띄우거나, 알림이 포커스를 채가거나. 삽입이 '지금 최전면인 아무 데나' 타이핑해 버리면 받아쓴 내용이 완전히 엉뚱한 앱에 떨어질 수 있어. 최악은 올릴 생각도 없던 채팅에 그대로 올라가는 거고. 스냅샷이 그래서 고정된 타깃이야. 포커스가 흘러간 곳이 아니라, 말하기 시작했을 때 있던 그 앱에 넣는 거지.

단축키 누름  -> 스냅샷 { app, pid, element, selection, category }
  ... STT ... 정리 ...   (여기서 포커스 흘러갈 수 있음!)
삽입         -> 최전면 앱이 아직 snapshot.app 인가?
                 예   -> 잡은 타깃에 삽입
                 아니오 -> 엉뚱한 앱에 타이핑 말고; 클립보드 + 알림

엉뚱한 앱 가드

가드 자체는 단순한 비교야. 결과가 엄격할 뿐이지. 삽입할 때 최전면 앱이 아직 스냅샷과 맞는지 확인해. 바뀌었으면 Firekeeper 는 붙여넣기를 거부하고, 대신 텍스트를 클립보드에 복사한 다음 알려줘. 규칙은 하나야. 맞는 앱에 넣거나, 아예 안 넣거나. 엉뚱한 앱에 타이핑하는 게 아예 안 하는 것보다 나빠. 손으로 붙여넣는 거야 언제든 되지만 이미 보낸 메시지는 못 무르니까. 이 비교 하나가 받아쓰기 앱이 저지를 수 있는 제일 소름 끼치는 실패를 막아.

동작은 찾아낸 타깃이 아니라 잡아 둔 타깃에 묶어. 의도한 시점과 효과가 나는 시점 사이에 시간이 뜨는 연산이라면, 의도한 시점에 타깃을 기억해 두고 효과가 날 때 그게 맞는지 확인해야 해. 효과가 나는 시점의 지금 상태는 네가 실제로 의도했던 상태를 대신할 수 없어. 라이브 앱에 텍스트를 올리는 것처럼 효과가 되돌릴 수 없는 거라면 더더욱.
보안 텍스트 필드는 절대 읽지 마. 스냅샷이 하는 일 중 하나가 포커스된 요소가 보안 필드나 비밀번호 필드인지 알아내는 거야. 맞으면 Firekeeper 는 거기서 맥락을 안 읽고 출입 금지로 다뤄. 비밀번호 필드를 들여다보는 보이스 도구는 그냥 재앙이야. 그래서 그 경계를 제일 먼저 세우는 자리가 캡처 단계인 거고.

Code

단축키를 누르는 순간 잡는 타깃 스냅샷·swift
struct TargetSnapshot {
    let appBundleID: String
    let pid: pid_t
    let focusedElement: AXUIElement?
    let selection: String?
    let category: TargetCategory   // browser / editor / terminal / chat / secure / unknown
    let isSecureField: Bool
}

// 삽입 시점에, 세상이 우리 밑에서 안 바뀌었는지 검증.
func canInsert(into snapshot: TargetSnapshot) -> Bool {
    guard let front = NSWorkspace.shared.frontmostApplication else { return false }
    return front.bundleIdentifier == snapshot.appBundleID   // 엉뚱-앱 가드
}
// 이게 false 면: 클립보드 + 알림, 엉뚱한 앱에 절대 붙여넣기 안 함.

External links

Exercise

시작한 시점과 효과가 나는 시점 사이에 간격이 있는 연산을 하나 떠올려봐. 예약 전송이나 지연 붙여넣기, 백그라운드 업로드 같은 거. 효과가 날 때 '시작할 때 잡아 둔 타깃' 대신 '지금 타깃' 을 쓰면 뭐가 잘못될까? 그걸 막을 가드를 그려봐.
Hint
실패는 늘 같은 모양이야. 간격 동안 세상이 바뀌었고, 효과가 엉뚱한 데 떨어졌어. 가드도 늘 같은 모양이고. 의도한 타깃을 미리 잡아 두고, 효과가 날 때 지금 타깃이랑 비교해. 다르면 엉뚱한 타깃에 손대는 대신 거부하고 안전한 폴백을 꺼내 보여줘.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.