서비스
home

[GAS] 네이버 SENS API로 문자 발송하기

목적

네이버 SENS SMS API 를 앱스 스크립트에서 사용해서 문자를 발송하는 방법을 이해합니다.

네이버 SENS SMS API 사용하기

네이버 SENS SMS API 를 사용하기 위해서는 우선 네이버 클라우드 플랫폼에 가입해야 합니다.
네이버답게 네이버 계정 로그인을 지원해서 편합니다.
가입을 완료하고, 마이페이지 > 계정 관리에 들어가면 인증키 관리 메뉴가 있습니다. 여기서 신규 API 인증키 생성을 클릭해서 새로운 Access Key ID와 Secret Key를 얻습니다. 잘 기록해두세요.
그리고 메뉴 중에 콘솔로 들어갑니다.
우측 메뉴에서 Services 을 클릭하면 엄청나게 많은 메뉴가 나오는데, 검색창에 SENS 를 입력하면 메뉴가 검색됩니다.
SENS(Simple & Easy Notification Service) 메뉴에 접속해서 프로젝트 생성하기를 클릭합니다.
프로젝트를 생성하면 이제 Project 메뉴에서 생성한 프로젝트를 볼 수 있고, 서비스 ID를 얻을 수 있습니다. 우측의 자물쇠 모양을 누르면 OPEN API Key 를 확인할 수 있는데, 여기서 SMS의 ID를 복사해서 기록해둡니다. 여기서 Secret Key 는 사용하지 않습니다.
SMS을 발송하기 위해서는 법령에 따라 발신번호 사전등록을 해두어야 합니다. 좌측의 메뉴의 SMS > Calling Number 에서 서류인증 또는 본인인증으로 등록합니다. 서류인증의 경우에는 1일 정도면 승인이 됩니다.
여기까지 진행하는 것으로 콘솔에서 할 일은 끝났습니다. 이제 앱스 스크립트로 가보실까요?

UrlFetchApp을 사용해 SMS 보내기

UrlFetchApp 사용하기

UrlFetchApp을 사용해서 API를 호출하는 방법은 이전 포스팅에서 다루었습니다.
기본적으로 앱스 스크립트 공식 문서에 나온 것처럼 할 수 있습니다.
// Make a POST request with a JSON payload. var data = { 'name': 'Bob Smith', 'age': 35, 'pets': ['fido', 'fluffy'] }; var options = { 'method' : 'post', 'contentType': 'application/json', // Convert the JavaScript object to a JSON string. 'payload' : JSON.stringify(data) }; UrlFetchApp.fetch('https://httpbin.org/post', options);
JavaScript
복사

NAVER SENS API HEADER 준비하기

그런데 NAVER SENS SMS API 를 사용하기 위해서는 중요한 점으로 header에 정보를 넣는 것이 있습니다. 단순히 ID, PWD 를 문자열로 넣는 것이 아니라, 암호화된 서명을 넣는 부분이라 조금 까다로울 수 있는데, 어떻게 하는지 함께 살펴보시죠.
header에 어떤 정보가 들어가야 하는지는 네이버 SMS API 가이드에 다음과 같이 소개되어 있습니다.
POST https://sens.apigw.ntruss.com/sms/v2/services/{serviceId}/messages Content-Type: application/json; charset=utf-8 x-ncp-apigw-timestamp: {Timestamp} x-ncp-iam-access-key: {Sub Account Access Key} x-ncp-apigw-signature-v2: {API Gateway Signature}
JavaScript
복사
4가지 항목을 넣어주어야 하는데, 어떻게 넣어주어야 한다는 말일까요?
1.
우선 Content-Type은 지정된 대로 application/json; charset=utf-8 를 넣습니다.
2.
x-ncp-apigw-timestamp는 “1970년 1월 1일 00:00:00 협정 세계시(UTC)부터의 경과 시간을 밀리초(Millisecond)로 나타냄”이라고 설명되어 있는데, 코드는 간단합니다. 마지막에 toString()으로 문자열 변환을 꼭 해주세요.
new Date().getTime().toString()
JavaScript
복사
3.
x-ncp-iam-access-key는 계정관리 > 인증키 관리에서 받은 Access Key ID입니다.
4.
x-ncp-apigw-signature-v2가 조금 까다롭습니다. 인증키 생성가이드를 참고해보면, 지금까지 확보한 여러 정보를 합쳐서 Secret Key로 암호화해야 하는데 어떻게 할 수 있을까요? 단계별로 살펴보겠습니다.
a.
정보 병합 다음과 같이 지금까지 얻은 정보들을 hmac 변수에 할당해줍니다. 백틱으로 문자열을 만들어줄 수 있지만, 이 경우에는 자동 문서 서식 기능을 사용하다보면 공백이 추가로 발생하기 때문에 +를 사용해서 만들어줍니다.
let space = ' ' //한 칸 공백 let newLine = '\n' //개행 문자 let method = 'POST' let serviceId = '콘솔에서 얻은 서비스ID' let uri = `/sms/v2/services/${serviceId}/messages` let timestamp = new Date().getTime().toString() let accessKey = '인증키 관리에서 받은 Access Key ID' let secretKey = '인증키 관리에서 Access Key ID와 매칭되는 Secret Key' let hmac = method + space + uri + newLine + timestamp + newLine + accessKey
JavaScript
복사
b.
암호화 Utilities 클래스의 computeHmacSha256Signature 메서드를 사용해서 hmac를 secretKey로 암호화해 줍니다.
let byteSignature = Utilities.computeHmacSha256Signature(hmac, secretKey)
JavaScript
복사
c.
base64 인코딩 Byte 형식의 결과를 base64Encode 메서드로 인코딩합니다. 마지막에 toString()으로 문자열 변환을 해주세요.
let signature = Utilities.base64Encode(byteSignature).toString()
JavaScript
복사
이제 header에 필요한 signature 를 얻었습니다.

