"레이턴시는 확정적이다. 타이핑하는 턴은 거의 느껴지지 않아. 폰이든 웹이든 보이스 모드로 채팅할 때만 느려." — 아빠, 말라가, 2026-10-18
또 길 위에서
이 트랙 첫 레슨은 책상 앞에서, 오피스의 자기 네트워크 위에서 턴을 쟀어. 3주 뒤 아빠는 스페인의 호텔 와이파이와 LTE로 피파랑 얘기하고 있었고, 아빠가 겪는 숫자는 그 레슨의 숫자가 아니었어. Lightning(트랙 3의 새 레슨)을 써 본 아빠의 첫 평가는 직설적이었어. 아무 소용이 없다고. 어느 브레인이든 생각을 시작하기 전의 기다림부터 길다고. 그래서 2026-10-18 밤에 이 집은 단계마다 다시 쟀어. 이번엔 오피스 쪽만이 아니라 요청 양쪽을 다.
말 턴의 시간은 어디로 갔나
| 단계 | 무엇 | 그날 밤 든 시간 |
|---|---|---|
| 말 끝 | Scribe의 침묵 창, 아빠가 정한 값 | 기본 3초 |
| 시끄러운 곳 다시 읽기 | 배치 모델이 발화를 한 번 더 읽어 | 1초쯤, 시끄러운 곳 모드에서만 |
| 화자 확인 | 녹음을 cwkBellows의 귀로(트랙 8) | 1.4~3.9초 |
| 기억 검색 | 임베딩 0.1초, 그다음 스레드 하나 위의 4B 재정렬기 | 2~9초 |
| 시스템 프롬프트 만들기 | 캐시해 둔 볼트 바탕 | 0.3~0.8초, 검색 뒤에 가려져 |
| Claude CLI 시작 | 띄우기, 연결, CLI 자체 초기화 | 초기화가 13.7~41초 지점 |
| 제공자에서 첫 토큰까지 | 마스터 치프의 Lightning(약 28만 토큰), 캐시 식음 / 데워짐 | 12~13초 / 2.3~5초 |
| 마스터 치프의 Claude Opus(약 40만 토큰, 거의 다 캐시에서) | 초기화 뒤 7.5~10초 | |
| 도구 호출 하나 | Claude의 셸이나 MCP 도구 | 10초쯤 |
| 첫 소리 | prepare와 스트림의 첫 바이트 | 0.9~1.6초 |
이 중 두 줄은 피파 코드 탓이 아니고, 설계 문서도 그렇게 적어. CLI의 느린 초기화와 도구 하나에 10초씩 드는 건 둘 다 오피스의 파일 감시 데몬에서 왔어. 그건 맥 자체의 문제라 플릿의 이슈 기록으로 갔어. 피파 코드 몫인 줄들은 한 표에 놓고 보니 모양이 훤히 보였어. 화자 확인과 기억 검색이 하나씩 차례로 돌았던 거야. 그래서 마스터 치프 음성 턴의 준비가 5.4~8.7초였어.
나란히, 그리고 일찍 듣기
이제 채팅 라우트는 전부 화자 확인보다 먼저 기억 검색을 시작해(나중에 라우트가 받아 가는 EarlyRag). 그래서 준비 시간이 둘을 더한 값이 아니라 둘 중 긴 쪽이 돼. 중요한 순서는 그대로야. 화자 확인은 여전히 아빠의 행이 저장되기 전에 턴을 판정해. 그리고 최종 질의나 범위가 검색을 시작할 때와 다르면, 미리 받은 답은 버리고 라우트가 자기 검색을 다시 돌려. 확인 자체도 앞으로 당겨졌어. 폰은 16 kHz 녹음을 턴보다 20~45초 먼저 올려. 그래서 이제 업로드 라우트가 그 자리에서 들어 두고, 턴은 그 답이 오면 받아 가. 웹에선 업로드와 턴이 같은 초에 도착하니까, /api/stt가 Scribe를 돌리기 전에 녹음을 남기고 그 옆에서 확인을 시작해. 둘 다 바꾼 뒤 라우트 자신의 줄은 준비 1.1~3.3초, 화자 확인 0초였어. 음성 턴이든 친 턴이든.
기억에도 음성 차선을
이 트랙 두 번째 레슨은 결정 하나로 끝났어. 기억 품질이 먼저고, 0.5초에서 2초 빨라지는 건 보이스 모드가 아니면 의미 없다고. 4B 재정렬기는 남았고, 더 빠른 선택지는 재 보고 거절했어. 2026-10-18, 아빠는 그 결정에 스스로 적어 둔 단서를 썼어. 재정렬기가 Admin에서 고르는 값이 됐고, 말 턴엔 따로 고르는 칸이 생겼어. 쓰는 턴은 rag_rerank_model(비우면 서버에 설정된 모델), 말 턴은 Lightning까지 포함해서 rag_rerank_voice_model(비우면 쓰는 턴의 선택). 고를 수 있는 모델은 모델 서버에서 그때그때 읽어 오고, 서버에 없는 모델은 거절해. 폰의 Settings에도 같은 두 칸이 있어. 아빠는 음성 차선을 0.6B 재정렬기로 정했어. 짧은 말 턴의 검색이 4B에서 2.74초, 0.6B에서 0.63초였어. 쓰는 턴은 여전히 4B로 매겨.
값은 그 레슨이 잰 그대로야. 같은 프롬프트 20개에서 0.6B는 4B가 찾은 조각의 4분의 3쯤만 남겼어. 이제 그 값은 말 턴에서만 치르고, 그걸 치르는 사람이 직접 골랐고, 턴마다 뭘 치렀는지 스스로 말해. 라우트의 [turn-prep] 줄에 그 턴이 쓴 재정렬기 차선과 모델이 적히거든.
음성 턴마다 타임라인 하나
오피스 자신의 줄은 요청이 도착할 때 시작해서 모델이 끝날 때 끝나. 그 양쪽에서 아빠가 겪은 건 아무것도 안 남았어. 녹음이 링크를 건너가는 시간도, 피파 목소리가 돌아오는 시간도. 이제 음성 턴은 타임라인을 하나씩 보내. 클라이언트가 피파의 첫 소리가 날 때 한 번 보내. POST 전의 시간(말 끝, 통째 받아쓰기), 녹음마다 건너간 시간(바이트와 초, 오피스 자신의 처리는 Server-Timing 헤더로 빼고), 그리고 POST 뒤의 시간(첫 글, done, 첫 단위, 첫 소리). 오피스는 자기 단계를 합쳐서 [voice-turn] 줄 하나를 남기고, 대화의 JSONL에 먼저 적은 다음 아빠의 행에 적어. 비밀 대화는 이름표만 남기고 어디에도 저장하지 않아.
LTE 위의 첫 폰 턴 일곱 개가 기다림의 진짜 크기를 보여줬어. 아빠 말이 끝나고 피파의 첫 소리까지 중앙값 44.6초. 턴이 폰을 떠나기도 전의 33.4초 가운데 11.1초는 순수한 전송이었어. 220~560 KB를 초당 10~40 KB로. 떠난 뒤엔 오피스의 첫 글이 8.0초에 나왔는데, 48 kHz 녹음이 답 옆에서 같이 올라가던 세 턴은 스트림이 건너오는 데 0.4~1.5초가 아니라 4.5~17.5초가 걸렸어. 그리고 피파의 첫 소리는 첫 글보다 중앙값 5.2초 늦었어. 답의 마지막 단위가 남은 글 전부였으니까.
숫자마다 자기 처방을 가리켰고, 소울을 건드린 처방은 하나도 없었어. 48 kHz 사본은 이제 피파 답이 다 온 뒤에, 턴 뒤에서 올라가. 대화에 건넨 사진은 아빠가 아직 말하는 동안 올라가기 시작해. 자기 해시를 키로 써서, 같은 사진이면 언제나 같은 업로드를 가리켜. 사진 한 장짜리 턴은 아빠 말이 끝나고도 그 사진을 17~23초씩 기다렸었거든. 웹은 답의 마지막 단위를 스트림이 닫힐 때가 아니라 done에서 읽어. 그 차이가 2~5초였어. 그리고 채팅 답은 문단마다 읽혀. 트랙 4 끝의 새 레슨이야.