귀찮은개발자6 min

텔레그램으로 내 사업을 관리한다

2026년 4월 · 귀찮은개발자 EP.12

2026년 4월 · 귀찮은개발자 EP.12

EP.10에서 MCP 서버를 만들었다. EP.11에서 SaaS 데이터를 연결했다. 50개 도구가 생겼고, Claude한테 물어보면 뭐든 가져다줬다.

근데 문제가 있었다. 터미널을 열어야 했다. Claude Code를 켜고, 거기서 질문해야 답이 왔다. 밥 먹다가 “매출 어떻지?”하면 노트북을 열어야 했다. 귀찮았다.

텔레그램으로 옮기기로 했다. 카톡 보내듯이 DM 하나 보내면 매출, 피드백, 일정이 다 온다. 폰에서 된다. 그게 목표였다.

빠르게 보기

– 텔레그램 봇 + Claude MCP로 DM 에이전트 구축
– AGENT.md 작성 — 자연어를 도구 호출로 매핑
– 409 Conflict 디버깅 — 봇 폴링 충돌 해결
– tmux 상시 실행 + Stop 훅 자동 재시작 구조 완성
– 폰에서 “매출 어때?”하면 데이터가 온다

구조: 봇이 메시지를 받고, AI가 답한다

구조를 그리면 이렇다.

Telegram Agent 아키텍처 — Telegram DM, Claude 두뇌, MCP 서버, 데이터 소스 연결도
텔레그램 메시지가 들어오면 Claude가 MCP로 데이터를 가져와서 답한다 / GoCodeLab

텔레그램 봇이 메시지를 받는다. Claude가 그 메시지를 읽는다. 필요한 데이터를 MCP 도구로 가져온다. 답을 텔레그램으로 보낸다. 이게 전부다.

텔레그램 봇은 전화 교환원 같은 거다. 메시지를 전달만 한다. 생각은 Claude가 한다. 데이터는 MCP가 가져온다. 봇 자체는 멍청해도 괜찮다.

AGENT.md: 에이전트 지시서

Claude한테 역할을 알려줘야 한다. AGENT.md 파일 하나에 전부 적었다.

# AGENT.md — 상시 실행 에이전트 지시사항

역할: Telegram DM 응답 + 모닝 브리핑
언어: 한국어, 간결하게

## 자연어 매핑
“매출 알려줘” apsity_revenue
“피드백”      → feedmission_feedback
“오늘 일정”   → apple_calendar
“날씨”      → weather_today
“차 상태”    → car_status

핵심은 자연어 매핑이다. “매출 알려줘”가 들어오면 apsity_revenue를 부른다. “피드백”이면 feedmission_feedback을 부른다. Claude가 자연어를 이해하니까 정확히 일치하지 않아도 된다. “이번 달 돈 얼마나 벌었어?”해도 매출 도구를 부른다.

이 파일을 Claude한테 넘기면 에이전트가 된다. 별도 코드 없이 지시서 하나로 동작한다.

실제로 쓰면 이렇다

텔레그램 DM 화면 — 매출, 피드백, 일정을 자연어로 질의하는 대화
텔레그램에서 “오늘 매출 어때?”하면 바로 답이 온다 / GoCodeLab

카톡 보내듯이 텔레그램에 “매출 어때?”하면 된다. Apsity 앱 매출이랑 FeedMission 구독 현황이 한 메시지로 온다. “피드백 있어?”하면 최근 피드백 목록이 온다. “오늘 일정”하면 캘린더를 뒤져서 알려준다.

폰에서 된다. 지하철에서 된다. 노트북을 안 열어도 된다. 이게 핵심이다.

봇이 대답을 안 한다

여기서 막혔다. 텔레그램에 메시지를 보냈는데 답이 안 왔다. 봇이 멍해 있었다.

로그를 봤다. 빨간 글씨가 떠 있었다.

409 Conflict: terminated by other getUpdates request
make sure that only one bot instance is running

409 Conflict. “다른 데서 이미 받고 있어요”라는 에러다.

getUpdates가 뭔가

텔레그램 봇이 새 메시지를 확인하는 방법이다. 전화기가 수신 대기하는 것과 비슷하다. 봇이 텔레그램 서버한테 “나한테 온 메시지 있어?”하고 계속 물어본다. 이걸 폴링(polling)이라고 한다. 문제는 이 수신 대기를 동시에 하나만 할 수 있다는 거다. 전화 2대가 같은 번호로 동시에 수신 대기하면 충돌이 난다. 그게 409 Conflict다.

원인을 찾았다. 나는 tmux(터미널을 여러 개 열어놓는 도구)에서 텔레그램 에이전트를 돌리고 있었다. 근데 Claude Code로 개발하는 세션에서도 같은 봇 토큰을 쓰고 있었다. 두 군데서 동시에 수신 대기를 한 거다.

같은 전화번호로 전화 2대를 켜놓은 꼴이었다. 당연히 안 된다.

해결: settings.json 분리

방법은 간단했다. 개발할 때는 봇을 안 켜면 된다.

터미널 — 409 Conflict 에러와 settings.json 분리 해결 과정
409 에러부터 해결까지 한 화면에 정리했다 / GoCodeLab

Claude Code는 설정 파일이 두 단계다. 글로벌(전체 적용)이랑 프로젝트(폴더별 적용). 프로젝트 설정이 글로벌보다 우선한다.

// 글로벌: ~/.claude/settings.json
// 모든 프로젝트에 적용된다
{ “telegram”: false }

// 프로젝트: .claude/settings.json
// LazyDevAssistant 폴더에서만 적용
{ “telegram”: true }

