← 노하우 목록

FROM THE WORKSHOP / 노하우

자비스 제작기 3 — 네스트로 시작하고, Mac으로 받아쓰고, 텔레그램에서 확인하기

보이스 스타토로 시작하는 단계별 음성 입력과 시고토 오와리의 확인형 종료를 연결했다. 새 대화 첫 입력 누락, 카드 누락, /clear 이후 출처 미확인을 각각 고치고 실제 표시까지 확인한 기록.

강대종 · 마이너스베타스튜디오

자비스 제작기 3 — 네스트로 시작하고, Mac으로 받아쓰고, 텔레그램에서 확인하기

2026-09-26 · 9월 25일 작업과 26일 새벽 최종 확인 기록

“자비스, 헤르메스 코덱스에 입력해 줘.” 짧아 보이는 이 문장에는 호출, 기능 선택, 프로그램 선택, 컴퓨터 선택이 한꺼번에 들어 있다. 실제로는 고유명사인 ‘헤르메스’부터 자주 틀렸다. 입력이 터미널에 도착했는데 텔레그램 카드가 없어 실패처럼 보이는 경우도 있었고, 카드가 생긴 뒤에는 누가 전달했는지 ‘미확인’으로 표시됐다.

이번에는 Google Nest를 시작 버튼으로 쓰고, 이후 대화와 받아쓰기는 Mac 마이크가 담당하도록 연결했다. 작업을 시작하고 끝내는 일본어 루틴도 같은 Matter 연결로 기존 자비스 스크립트에 이어 붙였다. 마지막 확인은 코드나 배포 로그가 아니라 사용자가 실제로 말한 뒤 본 텔레그램 카드였다.

이전 제작기: 호출·종료 확인·WOL · 자비스 공개 소스

1. 최종 사용법: 네스트는 시작, Mac은 선택과 본문

하고 싶은 일네스트에 말할 문구이어지는 동작
음성으로 세션에 입력“오케이 구글, 보이스 스타토” — ボイススタート자비스 질문에 프로그램 → 컴퓨터 → 본문 → “엔터” 순서로 답한다
작업 시작“오케이 구글, 시고토 스타토” — しごとスタート기존 ‘일하자’ 스크립트를 호출한다
작업 종료“오케이 구글, 시고토 오와리” — しごとおわり종료 확인 질문을 듣고 Mac 마이크에 “하이” — はい라고 답한다

이 문구는 이 환경의 Google Home 루틴에 등록한 시작 조건이다. 모든 Google Home에서 기본 제공하는 명령은 아니다.

음성 입력의 실제 순서는 다음과 같다.

  1. 네스트에 “오케이 구글, 보이스 스타토.”
  2. 자비스: “어디로 연결할까요?” → “코덱스.”
  3. 자비스: “어떤 노드인가요?” → “헤르메스.” 별칭 “노트북”도 같은 대상으로 연결한다.
  4. 자비스: “말씀하세요.” → 입력할 본문을 말한다.
  5. 마지막에 “엔터.” → 누적한 본문을 선택한 기존 세션으로 한 번 전달한다.

‘아테나’와 ‘헤르메스’는 컴퓨터 이름이고 ‘코덱스’는 프로그램이다. 이 둘을 순서대로 묻게 하니 긴 조합을 한 번에 알아듣게 만들 필요가 줄었다. 엔진 선택과 노드 선택, 본문 받아쓰기 상태를 구분하는 것이 핵심이다. “노트북”은 선택 단계의 별칭이며, 본문 안의 같은 단어까지 기기 명령으로 바꾸는 방식이 아니다.

여기서 네스트 마이크가 자유 발화 본문을 스트리밍하는 것은 아니다. 네스트는 등록한 문구를 알아듣고 Matter 명령을 보낸다. 이후 선택·본문·전송어는 아테나의 Mac 마이크로 받는다. 네스트가 방 건너편의 시작 요청을 받아도, 이어서 말할 때는 실제 받아쓰는 마이크가 들을 수 있어야 한다.

2. Matter를 기존 스크립트의 입구로 사용했다

연결은 다음과 같다.

네스트 → Google Home 루틴 → 페어링된 Matter 기기
                                  ↓
                           로컬 자비스 제어 경로
                                  ↓
                    선택 질문 / 음성 입력 / 기존 작업 스크립트

Google Home에는 작업용 기기와 음성 입력용 기기를 구분해 등록했다. 짧은 기기 제어를 로컬 자비스 동작으로 연결하되, 말한 내용을 셸 명령으로 조립하거나 공개 HTTP 명령 주소를 열지는 않았다. 페어링 정보와 기기별 설정은 개인 환경에 둔다.

