글

3.4MB짜리 Blogger 프로필 사진을 36KB로 줄였다

2026년 10월 13일, 이 블로그의 공개 페이지를 점검하다가 모든 표본 페이지가 3,427,910바이트(약 3.43MB)짜리 프로필 이미지를 참조하고 있는 것을 확인했다. 같은 날 최대 400x400 WebP로 바꿔 올렸다. 교체 완료는 업로드한 파일 크기가 아니라 공개 페이지의 이미지 참조와 응답 상태로 판정했다. 대상은 Blogger를 운영하면서 프로필이나 사이드바처럼 모든 페이지에 붙는 이미지 용량을 줄이려는 개발자다. 목표는 원본과 교체 파일의 크기를 기록하고, 교체 완료는 공개 페이지가 실제로 새 이미지를 참조하는지로 확인하는 것이다. 아래 숫자는 내 블로그 한 번의 교체 기록이다. 이 교체로 페이지 속도가 얼마나 좋아졌는지는 재지 않았다. 1. 모든 페이지에 붙는 큰 이미지를 찾는다 교체 전 감사는 로그인이나 설정 변경 없이 공개 페이지를 GET으로 받아서만 했다. 표본 페이지는 모두 프로필 가젯의 같은 PNG( <img alt='내 사진'> )를 참조했고, 그 응답 본문이 3,427,910바이트였다. 압축을 푼 텍스트 크기가 아니라 PNG 응답 본문의 바이트 수다. 비교 대상도 함께 쟀다. 최신 5편의 본문 cover·diagram 이미지는 56,723~83,411바이트, 인기글 썸네일은 108,006바이트와 165,802바이트였다. 감사는 본문 대표 이미지 대다수가 56~138KB인 데 비해 공통 프로필이 더 큰 정적 부담이라고 정리했다. 다만 감사도 한계를 적어 두었다. 브라우저가 이 이미지를 실제로 언제 요청하는지, lazy loading·cache·srcset으로 어떤 변형을 고르는지는 HTTP 실측으로 확정하지 않았다. 페이지별 무게 합계도 HTML이 직접 참조한 자원만 더한 근사이며, 브라우저 전체 전송량이나 CWV가 아니다. 2. 작게 만들어 같은 자리에 올린다 감사가 제시한 수정 위치는 Blogger → 레이아웃 → 프로필 가젯이었다. 표시 크기에 맞춘 작은 이미지로 바꾸고, 목표는 수십 KB...

agent_settled는 '답변 완료'라는 뜻이 아니었다

2026년 9월 30일 수정 전, 텔레그램으로 보낸 블로그 작업 요청 다섯 건이 모두 최종 답변 없이 끝났다. 요청은 다섯 건 모두 세션에 도착해 있었다. 수정 보고서가 짚은 브리지 쪽 문제는, 세션의 agent_settled 이벤트가 오면 최종 답변이 없어도 요청을 끝내고 폴백을 보내는 흐름이었다. 대상은 메신저 요청을 에이전트 세션에 넣고 답을 다시 메신저로 돌려보내는 브리지를 직접 만든 개발자다. 목표는 턴이 끝났다는 신호와 최종 답변이 생겼다는 사실을 따로 판정하는 것이다. 아래는 9월 30일 내 브리지 한 건의 수정 기록이다. 모든 에이전트 런타임의 이벤트가 이렇게 동작한다는 뜻은 아니다. 기록된 증상: 다섯 요청이 모두 도착했는데 답이 없었다 수정 보고서에 남은 원인은 이렇다. 기존 흐름은 요청의 user 메시지가 시작된 뒤 agent_settled 가 오면, 최종 assistant 텍스트가 없어도 바로 요청을 끝내고 폴백을 전송했다. 실제 요청 파일과 상태 파일이 만들어진 간격도 4~7초뿐이었다. 보고서가 대조한 세션 기록에서 다섯 요청은 모두 세션에 들어가 있었다. 한 건은 Claude 인증 차단, 나머지 네 건은 로드된 런타임의 OpenAI chunk 누락 오류가 난 뒤 assistant 최종 메시지가 없었다. 마지막 요청도 세션에서 유실된 것이 아니었다. 요청 표시가 세션 기록에 있었고, 바로 다음 줄에 provider 모듈 오류가 있었다. 정리하면 이 사고에서 두 가지가 겹쳤다. 하나는 provider 쪽 오류로 답변이 만들어지지 않은 것이다. 다른 하나는 브리지가 그 상황을 곧바로 "끝"으로 처리한 것이다. 두 오류가 왜 났는지는 이 보고서에 없다. 이 글은 두 번째, 브리지의 판정만 다룬다. 보고서는 이번 증상과 별개로 위험이 하나 더 있었다고 적었다. 기존 주입은 세션이 바쁜 상태로 바뀌는 경쟁 상황에 필요한 deliverAs 를 지정하지 않았다. 확장 API의 실제 비동기 실패는 fire-and-forg...

