## 왜 알림 시스템을 중앙화해야 할까?
여러 스크립트에서 텔레그램, 슬랙 등의 알림 API를 직접 호출하다 보면 몇 가지 문제가 발생합니다.
- **발송 이력 추적 불가**: 누가, 언제, 어떤 메시지를 보냈는지 기록이 없음
- **토큰 관리 어려움**: API 키가 코드 곳곳에 하드코딩됨
- **재사용성 부족**: 동일한 발송 로직이 중복 구현됨
이번 글에서는 분산된 알림 발송을 중앙 시스템으로 통합하고, 서비스를 새로운 VM 환경으로 안전하게 이전한 경험을 공유합니다.
---
## 1. 중앙 발송 시스템 설계
### 핵심 구조
**CLI 스크립트 (telegram_send.py)**
```python
#!/usr/bin/env python3
import sys
import psycopg2
from telegram import Bot
def send_and_log(message, channel):
# 1. 텔레그램 발송
bot = Bot(token=os.getenv('TELEGRAM_TOKEN'))
bot.send_message(chat_id=channel, text=message)
# 2. DB에 이력 기록
conn = psycopg2.connect(DB_CONFIG)
cursor = conn.cursor()
cursor.execute("""
INSERT INTO telegram_send_logs (message, channel, sent_at)
VALUES (%s, %s, NOW())
""", (message, channel))
conn.commit()
if __name__ == '__main__':
send_and_log(sys.argv[1], sys.argv[2])
```
**Python 모듈 (telegram_utils.py)**
```python
import subprocess
def alert_infra(message):
"""인프라 채널에 알림 발송"""
subprocess.run([
'python3', '/opt/scripts/telegram_send.py',
message, 'infra_channel'
])
def alert_ops(message):
"""운영 채널에 알림 발송"""
subprocess.run([
'python3', '/opt/scripts/telegram_send.py',
message, 'ops_channel'
])
```
### DB 스키마
```sql
CREATE TABLE telegram_send_logs (
id SERIAL PRIMARY KEY,
message TEXT NOT NULL,
channel VARCHAR(100),
sent_at TIMESTAMP DEFAULT NOW(),
script_name VARCHAR(255),
status VARCHAR(20) DEFAULT 'success'
);
```
---
## 2. 기존 스크립트 마이그레이션 전략
### Before: 직접 API 호출
```python
import requests
def backup_complete():
# 문제: 토큰 노출, 로깅 없음
requests.post(
'https://api.telegram.org/bot{TOKEN}/sendMessage',
json={'chat_id': '-123456', 'text': 'Backup done'}
)
```
### After: 중앙 모듈 사용
```python
from telegram_utils import alert_infra
def backup_complete():
alert_infra('백업 완료')
```
### 마이그레이션 작업량
- 총 44개 스크립트에 `from telegram_utils import ...` 추가
- 30개 이상의 직접 API 호출 코드 주석 처리
- 기존 코드는 롤백 대비 보존
---
## 3. VM 마이그레이션 체크리스트
### 이전 대상 서비스
- API 서버 3개 (각각 다른 포트로 운영)
- 데이터 처리 서비스
- 이미지 프록시 서버
### 안전한 이전 절차
**1단계: 새 VM 환경 준비**
```bash
# Docker Compose 파일 복사
scp docker-compose.yml new-vm:/opt/services/
# 환경 변수 설정
scp .env new-vm:/opt/services/
# 이미지 빌드/풀
docker-compose pull
```
**2단계: 트래픽 전환**
- L4/L7 로드밸런서 설정 변경
- 포트 포워딩 규칙 업데이트
- 헬스체크 확인 후 전환
**3단계: 검증**
```bash
# 서비스 상태 확인
curl http://new-vm:51051/health
curl http://new-vm:51054/health
# 로그 모니터링
docker-compose logs -f --tail=100
```
### 롤백 계획
- 기존 서버에 소스코드/이미지 보존
- `docker-compose up -d`로 즉시 복구 가능
- DNS TTL을 짧게 설정하여 빠른 전환 지원
---
## 4. 배운 점과 주의사항
### 중앙화의 이점
1. **감사 추적**: 모든 발송 이력을 SQL로 조회 가능
2. **에러 핸들링**: 발송 실패 시 재시도 로직 추가 용이
3. **비용 절감**: API 호출량 모니터링으로 중복 발송 방지
### VM 마이그레이션 팁
- **스테이트리스 설계**: 세션/캐시는 Redis 등 외부 저장소 사용
- **점진적 전환**: 트래픽의 10% → 50% → 100% 단계적 이동
- **메시지 큐 유지**: Kafka 같은 중요 인프라는 무중단 운영 우선
### 피해야 할 실수
- 환경 변수 누락으로 인한 서비스 장애
- 포트 충돌 (기존 VM에서 사용 중인 포트 확인 필수)
- 방화벽 규칙 미설정
---
## 마치며
알림 시스템 중앙화는 단순히 코드를 정리하는 것을 넘어, **운영 가시성**과 **유지보수성**을 크게 향상시킵니다. VM 마이그레이션도 충분한 준비와 롤백 계획이 있다면 안전하게 진행할 수 있습니다.
다음 단계로는 발송 실패 알림, 발송량 제한(rate limiting), 다채널 통합(슬랙, 이메일 등)을 고려해볼 수 있습니다.
**참고 자료**
- [Python subprocess 문서](https://docs.python.org/3/library/subprocess.html)
- [Docker Compose 마이그레이션 가이드](https://docs.docker.com/compose/)
- [PostgreSQL 로깅 베스트 프랙티스](https://www.postgresql.org/docs/current/runtime-config-logging.html)