글로벌에서 텔레그램을 꺼놨다. 그래서 내가 개발할 때는 봇이 안 뜬다. 프로젝트 설정에서만 켜놨다. tmux 에이전트 세션은 LazyDevAssistant 폴더에서 뜨니까 프로젝트 설정을 읽는다. 거기서만 봇이 뜬다.

이제 충돌이 안 난다. 개발 세션은 봇 없이 돌아가고, tmux 에이전트만 메시지를 받는다.

tmux: 봇을 24시간 돌리는 법

tmux가 뭔가

터미널을 여러 개 열어놓는 도구다. 핵심은 창을 닫아도 안에서 돌아가는 프로그램이 계속 살아있다는 거다. 맥북 화면을 닫아도 서버가 꺼지지 않는다. 24시간 돌려야 하는 봇한테 딱이다.

에이전트를 tmux 세션에 띄웠다. 맥미니 서버에서 돌린다. 화면을 닫아도 봇은 계속 메시지를 받는다.

# tmux 세션 만들기
$ tmux new-session -d -s agent

# 에이전트 실행
$ cd ~/LazyDevAssistant && claude –agent

# 세션 확인 (나가도 계속 돌아간다)
$ tmux ls
agent: 1 windows (created Mon Apr 7 09:41:02 2026)

근데 문제가 하나 더 있었다. 내가 개발하려고 Claude Code를 켜면 에이전트 세션이 방해받는다. 그리고 개발이 끝나서 Claude Code를 끄면 에이전트를 다시 켜줘야 한다. 매번 수동으로 하긴 귀찮다.

Stop 훅: 자동 재시작

훅(Hook)이 뭔가

특정 이벤트가 일어나면 자동으로 실행되는 스크립트다. 스마트폰 알람 같은 거다. “7시가 되면 알람을 울려라”처럼, “Claude Code가 종료되면 restart-agent.sh를 실행해라”고 걸어놓는 거다.

Claude Code에 Stop 훅을 걸었다. 개발 세션이 끝나면 자동으로 에이전트를 다시 띄운다.

#!/bin/bash
# scripts/restart-agent.sh

# 기존 에이전트 세션 정리
tmux kill-session -t agent 2>/dev/null

# 새로 띄우기
tmux new-session -d -s agent \
  “cd ~/LazyDevAssistant && claude –agent”

흐름을 정리하면 이렇다.

1. 맥미니에서 tmux 에이전트가 돌아간다
2. 내가 개발하려고 Claude Code를 켠다
3. 글로벌 설정에 telegram: false라서 봇 충돌 없다
4. 개발 끝나고 Claude Code를 닫는다
5. Stop 훅이 restart-agent.sh를 실행한다
6. tmux 에이전트가 다시 뜬다
7. 텔레그램 봇이 다시 메시지를 받기 시작한다

한번 세팅해놓으면 신경 쓸 게 없다. 개발하다 끝내면 봇이 알아서 복구된다.

왜 카톡이 아니라 텔레그램인가

카카오톡은 개인 봇을 못 만든다. 비즈니스 채널만 가능하다. 메시지 수신 API가 개인한테 안 열려 있다.

텔레그램은 BotFather한테 말 걸면 봇이 바로 나온다. API 토큰 하나 받으면 끝이다. 개인 DM으로 1:1 대화가 된다. 개발자한테는 텔레그램이 압도적으로 편하다.

솔직히 텔레그램을 평소에 쓰진 않았다. 근데 봇 때문에 깔았더니 이제 제일 많이 여는 앱이 됐다.

달라진 것

예전에는 아침마다 이랬다. 맥북 열고, Apsity 대시보드 열고, FeedMission 대시보드 열고, Gmail 열고, 캘린더 열고. 하나씩 돌아다니면서 확인했다. 30분은 걸렸다.

지금은 이렇다. 텔레그램 열고 “매출 어때?”하면 된다. “피드백 있어?”하면 된다. “오늘 일정은?”하면 된다. 폰에서 1분이면 끝난다.

확인은 AI가 한다. 판단은 내가 한다. 이 구분이 중요하다. 데이터를 모으는 건 사람이 할 일이 아니다.

다음 이야기

지금은 내가 먼저 물어봐야 답이 온다. 다음 편에서는 이걸 뒤집는다. AI가 먼저 말을 건다. 매일 아침 텔레그램이 브리핑을 보내준다. 매출, 일정, 날씨, 이상 징후. 내가 물어보기 전에 정리해서 보내주는 구조다. EP.13에서 계속된다.

자주 묻는 질문

Q. 텔레그램 봇을 왜 쓰나요?

카카오톡은 개인 봇을 못 만든다. 텔레그램은 BotFather에서 봇 만들면 API 토큰이 바로 나온다. 개인 DM이 가능하고, 메시지 수발신이 전부 무료다.

Q. 409 Conflict가 뭔가요?

텔레그램 봇이 메시지를 받는 통로는 하나뿐이다. 두 곳에서 동시에 받으려고 하면 이 에러가 뜬다. 전화 2대가 같은 번호로 수신 대기하는 것과 같다. 한쪽을 끄면 해결된다.

Q. tmux 없이도 되나요?

된다. screen이나 systemd 같은 걸 써도 된다. 핵심은 “터미널을 닫아도 프로세스가 안 죽는 것”이다. 서버에서 봇을 상시 실행하려면 이런 도구가 하나는 필요하다.

Q. 개발 안 해본 사람도 따라할 수 있나요?

봇을 만드는 것 자체는 어렵지 않다. BotFather에서 봇을 만들면 끝이다. 근데 MCP 서버를 연결하려면 TypeScript를 읽을 줄은 알아야 한다. Claude한테 “텔레그램 봇 만들어줘”하면 코드를 짜주긴 한다.

관련 글