API server down 경보를 받고 서버를 의심했습니다 — 로그가 거짓말한 겁니다
새벽에 알림 하나가 떴습니다. "API server down". 에이전트를 백본으로 살아가는 사람한테 이 문장은 심장이 내려앉는 문구입니다. 바로 SSH로 서버에 붙어서 점검을 시작했습니다. 프로세스가 죽었겠거니 하는 마음으로요.
서버는 말짱했습니다
먼저 포트를 확인했습니다.
ss -tlnp | grep 18642
돌아온 포트는 멀쩡히 LISTEN 상태였습니다. hermes status 점검도 플랫폼 정상이었고요. API 서버는 OpenAI 호환 HTTP 엔드포인트 0.0.0.0:18642으로 정상 구동 중이었고 응답도 잘 돌아오고 있었습니다. 그러니까 다운은 사실이 아니었습니다. 서버는 살아있었습니다.
그런데 이대로 "다행입니다"로 넘길 수가 없었습니다. 경보는 꽤 자신 있게 down을 외쳤고, 그 외침의 출처를 짚어볼 필요가 있었습니다. 열어보니 문제가 두 개 겹쳐 있었습니다. 하나는 로그 오독이었고, 다른 하나는 진짜로 고장난 문제였습니다.

첫 번째 오해 — gateway.log의 stopped·listening 쌍
용의자는 gateway.log였습니다. 이런 라인의 쌍이 반복 기록돼 있었습니다.
API server stopped
listening on :18642
API server stopped 한 줄만 보면 그건 그야말로 크래시 로그입니다. 슬쩍 읽다가 이 줄만 보고 서버가 죽었다고 판단하면 오인입니다. 바로 다음 줄을 보면 listening on :18642로 다시 태어나고 있었거든요. 이 쌍은 Gateway가 재기동할 때마다 정상적으로 찍히는 로그입니다. 카페가 아침마다 "잠깐 닫습니다" 안내판을 붙였다가 곧바로 "영업시작"으로 바꾸는 것과 같은 모습입니다. 닫습니다 문패만 보고 화재 신고를 하는 셈입니다.
여기서 얻은 교훈은 stopped 라인을 단독으로 보지 않는 것입니다. 뒤에 listening이 다시 뜨는지까지 세트로 봐야 하고, 쌍이 맞으면 성공한 재기동, stopped가 홀로 남아 있을 때만 장애를 의심하는 순서가 맞습니다.
두 번째, 진짜 고장 — 소리가 나오지 않았습니다
로그를 추적하는 동안 따로 숨어 있던 문제가 얼굴을 내밀었습니다. 음성(TTS) 기능이 "만들어지는데 들리지 않는" 상태였습니다.
생성 자체는 완벽했습니다. 텍스트가 들어오면 mp3가 ~/.hermes/cache/audio/tts_*.mp3로 성실하게 만들어지고 있었습니다. 문제는 그 다음 단계인 재생이었습니다. 터미널 TUI 세션에는 애초에 스피커 출력 채널이 없고, 제가 쓰는 헤드리스 서버에는 pipewire와 pulseaudio 같은 사운드 데몬이 꺼져 있었습니다. ALSA 디바이스 노드 자체는 있는데 사운드 데몬이 없으니 ffplay로 터미널 재생을 시도해도 실패했습니다. 오디오 컬렉션을 산처럼 쌓아놓고 앰프에 전기가 들어오지 않은 집 같은 모습입니다. 파일은 있는데 소리가 나올 수가 없습니다.
다만 이건 기능 전체의 문제는 아니었습니다. 같은 TTS 출력이라도 데스크톱 앱에서는 정상으로 재생됐거든요. 즉 생성은 모든 구간이 정상이고, 출력만 플랫폼별로 달랐다는 뜻입니다. "API 서버가 죽었다"고 착각하고 들어간 골목에서 뜻밖의 버그 하나를 건진 셈이라, 좀 씁쓸하면서도 수확이 있었습니다.
정리하면 이렇습니다. API 서버 리스닝과 /v1 엔드포인트, mp3 생성, 데스크톱 앱 음성 재생은 전부 정상이었습니다. 비정상인 것은 헤드리스 서버의 사운드 데몬이 비활성이라 서버 자체 스피커로 출력이 안 되던 지점 하나, 그리고 그 둘 어디에도 속하지 않던 로그 오독 하나였습니다.
솔직히 남은 한계와 다음 플랜
끝까지 못 풀은 부분이 있습니다. "API server down" 메시지가 어디서 떴는지가 아직 특정되지 않았습니다. 슬랙 알림인지, 데스크톱 팝업인지, 로그 파일 파생인지 못 찍은 겁니다. 그래서 그 시점에 실제로 잠깐의 장애가 있었는지, 아니면 순수하게 로그 오독이었는지는 열어둔 상태입니다. 로그만 놓고 보면 정상 재기동으로 보이지만 100% 단정은 못 하겠습니다.
다음은 세 가지를 하려고 합니다. 첫 번째는 알림 문구의 발화 지점을 추적해서 "down" 표기가 로그 파생인지 실장애 파생인지 한 번 확정하는 일입니다. 두 번째는 stopped·listening 쌍 패턴을 모니터링 룰에 반영해서, 정상 재바운드가 경보로 올라오지 않게 하는 일입니다. 이런 양치 소동이 반복되면 결국 경보 자체를 안 보게 되니까 실용적인 과제입니다. 세 번째는 음성 출력을 애초에 서버 스피커가 아니라 데스크톱이나 모바일 같은 클라이언트 단말에서 재생하는 쪽이 정상이라는 걸 확인한 점입니다. 서버는 생성만, 출력은 단말에서요. 서버 자체 스피커로 소리를 내려고 pipewire 데몬을 헤드리스 머신에 상주시키는 건 다른 차원의 판단이 필요해서 일단 보류했습니다.
서버가 죽었다는 잘못된 골목에서 나와서, 로그 읽는 법 하나와 스피커 버그 하나를 건졌습니다. gateway.log에서 stopped·listening 쌍이 춤추는 걸 보셨다면 당황하지 마세요. 아마 그냥 카페가 영업 준비 중인 겁니다.