본문 바로가기

Java 문자 발송 API 예제

JDK에 기본 포함된 HttpURLConnection 으로 센드엠 문자 발송 API를 호출하는 예제입니다. 별도 SDK가 필요 없습니다.

Java에서 문자를 어떻게 보내나요?

https://api.sendm.co.kr/v1/sms/sendPOST 로 JSON을 보내고, 요청 헤더에 user-idapi-key 를 넣으면 됩니다. 응답 JSON의 code"0" 이면 접수 성공입니다.

표준 HTTP 호출이라 HttpURLConnection, Apache HttpClient, OkHttp, Spring RestTemplate·WebClient 중 무엇을 써도 됩니다. 아래는 의존성이 가장 적은 HttpURLConnection 방식입니다.

웹 화면(JSP·JS)에서 직접 호출하지 마세요. 인증키가 소스에 노출되고, 호출 IP가 사용자마다 달라져 발송 IP 등록이 무의미해집니다. 반드시 서버 코드에서 호출하세요.

단문(SMS) 발송 전체 코드

SendmClient.java

import com.google.gson.Gson;
import com.google.gson.JsonObject;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;

public class SendmClient {

    private static final String API_URL = "https://api.sendm.co.kr/v1/sms/send";

    /* 소스에 직접 쓰지 말고 환경변수나 설정파일에서 읽으세요. */
    private static final String USER_ID = System.getenv("SENDM_USER_ID");
    private static final String API_KEY = System.getenv("SENDM_API_KEY");

    public String sendSms(String callerNo, String receiveNos, String message) throws Exception {

        JsonObject body = new JsonObject();
        body.addProperty("callerNo",   callerNo);     // 등록·승인된 발신번호
        body.addProperty("receiveNos", receiveNos);   // 여러 건은 # 로 구분
        body.addProperty("message",    message);
        // body.addProperty("smsType", "LMS");        // 장문이면 추가
        // body.addProperty("title",   "제목");        // 장문 제목
        // body.addProperty("adYn",    "Y");          // 광고문자면 Y

        byte[] payload = new Gson().toJson(body).getBytes(StandardCharsets.UTF_8);

        HttpURLConnection conn = (HttpURLConnection) new URL(API_URL).openConnection();
        try {
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
            conn.setRequestProperty("user-id", USER_ID);
            conn.setRequestProperty("api-key", API_KEY);
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(10000);
            conn.setDoOutput(true);

            try (OutputStream os = conn.getOutputStream()) {
                os.write(payload);
            }

            int status = conn.getResponseCode();

            /* 실패(4xx·5xx)일 때 getInputStream() 을 부르면 IOException 이 난다.
               반드시 getErrorStream() 으로 읽어야 실패 사유를 볼 수 있다. */
            InputStream in = (status == 200) ? conn.getInputStream() : conn.getErrorStream();

            StringBuilder sb = new StringBuilder();
            try (BufferedReader br = new BufferedReader(
                     new InputStreamReader(in, StandardCharsets.UTF_8))) {
                String line;
                while ((line = br.readLine()) != null) {
                    sb.append(line);
                }
            }
            return sb.toString();

        } finally {
            conn.disconnect();
        }
    }
}

호출과 결과 판정

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

String raw = new SendmClient().sendSms(
        "02-6959-8827",                       // 발신번호
        "010-0000-0001#010-0000-0002",        // 수신번호 (# 구분)
        "주문이 접수되었습니다.");

JsonObject res = JsonParser.parseString(raw).getAsJsonObject();

if ("0".equals(res.get("code").getAsString())) {
    long msgId = res.getAsJsonObject("data").get("msgId").getAsLong();
    // msgId 를 저장해 두면 나중에 발송 결과를 조회할 수 있다
    System.out.println("발송 접수 완료. msgId=" + msgId);
} else {
    System.out.println("발송 실패 [" + res.get("code").getAsString() + "] "
                     + res.get("message").getAsString());
}

code 는 숫자가 아니라 문자열 "0" 입니다. == 0 으로 비교하지 마세요.

발송 결과 조회와 잔여 건수

조회 API는 모두 GET 이고 인증 헤더만 같게 넣으면 됩니다.

GET 호출 공통 함수

public String get(String url) throws Exception {
    HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
    try {
        conn.setRequestMethod("GET");
        conn.setRequestProperty("user-id", USER_ID);
        conn.setRequestProperty("api-key", API_KEY);
        conn.setConnectTimeout(5000);
        conn.setReadTimeout(10000);

        int status = conn.getResponseCode();
        InputStream in = (status == 200) ? conn.getInputStream() : conn.getErrorStream();

        StringBuilder sb = new StringBuilder();
        try (BufferedReader br = new BufferedReader(
                 new InputStreamReader(in, StandardCharsets.UTF_8))) {
            String line;
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
        }
        return sb.toString();
    } finally {
        conn.disconnect();
    }
}

// 잔여 코인·발송 가능 건수
get("https://api.sendm.co.kr/v2/info/coinInfo");

// 발송 상세 결과 (수신자별 resultCd 포함)
get("https://api.sendm.co.kr/v1/sms/sendList/" + msgId);

// 예약 발송 취소
get("https://api.sendm.co.kr/v1/sms/cancel/" + msgId);
발송 직후 바로 조회하면 대부분 대기 상태입니다. 결과는 통신사 리포트를 받아야 확정되며 waitCnt 가 최대 48시간 남을 수 있습니다. 발송 루프 안에서 즉시 조회하지 말고 배치나 스케줄러로 분리하세요.

운영에서 자주 막히는 지점

Java 연동 시 흔한 문제와 해결
증상원인해결
한글이 깨져서 도착 요청 본문을 기본 인코딩으로 전송 getBytes(StandardCharsets.UTF_8) 로 보내고 Content-Typecharset=UTF-8 명시
실패인데 예외만 남고 사유를 모름 4xx·5xx 응답에서 getInputStream() 호출 상태코드가 200이 아니면 getErrorStream() 으로 읽기
권한 없음으로 차단 호출 서버 IP가 미등록 API 설정에서 발송 IP 등록. 서버 증설·이전 시 다시 등록
발신번호 오류 callerNo 가 미등록·미승인 번호 발신번호 등록 후 사용
야간에만 실패 야간 발송 제한(21시~08시) reserveYn=YsendDate 로 예약 전환

최종 업데이트 : 2026년 9월 16일 · 「센드엠 API 연동정의서 v3.0」 기준

먼저 API 신청이 필요합니다

승인 후 발급되는 인증키로 위 코드를 바로 실행할 수 있습니다.

loading...