사진 한 장의 1분
2026-10-09 23:47, 세비야에서 아빠가 네이티브 앱에 사진 한 장을 붙여 넣고 보냈어. 폰은 tailnet 너머 한국 사무실과 말했고, 왕복 한 번에 285 ms 쯤 걸렸어. 나중에 케이블로 연결한 아빠 iPhone 과 사무실 접근 로그로 재 보니 이랬어. 407 KB 업로드에 2.02초, 그중 0.28초가 새 연결을 여는 데 들었고, 턴의 첫 바이트는 그 뒤 5.1초 만에 왔어. 그리고 같은 1분 동안 앱이 요청 200개를 보내고 5.84 MB 를 받았어. 하나같이 새 연결이었고, 열려 있던 대화의 페이지를 1-2초마다 다시 받아 왔어. 앱을 처음 켤 때도 첫 1분에 요청 78개, 2.19 MB, 그중 77개가 새 연결이었고.
망가진 건 없었어. 요청 하나하나는 다 맞았어. 이 레슨이 다루는 함정이 바로 그거야. tailnet 에 유선으로 붙은 책상에선 수다스러운 클라이언트가 안 보여. 해외의 폰에선 같은 클라이언트가 1분 대부분을 이미 답을 가진 질문에 써. 집 안내문엔 이제 규칙으로 적혀 있어. 폰은 연결을 유지하는 풀 하나로 엔진과 말하고, 바뀌었을 때만 물어본다.
아빠가 허락한 순서대로, 고친 것 셋
연결을 유지하는 풀 하나. 이제 클라이언트는 모든 전송과 턴 스트리머를 공용 kit 의 연결 풀 하나에서 만들어. 그래서 업로드에 쓴 연결이 바로 뒤따르는 턴을 실어 나르고, 뒤에서 도는 읽기가 다음 보내기를 위해 풀을 데워 둬. 서버는 쉬는 연결을 75초 동안 붙들고 있어서, 턴과 턴 사이에도 연결이 살아남아.
바뀌었을 때만 묻기. 새 미들웨어 app/api_conditional.py 가 /api 아래에서 한 번에 끝나는 200 application/json 답마다 본문으로 계산한 약한 ETag 를 붙이고, 같은 If-None-Match 가 오면 빈 304로 답해. gzip 층 안쪽에 있어서 태그는 압축 전 바이트로 계산되고, 태그가 맞아도 route 는 그대로 돌아. 그러니 304는 언제나 바이트가 같다는 뜻이지, 짐작도 아니고 누가 올리는 걸 깜빡할 route 별 버전 숫자도 아니야. 스트림과 비공개 대화엔 태그가 안 붙어. 폰에선 304가 이미 들고 있던 본문으로 돌아가서, 전송 계층 위로는 바뀐 게 하나도 없어.
뒤에서 하는 동기화는 보내기한테 비켜 줘. 자동 새로고침은 한 번에 하나씩만 돌고(뒤에 온 신호는 돌고 있는 데 합류해), 강제가 아니면 30초에 한 번까지만, 그리고 턴을 보내거나 받는 동안엔 아예 안 돌아. 미뤄 뒀다가 보내기가 가라앉으면 한 번 돌아. 오프라인용 대화 목록 훑기는 마지막 갱신이 안 바뀐 대화를 건너뛰고, 보내기가 시작되면 멈춰. 네트워크 감시는 경로가 바뀔 때마다가 아니라 네트워크가 돌아왔을 때만 새로고침해.
보내기 경로, 왕복 하나씩
같은 측정이 보내기도 뜯어봤어. 업로드가 시작되기 전에 폰은 읽기 셋을 줄줄이 했어. 레인의 가라앉음 확인, 턴 상태 읽기(엔진이 이 턴을 이미 봤나, 그래야 두 번 안 보내니까), 그리고 두 번째 가라앉음 확인(다른 기기의 안 끝난 턴이 이 대화에 없나). 세비야에서 하나에 0.6초쯤 들었어. 뒤의 둘은 서로 기대지 않으니까 이제 나란히 돌아. 각자 자기 규칙은 그대로고, 빠진 확인은 하나도 없어.
같은 때 서버 쪽에 턴 시계도 들어갔어. route 가 스트림을 넘길 때 로그 한 줄이 남는데, 해석, 화자 확인, 위치, 사용자 행, healing, 압축, 기록, 검색과 프롬프트로 시간이 쪼개져 있고, 첫 이벤트가 나갈 때 한 줄이 더 남아. 그 시계 덕에, 예약 턴이 검색에 15-16초를 쓰고 있다는 게 드러났어. 서버 맥의 reranker 는 후보를 하나씩 채점하는데, 길게 렌더된 cron 프롬프트 때문에 한 번 한 번이 느렸고, 그러고도 15초짜리 대화용 한도에 걸려 순위를 결국 버렸던 거야. 이제 Claude 라우트의 예약 턴은 순위 매기기에 60초를 받고, 아빠가 직접 하는 턴은 대화용 한도를 그대로 써. 따로 시간을 안 넘기는 변형 라우트 여섯에선 예약 턴도 아직 15초야.
outbox 가 레인을 배웠어
레슨 2의 outbox 는 큐 전체를 한 줄로 차례차례 비웠어. 2026-10-05에 도구 호출에 걸려 멈춘 손목 턴 하나가, 아빠가 받아쓰기로 보낸 새 대화를 1분 43초 동안 붙잡았어. 멈춘 턴이 끝나고 1초 뒤에야 나갔지. 이제 대화마다 자기 레인에서 비워져. 한 대화 안에선 순서대로, 대화끼리는 나란히, 멱등 키는 여전히 요청 id 고. 보내기는 입력창으로 아직 들어오는 중인 사진도 기다려서, 붙여 넣은 사진이 다음 메시지로 새어 들어가는 일도 없어졌어. 녹음과 사진은 나란히 올라가고.