AWS

[ AWS ] - sns 활용하여 메일과 메시지 보내기

algml0703 2022. 8. 22. 16:17
반응형

SNS : Simple Notification Service

메일 또는 메시지 전송 기능을 제공하는 aws의 서비스이다. aws의 sns는 크게 A2A와 A2P로 나뉜다. 

Application to Application 의 약자인 A2A란 애플리케이션 간 메시징을 전송하는 것으로, 쉽게 이야기하면 aws의 sns 기능을 aws에서 제공하는 다른 서비스인 lambda, SQS 등의 서비스와 연동하는 것을 의미한다. 예를 들어 Lambda 함수가 구독하는 SNS 주제에 메시지가 게시되면 게시된 메시지의 페이로드와 함께 Lambda 함수가 호출되는 방식이 그러하다.

  반면에 A2P는 Application to Person이라고 하여 사용자에게 메시지를 보내주는 형태이다. 예를 들어 개발자가 주제라고 하는 채널을 생성하고, 주제에 메시지를 올리면 해당 주제를 구독하고 있는 전화번호 또는 메일로 메시지가 전송된다.


S2P 서비스 기능 활용 

[ 콘솔을 통해 서비스 생성하는 경우 ]

1. aws계정에 로그인한 후 콘솔창에 sns를 검색한 후 Simple Notification Service를 선택한다.

2. 메인 화면에서 주제 생성이라고 되어있는 곳에 해당 주제의 이름을 입력 후 다음 단계를 클릭한다.. 주제 이름은 그냥 해당 서비스 구분명이라고 생각하면 될 것 같다.

3. 아래와 같이 세부 정보 부분이 나오면 표준을 선택하고, 주제 생성을 클릭한다

4. 해당 주제를 선택 후 우측 하단에 구독 생성을 클릭한다.

5.  아래와 같이 구독 생성 세부 정보가 나오면 프로토콜 선택하는 부분이 있는데, 이 중에서 프로토콜을 선택한 것에 맞추어 앤드포인트를 입력하면 된다. 예를 들어 프로토콜을 이메일을 선택한 경우 앤드포인트에서는 해당 주제의 메시지를 수신할 이메일을 입력하고, SMS프로토콜을 선택한 경우 앤드포인트에는 해당 주제의 메시지를 수신할 전환번호를 입력하면 된다. 정보 입력 후 구독 생성을 클릭하여 준다.

** 주의할 점은 번호를 입력하는 경우 아래와 같이 +82를 함께 입력하여 주어야 한다. 

6. 현재는 프로토콜을 이메일로 선택 후 구독 생성하였다. 생성된 구독을 보면 상태가 확인 대기 중으로 되어있는 것을 확인 할 수 있다.

이는 구독 생성한 것에 대하여 해당 이메일의 인증이 이루어지지 않았기 때문이다. 해당 이메일의 메일함을 확인하면 아래와 같이 메일이 온 것을 확인할 수 있다. 

해당 메일에 들어가서 Confirm subscription을 클릭하여 주면 된다.

이후 다시 aws 창으로 돌아와 새로고침해주면 상태가 변경된 것을 확인할 수 있다.

7. 이후 주제에 다시 들어가서 (구독이 아니라 주제로 들어가는 것이다.) 우측 상단에 메시지 게시를 클릭한다.

아래와 같이 보낼 제목과 텍스트를 입력한 후 메시지 게시를 클릭하면 메시지가 전송된다.

메일함을 확인해보면 아래와 같이 메일이 온 것을 확인할 수 있다.


[ aws-sdk를 통해 서비스 생성하는 경우 ]

1. 우선 aws sns에 권한을 허용한 계정을 iam계정을 생성한다. iam 계정의 경우 아래의 블로그 글을 참고하여 aws 자격 증명 유형을 엑세스 키 - 프로그래밍 방식을 선택하고, 정책의 경우 AmazonSNSFullAccess 권한을 주어 계정을 생성한다.

2022.06.03 - [AWS] - [ AWS ] - aws I AM 설정 방법

aws-sdk의 경우 각 api 부분만 작성하였다. 필요에 따라 사용하면 될 것 같다. 그리고 aws 개발 문서에 예제 코드가 잘 정리되어 있다.

기본 설정
import AWS from "aws-sdk";
import env from "dotenv";
env.config();

const aws = new AWS.SNS({
  region: process.env.REGION,
  accessKeyId: process.env.ACCESSKEYID,
  secretAccessKey: process.env.SECRETACCESSKEY,
  apiVersion: "2010-03-31",
});

accessKeyId와 secretAccessKey는 반드시 env 파일로 보관하여 사용하여야 한다.

주제 생성
aws.createTopic({ Name: "mytopic_sdk_v" }).promise();

aws sns 콘솔에 들어가보면 아래와 같이 주제가 생성된 것을 확인할 수 있다.

주제 목록
const listTopicsPromise = aws.listTopics({}).promise();

listTopicsPromise
  .then(function (data) {
    console.log(data.Topics);
  })
  .catch(function (err) {
    console.error(err, err.stack);
  });

생성된 모든 주제 목록을 반환하여 준다.

주제 삭제
const deleteTopicPromise = aws
  .deleteTopic({
    TopicArn: "...",
  })
  .promise();

