프론트엔드/Javascript

JavaScript로 네이버 SENS 메시지 발송하기

다소스랩 2024. 12. 20. 17:23
반응형

 

네이버 SENS로 메시지를 발송하기에 앞서 준비해야할 사항이 3가지 있습니다(로그인이 필요).

  1. API키 (Access Key, Secret Key 총 2개) : 공식문서를 참고해주세요
  2. 프로젝트 ID: 프로젝트 생성 바로가기
  3. 발신번호 등록: 바로가기

 

환경변수

NCLOUD_ACCESS_API_KEY=""
NCLOUD_SECRET_KEY=""
NCLOUD_SERVICE_ID=""
NCLOUD_SENDER=""
NCLOUD_RECEIVER=""

 

발급받은 KEY, ID를 환경변수에 추가합니다.

 

시그니처 생성 함수

요청 정보를 API 인증키(AccessKey에 맵핑되는 SecretKey)로 암호화한 후 Base64로 인코딩하여 생성하는 서명값입니다. 암호화에는 HMAC 암호화 알고리즘(HmacSHA256)이 사용됩니다.
출처: 네이버 SENS 공식문서

 

보안을 위해 서명값을 생성해서 요청에 포함해서 보내야합니다. `npm i crypto-js`로 크립토 모듈을 설치해주세요.

import CryptoJS from "crypto-js"

export function makeSignature() {
  const space = " " // one space
  const newLine = "\n" // new line
  const method = "GET" // method
  const url = "/photos/puppy.jpg?query1=&query2" // url (include query string)
  const timestamp = "{timestamp}" // current timestamp (epoch)
  const accessKey = "{accessKey}" // access key id (from portal or Sub Account)
  const secretKey = "{secretKey}" // secret key (from portal or Sub Account)

  const hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, secretKey)
  hmac.update(method)
  hmac.update(space)
  hmac.update(url)
  hmac.update(newLine)
  hmac.update(timestamp)
  hmac.update(newLine)
  hmac.update(accessKey)

  var hash = hmac.finalize()

  return hash.toString(CryptoJS.enc.Base64)
}

 

메시지 전송 요청

import { makeSignature } from "@/libs/ncloud"

export async function sendSms(msg) {
  // 환경 변수에서 네이버 클라우드 서비스 ID, 액세스 키, 비밀 키 가져오기
  const serviceId = process.env.NCLOUD_SERVICE_ID
  const accessKey = process.env.NCLOUD_ACCESS_API_KEY
  const secretKey = process.env.NCLOUD_SECRET_KEY

  // 현재 타임스탬프 (밀리초 단위) 가져오기
  const timestamp = Date.now().toString()

  // 요청을 보낼 SMS API의 URL 구성
  const url = `https://sens.apigw.ntruss.com/sms/v2/services/${serviceId}/messages`

  // API 요청을 인증하기 위한 시그니처 생성
  const signature = makeSignature(timestamp, accessKey, secretKey)

  // 환경 변수에서 수신자 목록을 가져와 메시지 형식으로 변환
  const messages = process.env.NCLOUD_RECEIVER?.split(",").map((receiver) => ({
    to: receiver, // 수신자 번호
    content: msg, // 보낼 메시지 내용
  }))

  try {
    // SMS API에 요청 보내기
    const response = await fetch(url, {
      method: "POST", // HTTP POST 요청
      headers: {
        "Content-Type": "application/json; charset=utf-8", // JSON 데이터임을 명시
        "x-ncp-apigw-timestamp": timestamp, // 현재 타임스탬프
        "x-ncp-iam-access-key": accessKey, // 액세스 키
        "x-ncp-apigw-signature-v2": signature, // 인증 시그니처
      },
      // 요청 본문에 메시지 데이터를 포함
      body: JSON.stringify({
        type: "SMS", // 메시지 타입 (SMS)
        from: process.env.NCLOUD_SENDER, // 발신자 번호
        messages, // 수신자와 메시지 내용 리스트
      }),
    })

    // 요청이 성공하지 않은 경우 false 반환
    if (!response.ok) {
      console.log(response) // 실패한 응답 로그 출력
      return false
    }

    return true
  } catch (error) {
    // 오류가 발생하면 오류 메시지를 출력하고 false 반환
    console.error("Error sending SMS:", error)
    return false
  }
}

 

메시지 발송번호와 수신번호를 환경변수로 관리했으며 번호의 경우 `하이픈(-)`을 제외하고 숫자로만 구성해야 합니다. 수신번호의 경우 문자열로 나열하되 `콤마(,)`로 구분해뒀습니다.

 

 

자세한 사항은 네이버 SENS API 공식문서를 참고해주세요.

 

 

반응형