텔레그램 구독자 이중 관리 제거하고 DB 단일화
목차
notify.py 한 파일에 텔레그램 구독자 관리 로직 전체를 재정비했다.
배경: 구독자 목록이 두 군데 살고 있었다
이전 구조에서 텔레그램 알림을 보낼 때 구독자 목록을 어디서 읽어오는지 명확하지 않았다. 코드 어딘가에 하드코딩된 chat_id 리스트가 있고, DB에도 telegram_subscriber 테이블이 따로 있는 상황. 두 곳이 동시에 "진실"인 척 하는 구조였다.
이런 이중 진실(dual source of truth) 상태가 얼마나 위험한지는 운영해보면 바로 안다. 새 구독자를 추가할 때 한 쪽만 업데이트하면 알림이 빠지고, 구독자를 제거할 때도 한 쪽만 삭제하면 계속 수신된다. 팀 입장에서는 "어디를 봐야 맞는 거야?" 라는 질문이 반복되고, 그때마다 코드 뒤져서 확인하는 비용이 쌓인다.
결국 admin_db.telegram_subscriber 를 단일 진실(single source of truth) 으로 못 박는 작업을 이번에 했다.
작업 내용: SSOT 확립 + auto-bootstrap
핵심 변경은 두 가지다.
1. 구독자 조회 경로 단일화
notify.py 안에서 chat_id를 참조하는 모든 경로가 이제 admin_db.telegram_subscriber 테이블 하나만 바라본다. 인메모리 리스트나 설정 파일 기반 fallback 같은 건 제거했다.
# before: 여기저기 분산
CHAT_IDS = [123456789, 987654321] # 하드코딩
def get_subscribers():
db_subs = fetch_from_db()
return db_subs or CHAT_IDS # "DB 없으면 하드코딩 사용" 패턴 → 위험
# after: DB가 유일한 진실
def get_subscribers():
return fetch_from_db("admin_db.telegram_subscriber")
db_subs or CHAT_IDS 패턴이 겉보기엔 안전해 보이지만, DB가 비어있는 상태(예: 새 환경 배포 직후)에 하드코딩 목록으로 fallback 되는 건 사실 버그다. 실수로 구독자를 다 지웠을 때도 fallback 이 작동해서 "다 지웠는데 왜 알림이 와?" 같은 상황이 생긴다.
2. auto-bootstrap
SSOT를 DB로 못 박으면 자연스럽게 따라오는 문제가 있다. 새 환경에서 처음 실행할 때 테이블이 비어있으면 알림이 아무에게도 안 간다. 이걸 방치하면 배포할 때마다 "DB에 구독자 넣는 거 잊지 마세요" 라는 구두 전달이 필요해지고, 언젠가 꼭 누군가 잊는다.
auto-bootstrap은 이 문제를 코드 레벨에서 해결한다. 테이블이 비어있을 때 미리 정의된 기본 구독자 세트를 자동으로 insert 하는 로직이다.
def bootstrap_subscribers_if_empty():
count = count_subscribers()
if count == 0:
default_subs = load_default_subscribers_from_config()
insert_subscribers(default_subs)
logger.info(f"[bootstrap] 기본 구독자 {len(default_subs)}명 등록")
애플리케이션 기동 시점에 한 번 호출하면, 이후로는 DB만 보면 된다. 기본값 자체는 설정 파일에서 읽어오기 때문에 코드 수정 없이 환경별로 다르게 세팅할 수 있다.
왜 이게 중요한가: 운영 복잡도 관점
| 항목 | 변경 전 | 변경 후 |
|---|---|---|
| 구독자 진실 위치 | 코드 + DB (중복) | admin_db.telegram_subscriber 단독 |
| 신규 환경 세팅 | 수동 DB insert 필요 | auto-bootstrap 자동 처리 |
| 구독자 제거 보장 | DB 삭제해도 코드에 남을 수 있음 | DB 삭제 = 즉시 반영 |
| 온콜 디버깅 난이도 | "어디 보면 돼?" | DB 테이블 하나만 확인 |
사내 알림 시스템은 보통 "잘 되고 있으면 아무도 신경 안 쓰다가 문제 생기면 다들 같이 보는" 류의 코드다. 그래서 이런 류의 인프라성 코드일수록 "운영할 때 뭘 봐야 하는가"가 명확해야 한다.
회고
솔직히 이 작업은 기능 추가가 아니다. 코드 관점에서 보면 오히려 줄어드는 쪽이다. 하드코딩 리스트 제거, fallback 로직 제거. 근데 이런 정리 작업을 미루면 미룰수록 "혹시 저 하드코딩된 거 살아있는 거 아냐?" 라는 의심이 매번 생긴다. 팀원이 알림 관련 버그를 잡을 때 확인해야 할 경로가 하나 줄어드는 것, 그게 이 커밋의 실제 가치다.
auto-bootstrap 패턴도 배포 자동화가 성숙할수록 더 자주 쓰게 되는 패턴이다. "처음 실행 시 필요한 초기 데이터를 코드가 직접 심는다"는 발상은 마이그레이션 스크립트나 seed 데이터 개념과 맞닿아 있다. 다음에 비슷한 설정성 데이터가 생기면 같은 패턴 그대로 쓸 것 같다.
끝.
🛒 이 글과 어울리는 추천 상품
*위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.
댓글 0
첫 댓글 달아줘.