deleteTopicPromise
  .then(function (data) {
    console.log("Topic Deleted");
  })
  .catch(function (err) {
    console.error(err, err.stack);
  });

TopicArn 부분에는 삭제하려는 주제의 arn을 넣으면 된다.

주제 속성 가져오기
const getTopicAttribsPromise = aws
  .getTopicAttributes({
    TopicArn: "...",
  })
  .promise();

getTopicAttribsPromise
  .then(function (data) {
    console.log(data);
  })
  .catch(function (err) {
    console.error(err, err.stack);
  });
주제에 메시지 올리기 
let params = {
  Message: '안녕하세요',
  TopicArn: '...',
};

const publishTextPromise = aws
  .publish(params)
  .promise();

publishTextPromise
  .then(function (data) {
    console.log(
      `Message ${params.Message} sent to the topic ${params.TopicArn}`
    );
    console.log(data);
    console.log('MessageID is ' + data.MessageId);
  })
  .catch(function (err) {
    console.error(err, err.stack);
  });
특정 주제에 대한 구독 목록
const subslistPromise = aws
  .listSubscriptionsByTopic({
    TopicArn: "...",
  })
  .promise();

subslistPromise
  .then(function (data) {
    console.log(data);
  })
  .catch(function (err) {
    console.error(err, err.stack);
  });
구독 생성
// 이메일 등록하는 경우 
const params = {
  Protocol: 'email', //sms  /* required */,
  TopicArn: '....' /* required */,
  Endpoint: 'test@gmail.com', ,
};

// 전화번호 등록하는 경우 
// const params = {
//   Protocol: 'sms', //sms  /* required */,
//   TopicArn: '...' /* required */,
//   Endpoint: '+8201012345678',
// };

var subscribePromise = aws
  .subscribe(params)
  .promise();

// Handle promise's fulfilled/rejected states
subscribePromise
  .then(function (data) {
    console.log('Subscription ARN is ' + data.SubscriptionArn);
  })
  .catch(function (err) {
    console.error(err, err.stack);
  });
구독 취소
const unSubscribePromise = aws
  .unsubscribe({
    SubscriptionArn: "...",
  })
  .promise();

unSubscribePromise
  .then(function (data) {
    console.log(data);
  })
  .catch(function (err) {
    console.error(err, err.stack);
  });
sms 메시지 전송
const params = {
  Message: '안녕하세요' /* required */,
  PhoneNumber: '+8201012345678',
};

// Create promise and SNS service object
const publishTextPromise = aws
  .publish(params)
  .promise();

// Handle promise's fulfilled/rejected states
publishTextPromise
  .then(function (data) {
    console.log('MessageID is ' + data.MessageId);
  })
  .catch(function (err) {
    console.error(err, err.stack);
  });
sms 속성 설정
const params = {
  attributes: {
    /* required */
    DefaultSMSType: 'Promotional',
    //'DefaultSMSType': 'Promotional' /* lowest cost */
  },
};

var setSMSTypePromise = aws
  .setSMSAttributes(params)
  .promise();

setSMSTypePromise
  .then(function (data) {
    console.log(data);
  })
  .catch(function (err) {
    console.error(err, err.stack);
  });

promotional 이외에도 tranactional이 존재하는데 promotional이 더욱 저렴하다.

sms 옵트 아웃 확인 
** 옵트아웃이란 정보주체의 동의를 받지 않고 개인정보를 수집·이용한 후, 당사자가 거부 의사를 밝히면 개인정보 활용을 중지하는 것을 의미한다. 즉 사용자가 구독을 취소하였는지 확인하는 것이다.
const phonenumPromise = aws
  .checkIfPhoneNumberIsOptedOut({ phoneNumber: '+8201012345678' })
  .promise();

phonenumPromise
  .then(function (data) {
    console.log(data);
    console.log('Phone Opt Out is ' + data.isOptedOut);
  })
  .catch(function (err) {
    console.error(err, err.stack);
  });
sms 옵트아웃한 번호 목록 확인
const phonelistPromise = aws
  .listPhoneNumbersOptedOut({})
  .promise();

// Handle promise's fulfilled/rejected states
phonelistPromise
  .then(function (data) {
    console.log(data);
  })
  .catch(function (err) {
    console.error(err, err.stack);
  });
sms 인증 otp 보내기
const params = {
  PhoneNumber: "+8201012345678" /* required */,
  LanguageCode: "kr-KR",
};
const phonenumberPromise = aws.createSMSSandboxPhoneNumber(params).promise();

phonenumberPromise
  .then(function (data) {
    console.log(data);
  })
  .catch(function (err) {
    console.error(err, err.stack);
  });

LanguageCode는 de_DE | en_GB | en_US | es_419 | es_ES | fr_CA | fr_FR | it_IT | jp_JP | kr_KR | pt_BR | zh_CN | zh_TW가 올 수 있다.

인증 otp 보내기 - otp 확인
const params = {
  OneTimePassword: "..." /* required */,
  PhoneNumber: "+8201012345678" /* required */,
};
const phonenumberPromise = aws.verifySMSSandboxPhoneNumber(params).promise();

phonenumberPromise
  .then(function (data) {
    console.log(data);
  })
  .catch(function (err) {
    console.error(err, err.stack);
  });

 

 

출처 

반응형