SMS BODY 준비하기

문자를 발송하려면 내용을 준비해야하겠지요? 이것도 네이버 가이드에서 제공하는 양식을 따라서 만들어 줍니다.
let body = { "type": "SMS", "contentType": "COMM", "countryCode": "82", "from": "발신번호에 등록한 전화번호", "content": "내용", "messages": [ { "to": "받는사람 전화번호", "content": "문자 보내기 API 테스트입니다." } ] }
JavaScript
복사
위와 같이 작성하는 경우 실제 내용은 messages의 content로 발송됩니다. 관련된 조건은 가이드에 잘 설명되어 있습니다.
문자 발송 관련 조건
최대 지원 가능한 사이즈 초과 시 잘림 처리되어 발송 됩니다.
메시지(subject, content) 인코딩은 EUC-KR 기준으로 발송되며, 지원하지 않는 이모지 문자 포함 시 발송에 실패합니다.
messages 내에 subject, content를 정의하지 않으면 기본 subject, content로 지정된 값으로 발송 됩니다.
messages 내에 subject, content가 기본 subject, content 보다 우선순위가 높습니다.
type이 MMS인데 첨부하려는 파일이 없는경우 LMS로 발송됩니다.
reserveTime, scheduleCode를 모두 요청하는 경우 예약 발송으로 처리됩니다. (예약발송이 우선순위가 높음)
그런데 아까 header 의 Content-Type을 json 으로 지정하였었죠? 때문에 body를 json 으로 변환시켜주어야 합니다.
let jsonBody = JSON.stringify(body)
JavaScript
복사

API로 문자 발송하기

이제 모든 것이 준비되었으니, 문자를 발송해볼까요?
UrlFetchApp의 매개변수(options)의 headers 부분에 준비한 header 를 넣고, payload에 jsonBody를 넣어줍니다. method는 POST로 보내주어야 합니다.
최종 코드는 다음과 같습니다.
function sendSMS() { let body = { "type": "SMS", "contentType": "COMM", "countryCode": "82", "from": "발신번호에 등록한 전화번호", "content": "내용", "messages": [ { "to": "받는사람 전화번호", "content": "문자 보내기 API 테스트입니다." } ] } let jsonBody = JSON.stringify(body) let space = ' ' //한 칸 공백 let newLine = '\n' //개행 문자 let method = 'POST' let serviceId = '콘솔에서 얻은 서비스ID' let uri = `/sms/v2/services/${serviceId}/messages` let timestamp = new Date().getTime().toString() let accessKey = '인증키 관리에서 받은 Access Key ID' let secretKey = '인증키 관리에서 Access Key ID와 매칭되는 Secret Key' let hmac = method + space + uri + newLine + timestamp + newLine + accessKey let byteSignature = Utilities.computeHmacSha256Signature(hmac, secretKey) let signature = Utilities.base64Encode(byteSignature).toString() let apiUrl = `https://sens.apigw.ntruss.com/sms/v2/services/${serviceId}/messages` let options = { 'method': method, 'muteHttpExceptions': true, 'headers': { 'Content-Type': 'application/json; charset=utf-8', 'x-ncp-apigw-timestamp': timestamp, 'x-ncp-iam-access-key': accessKey, 'x-ncp-apigw-signature-v2': signature }, 'payload': jsonBody } let response = UrlFetchApp.fetch(apiUrl, options) Logger.log(response) }
JavaScript
복사
실행했을 때, 다음과 같은 응답을 받으면 성공한 것입니다.
{"statusCode":"202","statusName":"success","requestId":"1ec0356537c14fec95435f3a65d65248","requestTime":"2022-08-31T10:35:00.687"}
JavaScript
복사

관련 포스팅