AI 에이전트 세션 자동 인계, 세 가지 방법 다 실패하고 되돌렸다

나는 텔레그램 /blog 명령으로 에이전트 하네스 omo의 장기 작업 세션에 블로그 작업을 넘긴다. 2026년 9월 15일, 긴 컨텍스트에서 GPT가 작업을 처리하지 못한다는 문제를 풀려고 대화 기록 없이 새로 실행하는 /blog --fresh 를 만들었다. 실전 검증에서 세 방식이 모두 timeout으로 실패했고, 나는 이 기능을 통째로 되돌렸다. 대상은 긴 세션 문제를 "새 세션으로 자동 인계"로 풀려는 개발자다. 이 글은 성공 방법이 아니라 실패 기록이다. 모델을 바꾸는 것과 세션을 분리하는 것이 어떻게 다른지, 무엇을 시도했고 어디서 멈췄는지를 정리한다. 모델만 바꾸는 것은 답이 아니었다 먼저 떠오르는 방법은 모델 전환이다. 내 브리지에는 이미 모델 선택자가 있었다. /blog --model <선택자> … 는 그 요청만 지정 모델로 처리하고 원래 모델로 돌아오며, --model-sticky 는 바꾼 모델을 유지한다. 하지만 기록에 남긴 판단은 이렇다. 모델만 바꾸는 방식은 기존 85MB 세션을 그대로 넘기므로 해결책이 아니다. --model 은 기존 장기 세션의 컨텍스트를 그대로 쓴다. 모델 전환은 "어떤 모델이 읽느냐"를 바꾸고, 세션 분리는 "무엇을 읽느냐"를 바꾼다. 컨텍스트 문제에는 후자가 필요했다. 만들었던 구조 /blog --fresh 모델별칭 작업내용 을 OpenClaw 플러그인에 추가했다. 이 경로는 요청 폴더와 장기 세션 확장을 거치지 않고 worker 스크립트를 detached process로 띄운다. worker는 omo를 세션·확장·프롬프트 템플릿 없이 별도로 실행하고, 결과만 원래 텔레그램 메시지에 답장으로 보낸다. 기록된 실행 형태는 다음과 같다. omo --no-session --no-extensions --no-prompt-templates --print 기존 세션, 파일, 예약은 지우지 않았다. fresh 실행 자체의 대화 기록만 저장하지 않았...

Anthropic S-1 A/S: 2026 상반기 순손실에도 영업현금 순유입

