토스 자동매매 개발기 시리즈 (Phase 5/전체 16편)
- #0 기반 시스템 구축
- #3 설정 분리 & 재시도 로직
- #7 전략 클래스화
- #9 데이터 영속성 설계
- #13 백테스트 엔진
- #15 읽기전용 대시보드
- #16 텔레그램 봇 명령어 연동 (현재 글)
💡 이번 Phase 5-2 요약
- 목적: python-telegram-bot을 연결해 /status, /holdings, /pause, /resume 명령어를 실제 텔레그램에서 동작하게 만듦
- 핵심 포인트: 봇 서버는 통신만 담당하고 실제 로직은 기존 순수 함수(bot_commands.py, engine_control.py)를 그대로 호출 — 관심사 분리 유지
- 검증: 가짜 Update 객체로 단위테스트 7개 작성, pytest 전체 109개 통과 후 실제 텔레그램 앱에서 /status 응답까지 확인
지난 세션까지 만들어둔 engine_control.py와 bot_commands.py는 로직만 완성된 상태였다. 이번엔 진짜 텔레그램과 붙이는 작업.
봇 토큰 없이 먼저 검증 가능한 부분부터
BotFather로 토큰을 발급받기 전에, 명령어 핸들러 로직 자체는 토큰 없이도 테스트할 수 있다는 걸 활용했다. 순서를 바꿔서 병행 진행.
bot_server.py — python-telegram-bot v22 비동기 핸들러
python-telegram-bot 22 버전은 완전 비동기(async/await) API로 바뀌어서, 아래처럼 CommandHandler를 등록하는 구조가 된다.
from telegram import Update
from telegram.ext import ApplicationBuilder, CommandHandler, ContextTypes
async def status_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
if not is_authorized(update.effective_chat.id):
await update.message.reply_text("권한 없음")
return
text = build_status_text() # bot_commands.py의 순수 함수
await update.message.reply_text(text)
app = ApplicationBuilder().token(TELEGRAM_BOT_TOKEN).build()
app.add_handler(CommandHandler("status", status_handler))
설계 중 발견한 보안 이슈 — 접근 제어 추가
코드를 짜다 보니 봇 사용자명만 알면 아무나 명령을 보낼 수 있다는 문제가 보였다. .env의 TELEGRAM_CHAT_ID와 발신 채팅 ID가 일치할 때만 처리하도록 즉시 보완했다.
def is_authorized(chat_id: int) -> bool:
return str(chat_id) == os.getenv("TELEGRAM_CHAT_ID")
테스트 — 가짜 Update 객체로 서버 없이 검증
실제 텔레그램 서버 연결 없이도 핸들러 로직만 떼어 테스트할 수 있게, Mock Update/Message 객체를 만들어 7개 케이스를 작성했다: 권한 없는 채팅의 명령 거부, /pause·/resume의 실제 상태 변화, /holdings의 인증 실패/성공.
전체 pytest 재실행 결과 109개 전부 통과(기존 102개 + 신규 7개).
실사용 검증 — 채팅 ID를 못 찾아 삽질한 이야기
텔레그램 getUpdates API로 채팅 ID를 확인하려는데 처음엔 "result": []만 나왔다. 원인은 단순했다 — 봇과의 대화창에서 아직 한 번도 메시지를 보낸 적이 없었던 것. “시작” 버튼을 누르고 메시지를 보낸 뒤 재조회하니 정상적으로 채팅 ID가 나왔다.
토큰과 채팅 ID를 .env에 넣고 python bot_server.py를 실행, 실제 텔레그램 앱에서 /status를 보내 정상 응답을 확인했다.
python-telegram-bot v22의 비동기 CommandHandler로 /status, /pause 등을 등록하고, .env의 채팅 ID와 발신 채팅을 비교하는 방식으로 접근 제어를 붙이면 개인용 자동매매 봇에 안전하게 원격 제어 기능을 추가할 수 있다.
FAQ
Q1. python-telegram-bot 버전 22는 이전 버전과 뭐가 다른가요?
완전 비동기(async/await) 기반 API로 전환되어, 핸들러 함수를 코루틴으로 작성해야 합니다.
Q2. 봇 사용자명만 알아도 명령을 보낼 수 있나요?
기본적으로는 가능합니다. 그래서 채팅 ID 화이트리스트 검증을 반드시 추가해야 합니다.
Q3. 채팅 ID는 어떻게 확인하나요?
봇과의 대화창에서 먼저 메시지를 한 번 보낸 뒤 getUpdates API를 조회해야 결과가 나옵니다.
Q4. 실제 텔레그램 서버 없이 테스트가 가능한가요?
가짜 Update/Message 객체를 만들어 핸들러 로직만 분리 테스트할 수 있습니다.
“python-telegram-bot 명령어 핸들러 연동 | 토스 자동매매 개발기 #17”에 대한 1개의 생각