Claude Code 모바일 디버깅 실전기

핸드폰 하나로 서버 장애를 해결한 기록

by Blueming

텔레그램 봇이 멈췄다

나는 개인 프로젝트로 텔레그램 봇을 하나 운영하고 있다. 증권사 리포트 PDF를 자동으로 수집해서 AI로 요약한 뒤 채널에 발송하는 봇이다. 구독자가 약 2,000명 가까이 되는, 나름 의미있는 사이드 프로젝트다.


그런데 며칠 전부터 이상한 점을 발견했다. PDF 파일은 정상적으로 다운로드되어 채널에 올라가는데, 요약본이 사라졌다. 한화투자증권, POSCO홀딩스, 하나증권 — 리포트는 쌓이는데, 어디에도 AI 요약이 없다.


문제는 타이밍이었다. 이걸 발견한 건 컴퓨터 앞이 아니라 핸드폰을 보고 있을 때였다.


-----


핸드폰에서 Claude Code를 열다

예전이라면 컴퓨터 앞에 앉아야 디버깅을 시작할 수 있었다. 하지만 지금은 다르다. 모바일에서 Claude Code를 열고 서버에 접속했다.


“여전히 요약본이 안나오고 있음”이라고 한 줄 쳤다.

Claude Code는 먼저 몇 가지를 물어봤다. 어떤 요약본인지, 이전에 설정한 것이 있는지, 어떤 스크립트를 실행하고 있는지. 맥락을 파악하려는 것이다. 작업 디렉토리를 확인하고 나서, 본격적인 탐정 작업이 시작됐다.


-----


AI 탐정의 수사 과정

Claude Code가 한 일을 순서대로 정리하면 이렇다.


1단계: 현장 확인 — 오늘 날짜(03/26) 폴더를 확인했다. PDF 다운로드는 정상. 요약 생성 관련 코드를 읽기 시작했다.


2단계: DB 조회 — SQLite DB의 `sent_reports` 테이블을 직접 쿼리했다. 여기서 첫 번째 단서가 나왔다. 3/25부터 요약이 전혀 생성되지 않고 있었다. 3/23도 마찬가지. `sent=1`인데 `summary_text`가 비어 있다. 요약 없이 “전송 완료”로 처리되고 있었다는 뜻이다.


3단계: 로그 추적 — 로그를 뒤졌더니, 모든 리포트가 “이미 처리됨”으로 스킵되고 있었다. 다른 스크립트가 요약 없이 `sent=1`로 저장한 것이다.


4단계: 컬럼 분석 — DB 데이터를 자세히 들여다보니, `sent` 컬럼에 타이틀 텍스트가 들어가 있었다. 컬럼이 뒤섞여 있었다. 여기서 두 번째 단서.


-----


원인은 두 개였다

Claude Code가 최종적으로 찾아낸 원인은 두 가지였다.

문제 1: 실행 중인 스케줄러가 옛날 코드를 사용 — `report_scheduler.py`는 시작할 때 `importlib`로 모듈을 한 번만 로드한다. `summarize_scraped_content` 함수에서 OpenAI API 호출 시 `max_tokens` 파라미터를 사용하고 있었는데, `gpt-5-nano` 모델은 이걸 지원하지 않고 `max_completion_tokens`만 지원한다. 코드 파일은 이미 수정되어 있었지만, 스케줄러를 재시작하지 않아서 메모리에 올라간 옛 코드가 계속 실행되고 있었다. 결과: OpenAI API 400 에러.


문제 2: 요약 실패인데 `sent=1`로 저장 — 요약이 실패했는데도 DB에 `sent=1`로 기록되어, 다음 실행 시 “이미 처리됨”으로 스킵되는 악순환이 발생했다.


한 마디로, 코드는 고쳤는데 프로세스를 재시작 안 한 것 + 에러 핸들링 미비의 합작이었다. 개발자라면 한 번쯤 겪어봤을 클래식한 실수다.


-----


수정도 Claude Code가 했다


원인을 찾은 뒤, Claude Code는 수정 계획을 제시했다.


조치 1:DB에서 요약 없이 `sent=1`로 저장된 294개 레코드를 `sent=0`으로 리셋.


조치 2: 스케줄러를 재시작하여 수정된 코드를 적용.


“부탁해”라고 한 마디 치니, 직접 SQL을 실행하고 스케줄러를 재시작했다. 이어서 수동 테스트까지 돌려 요약이 정상 생성되는 것을 확인했다. API 호출도 200 OK.


전 과정이 핸드폰 화면 안에서 이루어졌다. 컴퓨터는 건드리지도 않았다.



-----


이것이 ‘디지털 군단’의 실체다


이 에피소드가 중요한 이유는, 지난 일주일간 이야기해 온 개념들이 실제로 작동하는 장면이기 때문이다.


에이전틱 루프 — Claude Code가 파일을 읽고, DB를 쿼리하고, 로그를 분석하고, 원인을 특정하고, 코드를 수정하고, 테스트까지 돌렸다. 사람은 중간중간 승인 버튼을 누른 것뿐이다.


모바일 원격 제어 — Dispatch나 Claude Code 원격 기능이 아니어도, 모바일 Claude Code만으로 서버 장애를 진단하고 해결할 수 있었다. “컴퓨터 앞에 앉아야 한다”는 마지막 제약이 사라지고 있다.


자연어 디버깅 — “요약본이 안나와”라는 한 줄에서 시작해서, `max_tokens` vs `max_completion_tokens` 파라미터 차이까지 도달했다. 프로그래밍 언어의 문법을 외울 필요가 없다.


이전 글에서 “생각은 GPT-5.4처럼 깊게, 행동은 Claude Code처럼 빠르게”라고 썼다. 오늘 그 문장이 핸드폰 화면 안에서 증명됐다.


-----


설계자의 교훈


이번 경험에서 얻은 교훈은 기술적인 것보다 구조적인 것이다.


에이전트가 아무리 똑똑해도, 프로세스 재시작은 사람이 판단해야 한다. 코드를 고치는 것과 실행 환경에 반영하는 것은 별개의 문제다. 이 간극을 메우는 것 — CI/CD 파이프라인, 헬스체크, 자동 롤링 리스타트 — 이 바로 ‘설계자’의 몫이다.


에이전트는 점점 더 많은 것을 자율적으로 할 수 있게 될 것이다. 하지만 그 자율성이 올바르게 작동하려면, 그 아래에 사람이 설계한 구조가 있어야 한다.


당신의 디지털 군단은 오늘 밤, 어떤 문제를 해결하고 있는가?

작가의 이전글나만의 디지털 군단 만들기