이미지
지난 글에서 WSJ 보도로만 본 Anthropic 상장신고서(Form S-1)가 2026-10-26 미국 SEC에 공개 제출됐다. 그때 쓴 어림값을 공시 원문과 다시 대조했다. 2026년 상반기 순손실은 807.48억 달러였지만 영업활동 현금은 +39.29억 달러 순유입이었다. Anthropic S-1 정식 공시와 WSJ 보도 비교 이번 문서는 나스닥(심볼 ANT) 상장을 신청하는 단계의 예비 신고서다. 공모가와 발행주식수, 공모 일정은 아직 빈칸이다. 아래 표는 WSJ가 전한 어림값과 S-1의 정밀값을 나란히 놓은 것이다. 단위는 억 달러이고 근거는 S-1 p.22, p.168, F-7, F-12다. 항목 WSJ 보도(10/20) S-1 공시(10/26) 2026 상반기 매출 약 163 162.86 2025 상반기 매출 11 11.63 상반기 매출 배수 약 14.8배 약 14.0배 2026 상반기 순손실 807 807.48 2026 상반기 컴퓨팅·인프라 약 90 89.45 2025 연간 매출 / 컴퓨팅 46 / 73 45.85 / 73.26 비용 ÷ 매출(2025 연간 → 2026 상반기) 약 159% → 약 55% 159.8% → 54.9% 2026 상반기 영업활동 현금 이전 글에 없음 +39.29 전년 동기 매출이 11.63억 달러로 정밀해져 상반기 매출 배수는 14.8배에서 약 14.0배가 됐다. 보도된 어림값과 공시된 정밀값의 차이이고, 실적을 정정했다는 근거는 없다. 2025년은 12개월, 2026년은 6개월 수치다. 컴퓨팅·인프라는 감가상각을 포함한 회계 비용이다. 출처: Anthropic S-1 p.22·F-7 차트의 2026년 막대는 6개월 수치여서 12개월인 2025년과 길이를 그대로 견줄 수 없다. 또 S-1(p.145)은 이 비용에 클라우드 비용, 리스료, 서버 감가상각을 넣는다. 그래서 지난 글의 '지출' 표현과 달리 이 숫자는 현금 지급 총액이 아니다. 매출원가나 현금 소진액으로 바꿔 읽어도 안 된다. ...

텔레그램 봇이 답을 안 한다, 프로세스는 멀쩡했는데

2026년 10월 2일, 텔레그램으로 블로그 작업을 넘기는 봇의 응답이 끊겼다. 운영 기록에 남은 원인은 텔레그램 메시지를 받아 세션에 넘기는 프로세스가 아니라, 브리지가 의존하는 herdr의 멈춤이었다. 대상은 텔레그램 봇을 에이전트 세션에 붙여 쓰다가 "프로세스는 살아 있는데 답장이 안 온다"는 상황을 만난 개발자다. 목표는 프로세스가 살아 있는지와 메시지가 실제로 오가는지를 따로 판정하는 것이다. 아래 내용은 10월 2일 내 환경 한 건의 기록이고, 같은 증상이 모두 herdr 때문이라는 뜻은 아니다. 기록된 증상과 복구 내 구성에서 텔레그램 메시지는 OpenClaw 플러그인과 게이트웨이를 거쳐 블로그 작업 세션으로 넘어간다. 세션 쪽에서 요청을 가져가는 프로세스를 여기서는 소비 프로세스라고 부른다. 이 브리지는 herdr에 의존한다. 10월 2일 응답이 끊겼을 때 herdr 창에는 다음 오류가 떠 있었다. Failed to continue queued messages: Cannot continue from message role: assistant herdr는 launchd 항목 sh.brew.herdr 로 새 PID를 받아 다시 떴다. 그러자 텔레그램 응답도 바로 돌아왔고, 텔레그램 쪽에서 실제로 답장을 받는 것까지 확인했다. 기록에 없는 것도 분명히 해 둔다. herdr를 내가 다시 띄웠는지 launchd가 자동으로 다시 띄웠는지는 남기지 않았다. 응답이 언제부터 얼마나 끊겼는지도 기록에 없다. 위 오류 문자열이 정확히 무엇을 뜻하는지, herdr가 왜 멈췄는지도 이 기록으로는 알 수 없다. 살아 있는 PID가 말해 주지 않는 것 이 사고에서 남긴 교훈은 이렇다. 소비 PID가 살아 있고 ready.json 과 consumer.lock 이 그 PID를 가리키고 있어도 정상이라는 뜻은 아니다. PID와 락 파일은 "소비 프로세스가 떠 있고 자기가 담당이라고 표시했다"는 것까지만 알려 준다. 메시지가...

텔레그램 봇이 파일 경로를 명령어로 착각했다