작업 시작은 Matter ON을 기존 ‘일하자’ 함수에 연결했다. 요청 뒤 스위치 표시를 OFF로 되돌리는 내부 처리에는 종료 동작을 붙이지 않는다. 컨트롤러에서 들어온 명시적인 OFF만 종료 확인을 요청한다. 중복 ON, 빠른 재호출, 재시작 때의 초기 상태 변화도 실행 요청과 구분한다.

등록 과정에서는 Google Home이 실제로 기기를 표시하고 제어할 수 있는지까지 확인해야 한다. QR 화면을 열었거나 루틴의 저장 버튼을 눌렀다는 사실만으로 연결됐다고 할 수 없다. 이번 등록은 QR 대신 수동 페어링 코드를 복사해 Google Home의 코드 입력란에 넣는 방법도 사용할 수 있었다. 페어링 코드는 공개 문서나 로그에 남기지 않는다.

처음 고른 “메모 스타토”는 원하는 루틴으로 이어지지 않았다. 네스트가 다른 기능의 응답을 했고, 최종적으로 “보이스 스타토”로 바꾼 뒤 실제 연결·입력이 확인됐다. 모든 사용자에게 같은 충돌이 생긴다고 단정할 수는 없지만, 호출어를 고를 때 흔한 내장 기능 이름과 겹치는지 확인할 이유가 됐다.

3. “시고토 오와리”는 종료 확인 질문을 연다

종료는 시작과 다르게 설계했다. Google Home의 작업 종료 루틴이 Matter OFF를 보내더라도 바로 PC를 끄지 않는다. 로컬 자비스에 종료 확인 질문을 요청한다.

  1. 네스트에 “오케이 구글, 시고토 오와리.”
  2. 자비스의 **“오늘의 작전을 종료할까요?”**를 끝까지 듣는다.
  3. 질문 재생이 성공적으로 끝난 뒤 **12초 안에 Mac 마이크로 “하이(はい)”**라고 답한다.
  4. 자비스가 **“작전 종료 절차를 시작합니다.”**라고 안내하고 기존 종료 스크립트를 호출한다.

다른 답변과 시간 초과는 취소다. 질문 전에 녹음된 말, 질문 재생 실패, 재시작, 단독으로 말한 “하이”, 같은 OFF 요청의 반복은 종료 승인이 되지 않는다. 승인 상태는 한 번만 소비한다. 일본어 음성 인식은 이 확인 대기 상태에 한정하고 기존 한국어 확인 경로는 유지했다.

사용자는 “오와리는 잘됨”이라고 확인했다. 실행 기록에서는 두 Mac의 화면 밝기 0을 확인했다. PC 종료 요청의 일부 결과는 unverified였으므로, 모든 PC가 실제로 꺼졌다고 기록하지 않았다. 작업 시작도 화면 밝기는 확인했지만 WOL 패킷 전송과 실제 PC 부팅 완료는 구분했다. 루틴 연결 성공과 모든 장치의 물리 상태 성공은 서로 다른 확인 항목이다.

4. ‘입력이 안 됨’은 세 가지 경계에서 따로 확인해야 했다

음성 인식 결과가 생겼다는 것, 세션에 본문이 도착했다는 것, 텔레그램 카드가 표시됐다는 것은 각각 다른 사건이다.

증상확인한 원인수정 방향
새 대화에 첫 본문을 넣지 못함입력 전에 세션 기록 파일이 반드시 있어야 한다고 가정정상 입력 조건 확인 후 한 번 전달하고 새 기록 파일에서 수신 확인
본문과 답변은 있는데 받은 입력 카드가 없음새 기록 파일을 끝에서 따라 읽기 시작해 이미 적힌 첫 사용자 이벤트를 건너뜀출처가 확인된 첫 음성 입력만 복구하고 중복 카드 방지
카드는 생기지만 ‘지시자/전달 프로그램 미확인’/clear 직후 출처 기록은 이전 대화 파일, 본문은 새 대화 파일에 연결됨같은 실행 세션의 실제 새 입력 이벤트를 확인해 출처 기록 재연결

처음에는 ‘카드가 빠져서 입력이 안 된 것처럼 보였다’고 설명했다. 그런데 사용자는 “터미널 입력도 텔레그램으로 보내는 기능이 이미 있지 않느냐”고 지적했다. 맞는 지적이었다. 기존 터미널 입력 미러링 기능이 없는 문제가 아니라 새 대화의 첫 입력을 뒤늦게 발견하는 경로가 일반 입력 처리 경로를 거치지 않은 버그였다.

그래서 기존 기능을 새로 만들었다고 설명할 것이 아니라, 어느 예외 경로에서 빠졌는지 확인해야 했다. 당시 실제 세션에는 “입력 확인,”이 들어 있었고 답변도 생성됐다. 전송어 “엔터”는 본문에서 빠졌으며, 쉼표는 음성 인식 결과에 포함돼 있었다.

