사이트 접수 알림을 텔레그램 봇으로 받기

사이트에 신청·문의 폼을 만들었는데, 들어온 줄 모르고 며칠씩 방치되면 신뢰가 무너진다. 이 문서는 접수가 들어오는 순간 내 텔레그램으로 알림이 오게 만드는 전 과정을 기록한 것이다. 2026-08-26 사교원 자체서버(햇소자·망남 마을학교 접수)에 실제로 적용하며 겪은 함정까지 그대로 담았다.

전체 그림

방문자가 폼 제출 → 사이트 서버가 접수 저장 → 서버가 텔레그램 봇 API 호출 → 내 텔레그램에 알림

필요한 것은 딱 두 가지 값이다:

무엇인가어디서 얻나
봇 토큰봇의 비밀 열쇠 (1234567:AAxx... 형태)BotFather에서 봇 생성 시
chat id알림을 보낼 방의 번호봇에게 메시지 보낸 뒤 getUpdates로 확인

1단계 — 봇 만들기 (휴대폰, 3분)

  1. 텔레그램 검색창에 BotFather 검색
  2. ⚠️ 가짜 주의: 사칭 봇이 많다. 진짜는 ① 아이디가 정확히 @BotFather (뒤에 숫자·밑줄 없음) ② 이름 옆 파란 공식 인증 체크마크 ③ 월간 사용자 수백만 명. “구독(subscribe)” 어쩌고 하는 봇은 전부 가짜다 — 차단하고 나올 것.
  3. 진짜 BotFather에서 /newbot 입력 → 두 가지를 차례로 묻는다:
    • 이름(표시용, 한글 가능): 예) 사교원 알림
    • 아이디(영문, 반드시 bot으로 끝나야 하고 전 세계 유일): 예) sakyowon_alarm_2026_bot
    • “already taken”이 나오면 숫자를 바꿔 재시도
  4. “Done! Congratulations…” 메시지에 토큰이 온다. 복사해 두되:

🔴 토큰은 비밀번호다. 단체방·문서·AI 채팅창 어디에도 붙여넣지 말 것. 토큰이 유출되면 남이 내 봇 행세를 할 수 있다. 유출됐다면 BotFather에서 /revoke로 재발급.

2단계 — 알림 받을 곳 정하기 (휴대폰, 1분)

A. 나 혼자 받기 (간단, 권장) : BotFather 메시지의 t.me/봇아이디 링크를 눌러 봇과 대화방을 열고 → START(시작) 버튼 → 아무 메시지 하나 전송 (“안녕” 등).

B. 단체방으로 받기 : 단체방 → 멤버 추가 → 봇 아이디 검색해 초대 → 방에 /start 라고 전송. ⚠️ 봇은 기본 설정(privacy mode)에서 단체방의 일반 대화를 못 본다. 반드시 /로 시작하는 명령을 보내야 다음 단계에서 방 번호가 잡힌다.

3단계 — 방 번호(chat id) 확인 (서버 터미널)

명령이 길면 복사가 끊기므로 두 줄로 나눠 실행한다:

TOKEN=여기에토큰
curl -s "https://api.telegram.org/bot$TOKEN/getUpdates" | grep -o '"chat":{"id":[-0-9]*'
  • 주소의 bot이라는 글자 바로 뒤에 토큰이 붙는 구조다 (/bot1234567:AAxx.../getUpdates) — bot을 지우면 안 된다.
  • 결과 "chat":{"id":55676976 에서 숫자가 방 번호. 1:1이면 양수, 단체방이면 -100… 마이너스 숫자 — 마이너스까지 포함해 쓴다.
  • 빈 결과 {"ok":true,"result":[]} 가 나오면: 2단계 메시지를 한 번 더 보내고 재실행. (봇이 받은 메시지가 있어야 방 번호가 보인다)
  • 404 Not Found/401 Unauthorized: 토큰이 잘못 들어간 것 — TOKEN= 줄부터 다시.

4단계 — 서버에 연결

환경변수 등록 (사교원 자체서버 기준)

echo "SAKYOWON_TG_TOKEN=$TOKEN" >> /etc/sakyowon-api.env
echo "SAKYOWON_TG_CHAT=방번호" >> /etc/sakyowon-api.env
systemctl restart sakyowon-api

⚠️ 한 줄씩 복사할 것. 여러 줄을 한꺼번에 붙여넣다 줄이 겹치면 echo "..." >>echo "..." 같은 기형 명령이 만들어져 토큰이 잘못된 형태로 저장된다(실제 사고 사례). 의심되면 grep -c "TG_TOKEN" /etc/sakyowon-api.env1인지, grep "TG_TOKEN" /etc/sakyowon-api.env | grep -c " "0(줄 안에 공백 없음)인지 확인. 잘못됐으면 sed -i '/SAKYOWON_TG_TOKEN/d' /etc/sakyowon-api.env 로 지우고 다시.

서버 코드 (Python, 표준 라이브러리만)

새 사이트를 만들 때 이 함수를 접수 저장 직후에 호출하면 된다:

import json, os, urllib.request
 
TG_TOKEN = os.environ.get("SAKYOWON_TG_TOKEN", "")
TG_CHAT  = os.environ.get("SAKYOWON_TG_CHAT", "")
 
def notify_telegram(text):
    if not (TG_TOKEN and TG_CHAT):
        return                      # 미설정이면 조용히 건너뜀
    try:
        payload = json.dumps({"chat_id": TG_CHAT, "text": text}).encode("utf-8")
        req = urllib.request.Request(
            f"https://api.telegram.org/bot{TG_TOKEN}/sendMessage",
            data=payload, headers={"Content-Type": "application/json"})
        urllib.request.urlopen(req, timeout=5).read()
    except Exception:
        pass                        # 알림 실패가 접수 자체를 막으면 안 된다

설계 원칙 두 가지:

  • 토큰은 코드·깃에 절대 넣지 않는다 — 환경변수로만 주입.
  • 알림 실패는 삼킨다 — 텔레그램이 죽어도 방문자의 접수는 저장돼야 한다.

5단계 — 끝까지 테스트

설정을 “했다”와 “알림이 온다”는 다르다. 실제 폼으로 테스트 접수를 한 건 넣어서 휴대폰에 알림이 도착하는 것까지 확인해야 끝이다.

[문의] 데카 테스트 (000-0000-0000)
텔레그램 알림 연결 확인용 테스트입니다. …

안 오면: journalctl -u sakyowon-api -n 20 --no-pager 로 서버 로그 확인 → 대부분 토큰 오타·env 기형 줄·재시작 누락 셋 중 하나다.

함정 요약 (오늘 실제로 밟은 것들)

  1. 가짜 BotFather — 인증 체크마크 없는 봇에게 말 걸었음. 봇 이름만 말한 정도는 피해 없음. 차단하고 진짜를 찾을 것.
  2. 아이디 단계에서 멈춤 — 토큰은 이름+아이디 둘 다 보내야 나온다.
  3. 긴 명령 반쪽 복사 — 파이프(|)부터 시작하는 반쪽이 붙으면 터미널이 멈춘 듯 보인다. Ctrl+C 후 두 줄 나누기 방식으로.
  4. 여러 줄 한꺼번에 붙여넣기 사고 — env에 기형 줄이 들어간다. 한 줄씩.
  5. 단체방 privacy mode — 일반 메시지로는 chat id가 안 잡힌다. /start를 보낼 것.

작성: 데카 · 2026-08-26 · 사교원 자체서버(햇소자) 알림 구축 실전 기록. 관련: 서버 코드 원본은 sakyowon-site server/app.pynotify_telegram.