2026년 10월 2일, 텔레그램 봇에 보낸 '/'로 시작하는 일반 메시지가 명령으로 오인돼, 블로그 세션이 아니라 OpenClaw의 CEO 에이전트로 갔다. 기록에 남은 예는 /Users/... 형태의 파일 경로다. 같은 날 명령 판별 조건을 좁히고 회귀 테스트를 붙였다. 그 조건과 사례표를 정리한다. 대상은 텔레그램 봇이 받은 메시지를 명령과 일반 텍스트로 나눠 서로 다른 실행자에게 보내는 개발자다. 목표는 파일 경로처럼 '/'로 시작하는 일반 텍스트가 명령으로 잡히지 않게 하고, 그 경계를 테스트로 고정하는 것이다. 아래는 내 OpenClaw 텔레그램 브리지 플러그인의 기록이며, 예시 경로는 실제 경로가 아니라 가짜다. 라우팅 규칙과 사고 전날인 10월 1일 라우팅을 바꿨다. 소유자 개인 대화에서 / 로 시작하지 않는 모든 메시지와 사진 캡션을 블로그 세션으로 보낸다. /blog , 모델 선택자, 알림 답장, 중복 방지는 그대로 두고, 다른 /명령 과 다른 사람, 단체방 메시지는 블로그로 보내지 않는다. 이 규칙에서 기준은 첫 글자 '/'였다. 파일 경로도 '/'로 시작한다. 10월 2일, '/'로 시작하는 일반 메시지가 명령어로 오인돼 블로그가 아닌 CEO 에이전트로 갔다. CEO 쪽은 gpt-5.4-mini 미지원 오류로 답하지 못했다. 수정: 명령은 "/이름[@봇] 뒤에 공백 또는 끝" 플러그인에서 다른 명령으로 보는 조건을 " /이름[@봇] 뒤에 공백이 오거나 메시지가 끝날 때"로 좁혔다. 판별 정규식은 다음과 같다. /^\/[A-Za-z0-9_]+(?:@[A-Za-z0-9_]+)?(?:\s|$)/ / 다음에 영문·숫자·밑줄로 된 이름이 오고, 선택적으로 @봇이름 이 붙은 뒤, 바로 공백이나 끝이 와야 명령이다. 단, 이 검사는 /blog 와 /blog@봇이름 을 먼저 따로 판별한 뒤에만 적용한다. 그래서 /blog hel...

Node ESM 파일을 고쳤는데 옛 코드가 돌았다

2026년 9월 14일 12:55에 시작한 omo 프로세스는 9월 16일에 확인했을 때도 시작할 때 읽은 텔레그램 브리지 확장을 그대로 쓰고 있었다. 그사이 확장 파일을 두 번 고쳤지만 둘 다 실행 중인 프로세스에는 반영되지 않았다. 디스크의 파일과 실행 중인 모듈이 서로 다른 세대일 때 그 차이를 어떻게 대조했는지 기록한다. 대상은 로컬 에이전트나 봇의 Node ESM 확장을 고쳤는데 동작이 그대로인 개발자다. 목표는 수정이 실제로 올라왔는지 판정하고, 무엇을 바꿨을 때 무엇을 다시 띄워야 하는지 구분하는 것이다. 아래는 9월 당시 내 omo 하네스와 OpenClaw 텔레그램 브리지의 기록이다. Node.js ESM 캐시 동작 전반을 따로 실험해 확인한 글은 아니다. 증상: 모델만 바꾸라는 요청이 빈 요청이 됐다 이 브리지에서는 텔레그램으로 /blog --model <선택자> 작업내용 을 보내면 그 요청만 지정 모델로 처리하고, --model-sticky 를 쓰면 모델을 유지한다. 9월 15일 15:55와 16:24에 작업 내용 없이 --model 아스트라 만 보냈다. 두 번 모두 실제 소비 세션은 새 확장을 reload하지 않은 상태였고, 기존 구현이 빈 프롬프트를 세션에 넣은 뒤 최종 답변을 확인하지 못했다는 안내를 보냈다. 이것을 UX 결함으로 보고, 모델만 담긴 요청은 모델을 유지 전환하고 모델 호출 없이 바로 성공 회신하도록 세션 확장을 고쳤다. 원인: 파일은 새것, 프로세스는 9월 14일 것 9월 16일에 다시 확인하니 모델 변경 명령이 안 먹는 진짜 원인은 프로세스 세대였다. omo 프로세스는 9월 14일 12:55에 시작해 그때의 확장을 계속 쓰고 있었다. 9월 15일 16:00의 모델 단독 요청 처리 수정과 9월 16일 08:21의 em/en 대시 허용 수정이 모두 반영되지 않았다. 로더 캐시 버전을 올려도 /reload 나 재시작 전에는 적용되지 않았다. 9월 13일 날짜가 붙은 기록 절에도 이런 주의가 적혀 있다. ...