5. 출처 정보는 본문 밖에서 전달한다

사용자가 말한 본문에 “네스트에서 온 승인입니다” 같은 문구를 덧붙이지 않았다. 별도의 로컬 수신 기록에 다음 정보를 보관했다.

  • 시작 경로: 네스트의 Google Home·Matter인지, 직접 마이크 호출인지
  • 받아쓴 컴퓨터와 전달 프로그램
  • 대상 엔진·컴퓨터, 실제 세션 파일과 입력 이벤트 위치
  • 본문 해시, 생성 시각, 같은 실행 세션을 확인하기 위한 정보

본문 전체를 출처 기록에 중복 보관하지 않고, 해시로 실제 수신 본문과 비교한다. 이 정보는 표시를 위한 전달 경로다. 화자의 신원을 인증하거나 명령의 실행 권한을 부여하는 근거로 사용하지 않는다.

/clear 직후에는 이전 대화 파일이 잠시 열린 상태로 남을 수 있었다. 본문을 보내기 전에 발견한 파일과 실제 입력이 기록된 파일이 달라졌고, 이전 파일의 바이트 위치를 새 파일과 비교하면서 매칭까지 실패했다.

수정 후에는 아직 매칭되지 않은 기록에 한해 같은 실행 세션의 새 파일을 확인한다. 전송 이후의 이벤트인지, 본문 해시가 정확히 같은지, 유효 시간 안인지 확인하고 실제 새 이벤트 위치에 연결한다. 이미 매칭된 기록을 다른 입력으로 옮기거나, 시간이 지난 기록을 살리거나, 과거의 같은 문장을 새 음성 입력으로 간주하지 않는다. 애매한 전송 결과를 복구한다며 본문을 다시 보내지도 않는다.

최종 카드는 다음처럼 표시됐다.

네스트로 시작 · 아테나 음성 입력 · 자비스 전달 → 헤르메스 코덱스

직접 자비스를 불렀다면 ‘네스트로 시작’은 붙지 않는다. 출처를 확인할 수 없는 일반 터미널 입력은 미확인 표시를 유지한다. 모든 터미널 입력을 자비스 입력으로 분류해서 화면만 고치는 방식은 피했다.

6. 배포 완료와 실제 수신 확인을 나눴다

수정본은 격리된 작업 공간에서 검증하고 PR을 병합한 뒤 실행 환경에 적용했다. 실행 중인 저장소 전체를 덮어쓰지 않고 필요한 변경만 백업 후 반영했다. 브릿지 교체 때는 코덱스 대화 자체를 재시작하지 않았다.

  • 브릿지 프로세스가 새 코드로 바뀌었는지 확인
  • 기존 코덱스 프로세스와 대화 파일이 유지됐는지 확인
  • 대기 중인 입력 큐와 읽기 위치가 보존됐는지 확인
  • 실제 설치 파일과 검증한 파일이 같은지 확인

자비스 관련 전체 검사는 해당 수정 단계에서 192개가 통과했다. 마지막 출처 재연결 수정은 두 노드의 실제 브릿지 환경에서 관련 17개 검사가 각각 통과했다. 실제 실패 기록을 읽기 전용으로 대조하고 임시 출처 기록에만 수정된 매칭을 실행해, 본문을 재전송하지 않고도 원인을 재현했다.

그 뒤에도 완료로 닫지 않았다. 사용자가 /clear → 네스트 호출 → 코덱스 → 헤르메스 → 본문 → 엔터를 다시 실행하고 출처 카드가 “정상 표시됨”이라고 확인한 뒤 종결했다. 이 확인은 해당 경로의 성공이지 모든 기기·프로그램 조합이나 장기간 인식률을 보장하는 측정은 아니다.

다시 같은 증상을 만났을 때

  1. 네스트의 응답 내용과 Matter 요청 접수를 확인한다. 호출어 문제와 로컬 수신 문제를 구분한다.
  2. 실제 선택·본문을 받는 마이크가 어느 기기인지 확인한다.
  3. 인식된 본문, 수신 세션의 사용자 이벤트, 텔레그램 카드를 차례로 대조한다.
  4. 첫 입력이나 /clear 뒤라면 새 기록 파일 생성과 이전 파일 잔존 여부를 먼저 본다.
  5. 본문이 이미 도착했다면 재전송하지 않고 표시 경로를 복구한다.
  6. 테스트 통과·설치·세션 보존·사용자 화면 확인을 각각 기록한다.

호출 문구는 짧게, 선택은 단계별로, 본문은 그대로 전달한다. 사용자가 보는 마지막 카드까지 확인해야 “입력됐다”는 말이 실제 경험과 일치한다.

기록은 다음 시작이 됩니다.노하우 더 읽기 ↗이 작업장의 제품 ↗
작업장 전체 페이지 목적에 맞는 페이지 찾기