← 목록

SNS SMS 크로스 리전 구성: Seoul에서 Tokyo 경유 문자 알림 발송

Seoul 리전의 SMS 미지원 제약을 Tokyo 리전 경유로 해결. CloudWatch Alarm → SNS → Lambda → Tokyo SNS → SMS 파이프라인 구축과 Sandbox 환경 운영 노하우

2024-08-10AWSSNSSMSMonitoringLambda

배경

CloudWatch 알람 발생 시 운영 담당자에게 문자(SMS)를 보내야 하는데, Seoul 리전(ap-northeast-2)은 SNS SMS 발송을 지원하지 않는다. 이 제약을 해결하기 위해 Tokyo 리전(ap-northeast-1)을 경유하는 크로스 리전 SMS 발송 구조를 설계했다.


아키텍처

CloudWatch Alarm (Seoul)
  → SNS Topic: cloudwatch-alarm-topic (Seoul)
    → Lambda: sns-forward-to-tokyo (Seoul)
      → SNS Topic: cloudwatch-alarm-topic-tokyo (Tokyo)
        → SMS 발송 (6명 구독)

Seoul에서 발생한 알람 메시지를 Lambda가 받아서 Tokyo 리전의 SNS Topic으로 전달하고, Tokyo SNS가 등록된 전화번호로 SMS를 발송하는 구조다.


Lambda: sns-forward-to-tokyo

Seoul SNS Topic의 구독자로 등록된 Lambda 함수가 메시지를 받아 Tokyo SNS로 포워딩한다.

import boto3
import json
 
# Tokyo 리전의 SNS 클라이언트
sns_tokyo = boto3.client('sns', region_name='ap-northeast-1')
 
TOKYO_TOPIC_ARN = 'arn:aws:sns:ap-northeast-1:[account-id]:cloudwatch-alarm-topic-tokyo'
 
def lambda_handler(event, context):
    # Seoul SNS에서 전달된 메시지 파싱
    sns_message = event['Records'][0]['Sns']
    subject = sns_message.get('Subject', 'CloudWatch Alarm')
    message = sns_message['Message']
 
    # 메시지를 SMS에 적합한 형태로 가공
    # SNS SMS는 160자 제한이 있으므로 핵심 정보만 추출
    alarm_info = json.loads(message)
    alarm_name = alarm_info.get('AlarmName', 'Unknown')
    new_state = alarm_info.get('NewStateValue', 'Unknown')
    reason = alarm_info.get('NewStateReason', '')[:80]
 
    sms_message = f"[알람] {alarm_name}\n상태: {new_state}\n{reason}"
 
    # Tokyo SNS Topic으로 발행
    sns_tokyo.publish(
        TopicArn=TOKYO_TOPIC_ARN,
        Subject=subject,
        Message=sms_message
    )
 
    return {'statusCode': 200}

IAM 권한

Lambda 실행 역할에 Tokyo 리전 SNS 발행 권한이 필요하다.

{
  "Effect": "Allow",
  "Action": "sns:Publish",
  "Resource": "arn:aws:sns:ap-northeast-1:[account-id]:cloudwatch-alarm-topic-tokyo"
}

Tokyo SNS SMS 설정

Sandbox 환경

Tokyo 리전의 SNS SMS는 Sandbox 상태로 운영 중이다. Sandbox에서는 사전 등록(Verified)된 전화번호에만 SMS를 발송할 수 있다.

항목상태
월간 지출 한도$50
전송 성공 샘플링100%
샌드박스 상태Sandbox (등록된 번호만 발송 가능)

전화번호 등록

SMS를 수신할 담당자 번호를 Sandbox에 등록한다.

SNS 콘솔 (Tokyo) → Mobile → Text messaging (SMS)
→ Sandbox destination phone numbers → Add phone number
→ 인증 코드 수신 → Verified 완료

운영팀 담당자 번호를 등록하여 CloudWatch 알람 SMS를 수신한다.

Sandbox 해제(프로덕션 전환)를 위해서는 AWS Support에 사용 사례를 설명하고 승인을 받아야 한다. 현재는 수신 대상이 내부 담당자로 한정되어 있어 Sandbox로 충분하다.


SNS Topic 구독 구성

Seoul SNS Topic

Topic구독 프로토콜대상용도
cloudwatch-alarm-topicLambdasns-forward-to-tokyoSMS 포워딩 허브

이 Topic에는 SMS 외에도 이메일 구독이 연결되어 있어, 하나의 알람이 이메일 + SMS 동시 발송된다.

Tokyo SNS Topic

Topic구독 프로토콜구독자 수용도
cloudwatch-alarm-topic-tokyoSMS6명CloudWatch 알람 SMS
서비스별 타임아웃 알림 TopicSMS1~6명서비스 타임아웃 SMS
운영 알림 TopicSMS1명운영 SMS

SMS 알림 대상 CloudWatch 알람

Seoul의 cloudwatch-alarm-topic에 연결된 알람들이 Tokyo를 경유하여 SMS로 전달된다.

서비스알람 항목
애플리케이션 서버 (Worker Node, 코디네이터)CPU, 메모리, 디스크
DB 서버 (Primary)CPU, 메모리, 디스크(OS/데이터 볼륨), SWAP
애플리케이션 서버 (PRD)CPU, 메모리, 디스크(OS/SW 볼륨), SWAP
DB 서버 (Replica)CPU, 메모리, 디스크(OS/데이터 볼륨)
FTP 서버 (Windows)CPU, 메모리, 다중 드라이브
연동 서버 (IS)CPU, 메모리, 디스크(OS/데이터)
배치 서비스메모리

트러블슈팅

SMS 미수신 문제

SMS가 발송되었으나 수신되지 않는 경우, Tokyo SNS의 전송 상태 로그를 확인한다.

SNS 콘솔 (Tokyo) → Text messaging (SMS) → Message delivery status
→ CloudWatch Logs에서 전송 성공/실패 로그 확인

주요 실패 원인:

메시지 길이 제한

SNS SMS는 단일 메시지 160자(영문) 또는 70자(한글) 제한이 있다. CloudWatch 알람 메시지는 원본이 길기 때문에, Lambda에서 핵심 정보만 추출하여 SMS에 적합한 길이로 가공한다.


비용

항목비용
SNS SMS 발송 (한국)$0.047 / 건
Lambda 실행무료 (프리티어)
SNS Topic 발행무료 (월 100만 건까지)
월간 지출 한도$50 (설정 변경 가능)

월 100건 SMS 발송 기준 약 $4.7 수준이다.


정리


배운 점

클라우드를 쓰면 리전은 배포 위치 정도로만 생각하기 쉽다. 그런데 서비스마다 리전별로 제공 범위가 다르고, 그 차이가 설계를 바꾼다. Seoul에서 SMS를 못 보낸다는 사실 하나 때문에 Lambda 포워더가 아키텍처에 추가됐다.

이런 제약은 문서를 읽어서 피하는 것보다, 필요한 기능을 리전 기준으로 먼저 확인하는 습관으로 피하는 편이 빠르다. "이 리전에서 이게 되는가"를 설계 전에 확인하는 단계를 그 뒤로 넣게 됐다.

경유 구조는 단순하지만 장애 지점이 하나 늘어난다는 뜻이기도 하다. 통합 모니터링 시스템 구축에서 알림 경로를 여러 채널로 나눠 둔 이유도, 한 경로가 막혔을 때 전체가 조용해지는 상황을 피하기 위해서였다.


이어 읽기