Node.js 문자 발송 API 예제
Node.js 18 이상에 내장된 fetch 로 센드엠 문자 발송 API를 호출하는 예제입니다. 추가 패키지 설치가 필요 없습니다.
Node.js에서 문자를 어떻게 보내나요?
Node.js 18 부터는 별도 패키지 없이 전역 fetch 로 https://api.sendm.co.kr/v1/sms/send 에 요청을 보내면 됩니다. 인증은 헤더 user-id·api-key 로 하고, 응답 code 가 문자열 "0" 이면 접수된 것입니다.
아래 예제는 CommonJS(require) 모듈 sendm.js 하나로 구성했습니다. 아이디와 인증키는 소스에 쓰지 않고 process.env 에서 읽으므로, Express 라우트나 배치 스크립트에서 require('./sendm') 로 불러 그대로 쓸 수 있습니다.
단문(SMS) 발송
sendm.js
const BASE_URL = 'https://api.sendm.co.kr';
const HEADERS = {
'user-id': process.env.SENDM_USER_ID, // 센드엠 아이디
'api-key': process.env.SENDM_API_KEY, // API 신청 후 발급받은 키
};
/**
* 문자 발송
* @param {string} callerNo 등록·승인된 발신번호
* @param {string} receiveNos 수신번호. 여러 건은 '#' 로 구분
* @param {string} message 본문
*/
async function sendSms(callerNo, receiveNos, message, options = {}) {
const body = {
callerNo,
receiveNos,
message,
smsType: options.smsType || 'SMS', // 'SMS' 단문 / 'LMS' 장문
adYn: options.adYn || 'N', // 'N' 일반 / 'Y' 광고 / 'E' 선거
};
if (options.title) body.title = options.title; // 장문 제목
if (options.reserveYn) body.reserveYn = options.reserveYn; // 'Y' 예약
if (options.sendDate) body.sendDate = options.sendDate; // YYYYMMDDHHMM
const res = await fetch(BASE_URL + '/v1/sms/send', {
method: 'POST',
headers: Object.assign({ 'Content-Type': 'application/json' }, HEADERS),
body: JSON.stringify(body),
signal: AbortSignal.timeout(10000),
});
return res.json();
}
module.exports = { sendSms, BASE_URL, HEADERS };
호출과 결과 판정
const { sendSms } = require('./sendm');
const result = await sendSms(
'02-6959-8827', // 발신번호
'010-0000-0001#010-0000-0002', // 수신번호 (# 구분)
'주문이 접수되었습니다.'
);
// code 는 숫자가 아니라 문자열 '0' 이다
if (result.code === '0') {
console.log('발송 접수 완료. msgId =', result.data.msgId);
} else {
console.error('발송 실패 [' + result.code + '] ' + result.message);
}
장문(LMS) 예약 발송 — reserveYn: 'Y'
function toSendDate(date) {
const p = (n) => String(n).padStart(2, '0');
return date.getFullYear()
+ p(date.getMonth() + 1)
+ p(date.getDate())
+ p(date.getHours())
+ p(date.getMinutes()); // YYYYMMDDHHMM (24시간제)
}
const twoHoursLater = new Date(Date.now() + 2 * 60 * 60 * 1000);
await sendSms('02-6959-8827', '010-0000-0001', '주문하신 상품이 출고되었습니다.', {
smsType: 'LMS',
title: '배송 안내',
reserveYn: 'Y',
sendDate: toSendDate(twoHoursLater),
});
FormData 로 포토문자(MMS) 보내기
fs/promises 로 읽은 이미지 Buffer 를 Blob 으로 감싸 attachFile01~03 에 붙입니다.
const fs = require('node:fs/promises');
const path = require('node:path');
async function sendMms(callerNo, receiveNos, message, imagePaths, title) {
const form = new FormData();
form.append('callerNo', callerNo);
form.append('receiveNos', receiveNos);
form.append('message', message); // MMS 는 본문이 없어도 된다
form.append('smsType', 'MMS');
if (title) form.append('title', title);
// 최대 3장 : attachFile01 ~ attachFile03
for (let i = 0; i < Math.min(imagePaths.length, 3); i++) {
const buf = await fs.readFile(imagePaths[i]);
const name = 'attachFile' + String(i + 1).padStart(2, '0');
form.append(name, new Blob([buf]), path.basename(imagePaths[i]));
}
const res = await fetch(BASE_URL + '/v1/mms/send', {
method: 'POST',
headers: HEADERS, // Content-Type 은 fetch 가 자동 생성
body: form,
signal: AbortSignal.timeout(30000),
});
return res.json();
}
요청 headers 에는 인증 헤더만 두세요. Content-Type 을 직접 지정하면 fetch 가 자동으로 붙이는 boundary 값이 사라져 서버가 첨부파일을 읽지 못합니다. 첨부 가능한 이미지 규격은 API 연동 방법에 정리돼 있습니다.
알림톡 발송
수신자 배열을 JSON.stringify 로 문자열로 바꾼 뒤 FormData 의 kakaoList 항목에 넣습니다. 배열을 그대로 append 하면 [object Object] 형태의 문자열로 바뀌어 전송됩니다.
const kakaoList = [
{
receive: '010-0000-0001',
message: '홍길동님, 주문번호 A1234 상품이 출고되었습니다.',
reYn: 'Y', // 알림톡 실패 시 문자로 대체
reType: 'LMS',
reTitle: '배송 안내',
reMsg: '홍길동님, 주문번호 A1234 상품이 출고되었습니다.',
},
];
const form = new FormData();
form.append('callerNo', '02-6959-8827');
form.append('senderKey', '카카오 채널 발신 프로필 키');
form.append('tmplCd', '승인된 템플릿 코드');
form.append('kakaoList', JSON.stringify(kakaoList));
const res = await fetch(BASE_URL + '/v2/kakao/sendAt', {
method: 'POST',
headers: HEADERS,
body: form,
signal: AbortSignal.timeout(30000),
});
console.log(await res.json());
알림톡 message 에는 승인받은 템플릿 문구를 그대로 넣어야 합니다. 템플릿 승인 과정은 카카오 알림톡 시작하기에서 설명합니다.
fetch 로 발송 결과·잔여 건수 조회
async function get(pathname) {
const res = await fetch(BASE_URL + pathname, {
headers: HEADERS,
signal: AbortSignal.timeout(10000),
});
return res.json();
}
// 잔여 코인·발송 가능 건수
const info = await get('/v2/info/coinInfo');
console.log(info.data.smsCnt + '건 발송 가능');
// 발송 상세 결과 (수신자별 resultCd)
const detail = await get('/v1/sms/sendList/' + msgId);
console.log('성공 ' + detail.data.successCnt
+ ' / 실패 ' + detail.data.failCnt
+ ' / 대기 ' + detail.data.waitCnt);
detail.list.forEach(function (row) {
console.log(row.receiveNo, row.resultCd, row.resultCdNm);
});
// 예약 발송 취소
await get('/v1/sms/cancel/' + msgId);
resultCd 해석은 발송 실패 원인과 결과코드를 참고하세요.
이어서 보면 좋은 문서
최종 업데이트 : 2026년 9월 16일 · 「센드엠 API 연동정의서 v3.0」 기준
Node.js 연동은 API 신청부터
승인되면 아이디를 SENDM_USER_ID, 발급된 인증키를 SENDM_API_KEY 환경변수로 지정하고 위 sendm.js 를 불러오면 됩니다.