AI 키보드가 품절돼 생긴 일

작성자

카테고리:

시작은 키보드였습니다

Codex Micro 매크로패드. 아래쪽 가장 큰 키에 마이크 아이콘이 있습니다.
이미지 출처: PCMag, “OpenAI Is Selling a $230 Keyboard Designed for Its Codex Agent”

Codex Micro라는 키보드를 봤습니다. Work Louder와 OpenAI가 만든 230달러짜리 매크로패드인데, 키마다 색이 바뀌며 상태를 알려주고 — 파랑이면 생각 중, 초록이면 완료, 노랑이면 내 차례 — 아래쪽 가장 큰 자리에 마이크 키가 박혀 있었습니다. 사고 싶었습니다. 이미 품절이었습니다.

못 사게 되니 오히려 생각을 하게 됐습니다. 나는 Claude Code를 쓸 때 무엇으로 지시를 내리고 있나. 세어보니 거의 전부 타이핑이었습니다. 그리고 지시가 길어질수록 느려졌습니다. 머릿속에 있는 걸 다 적기 전에 앞부분을 다듬고 있거나, 귀찮아서 짧게 줄이고 있었습니다.

긴 지시에는 말이 더 맞겠다는 판단이 여기서 나왔습니다. 저 키보드에 마이크 키가 있는 것도 우연은 아닐 겁니다.

키보드는 못 샀으니 소프트웨어로 만들기로 했습니다.

만들려던 것

마이크에 대고 말하면 그대로 받아적어서, 지금 열려 있는 Claude Code 세션에 넣어주는 상주 스크립트입니다. “엔터”, “지워” 같은 예약어는 텍스트 대신 키 입력으로 처리합니다.

받아적는 건 로컬에서 돌립니다. mlx-whisper의 large-v3-turbo를 쓰고, 그 앞에 faster-whisper의 VAD를 세워 무음 구간을 걸러냅니다. 조용한 구간을 whisper에 그냥 넘기면 하지도 않은 말을 지어내기 때문입니다.

반대 방향도 붙였습니다. Claude의 대답은 macOS say로 읽어줍니다. 화면을 안 보고도 진행 상황을 알 수 있습니다.

시작할 때 몰랐던 것

상시 대기가 이렇게 어려운 줄 몰랐습니다.

핫키를 누르고 말하는 방식으로 먼저 만들었습니다. 잘 돌아가니 욕심이 났습니다. 손도 안 대고 “클로드” 한마디로 깨어나면 더 좋지 않겠나. 시리도 하고 알렉사도 하는데.

며칠, 어디까지

하루입니다. 설계 문서를 커밋한 게 7월 24일 오후, 마지막 커밋이 25일 새벽 0시 50분. 그 사이 23개 커밋이었습니다.

하루로 끝난 데는 이유가 있습니다. 전에 Vibe-Chat을 만들면서 STT와 TTS를 이미 한 번씩 공부해뒀습니다. whisper가 무음 구간에서 “감사합니다” 같은 하지도 않은 말을 지어낸다는 것도 그때 겪었고, 앞에 VAD를 세워 막아야 한다는 것도 그때 알았습니다. 이번엔 그 부분을 그대로 가져다 썼습니다. 처음부터 만든 게 아니라 절반은 재고에서 꺼낸 셈입니다.

그리고 그날 밤 이걸로 실제로 일했습니다. 실행 로그가 201줄 남아 있습니다.

21:23:44 ● 녹음중… (말이 끝나면 자동 종료)
21:23:46 ⏳ 변환중…
21:23:47 ✓ 키 입력: esc_esc
21:23:47 ● 녹음중… (말이 끝나면 자동 종료)
21:23:51 ⏳ 변환중…
21:23:51 ✓ "응, 좋아졌지?" 주입됨

되돌린 것

웨이크 워드를 만들었고, 하루 만에 지웠습니다.

fc6d1c3  feat: 웨이크 워드 '클로드' 상시 대기 모드
9569f74  revert: 웨이크 워드 제거 — 핫키+VAD 자동 종료로 복귀

이유는 정확도였습니다. “클로드”라고 불렀는데 안 깨어나거나, 부른 적 없는데 깨어났습니다. 둘 다 드물게 일어나는데, 드물게 일어나는 게 더 나빴습니다. 언제 틀릴지 모르니 매번 신경을 쓰게 됩니다. 편하려고 만든 기능이 신경 쓸 거리를 하나 더 늘린 셈이었습니다.

