python-telegram-bot 명령어 핸들러 연동 | 토스 자동매매 개발기 #17

🌐 Read in English

💡 이번 Phase 5-2 요약

  • 목적: python-telegram-bot을 연결해 /status, /holdings, /pause, /resume 명령어를 실제 텔레그램에서 동작하게 만듦
  • 핵심 포인트: 봇 서버는 통신만 담당하고 실제 로직은 기존 순수 함수(bot_commands.py, engine_control.py)를 그대로 호출 — 관심사 분리 유지
  • 검증: 가짜 Update 객체로 단위테스트 7개 작성, pytest 전체 109개 통과 후 실제 텔레그램 앱에서 /status 응답까지 확인

지난 세션까지 만들어둔 engine_control.pybot_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))

설계 중 발견한 보안 이슈 — 접근 제어 추가

코드를 짜다 보니 봇 사용자명만 알면 아무나 명령을 보낼 수 있다는 문제가 보였다. .envTELEGRAM_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를 보내 정상 응답을 확인했다.

FAQ

Q1. python-telegram-bot 버전 22는 이전 버전과 뭐가 다른가요?

완전 비동기(async/await) 기반 API로 전환되어, 핸들러 함수를 코루틴으로 작성해야 합니다.

Q2. 봇 사용자명만 알아도 명령을 보낼 수 있나요?

기본적으로는 가능합니다. 그래서 채팅 ID 화이트리스트 검증을 반드시 추가해야 합니다.

Q3. 채팅 ID는 어떻게 확인하나요?

봇과의 대화창에서 먼저 메시지를 한 번 보낸 뒤 getUpdates API를 조회해야 결과가 나옵니다.

Q4. 실제 텔레그램 서버 없이 테스트가 가능한가요?

가짜 Update/Message 객체를 만들어 핸들러 로직만 분리 테스트할 수 있습니다.

🎉 이걸로 Phase 0~5 전체가 완료되었다. 다음은 Phase 6(운영 자동화) — APScheduler 또는 systemd/cron으로 넘어갈 예정.

👉 시리즈 전체 목차 보기

“python-telegram-bot 명령어 핸들러 연동 | 토스 자동매매 개발기 #17”에 대한 1개의 생각

댓글 남기기