핫키는 그런 게 없습니다. 누르면 듣고, 안 누르면 안 듣습니다. 여기에 무음 1.5초면 알아서 끊는 VAD를 붙이니, 결국 손이 가는 건 시작할 때 한 번뿐이었습니다. 웨이크 워드로 아끼려던 게 딱 그 한 번이었습니다.

되돌리는 커밋을 쓰면서 든 생각은, 이걸 만들어보지 않았으면 몰랐겠다는 것이었습니다. 웨이크 워드가 어렵다는 얘기는 어디서든 읽을 수 있습니다. 그런데 “드물게 틀리는 게 자주 틀리는 것보다 성가시다”는 건 읽어서는 안 와닿았습니다. 내가 만든 걸 내가 쓰다가 짜증이 나야 알게 되는 종류입니다.

책상을 떠났습니다

여기까지 와도 물리 버튼이 없었습니다. 노트북 키를 눌러야 하니 결국 책상 앞이어야 했습니다. 그러니까 처음에 못 산 그 키보드가 다시 떠올랐습니다.

8BitDo Micro 블루투스 게임패드

집에 8BitDo Micro가 있었습니다. 손가락만 한 블루투스 게임패드인데, 뒷면 스위치를 키보드 모드로 놓으면 별도 드라이버 없이 macOS에서 키보드로 잡힙니다. 값은 230달러의 10분의 1 정도입니다.

여기서 한 번 걸렸습니다. 키보드 모드의 버튼은 원하는 키로 바꿀 수 있는 게 아니라, 버튼마다 정해진 문자키를 보냅니다. L 버튼은 k를 보냅니다. 푸시투토크 키로 쓰기엔 곤란합니다. 누를 때마다 화면에 k가 찍힐 테니까요.

그래서 Karabiner-Elements를 한 겹 끼웠습니다. 패드가 보내는 kF13으로 바꿉니다. F13은 화면에 아무것도 안 찍히고 macOS 기본 기능도 없어서 푸시투토크에 안전합니다.

여기서 꼭 필요한 게 기기 식별자 조건입니다. 이걸 빼면 변환이 진짜 키보드에까지 적용돼서, 타이핑하다 k를 누를 때마다 녹음이 시작됩니다.

vendor_id: 11720, product_id: 36897

나머지 버튼은 필요해서 걸었습니다. Claude Code는 말만 주고받다 끝나지 않습니다. 중간중간 선택지를 띄웁니다 — 이 편집을 허용할지, 어느 쪽으로 갈지. 방향키로 고르고 Enter로 정하고, 아니다 싶으면 ESC로 이전 메뉴로 돌아갑니다. 짧고 자주 오는 순간이라 말로 하기엔 오히려 번거롭습니다.

그래서 D패드에 방향키, Y에 Enter, X에 ESC를 걸었습니다. 이제 한 손에 쥐고 대화를 끝까지 끌고 갈 수 있습니다.

D패드에서 한 번 더 걸렸습니다. 패드를 세로로 쥐니 버튼 라벨과 실제 방향이 안 맞는데, 회전을 계산해서 맞추려다 틀렸습니다. 좌우가 뒤집힌 배치였습니다. 결국 EventViewer를 열고 네 방향을 하나씩 눌러 실측해서 넣었습니다.

스크립트에서 바꾼 건 이 줄 하나입니다.

HOTKEY = keyboard.Key.f13

이제 AirPods를 끼고 게임패드를 쥔 채로 책상을 떠날 수 있습니다. 누르고, 말하고, 놓으면 됩니다.

여기서 좀 이상한 일이 생겼습니다. 못 사서 아쉬웠던 그 키보드는 애초에 이걸 못 합니다. 매크로패드는 책상에 놓여 있어야 하니까요. 대체품을 만들다 보니 원본이 못 하는 걸 하게 됐습니다.

남은 것

한국어 짧은 명령어는 여전히 자주 틀립니다. “지워”가 “주워”로 찍힙니다. 오인식 단어장과 자모 유사도 매칭을 붙여 급한 불은 껐지만, 근본적으로 해결한 건 아닙니다.

그리고 오늘 이런 게 있었습니다. 녹음을 시작하자마자 “무음”으로 끝나버리는 일이 생겼습니다. 원인은 녹음 시작을 알리는 그 “띵” 소리였습니다. 스피커에서 난 소리가 마이크로 새어들어가고, VAD가 그걸 사람 말로 착각하고, 제가 입을 떼기도 전에 “말이 끝났다”고 판단해 녹음을 닫아버린 겁니다. 편하라고 붙인 소리 알림이 자기 귀를 막고 있었습니다.

감시 시작 시점을 조금 뒤로 미뤄서 막아뒀지만, 헤드셋을 안 쓰면 언제든 다시 나올 수 있습니다.