문자는 **템플릿 승인이 필요 없습니다.** 본문을 코드에서 자유롭게 만들 수 있어서, 알림톡 템플릿으로 커버되지 않는 일회성 안내나 인증번호에 적합합니다.

## 준비물

- 사전등록된 **문자 발신번호**(`senderKey`) → [발신번호 사전등록](/ko/cookbook/sender-number)
- 액세스 키 / 시크릿 키

카카오 발신프로필은 필요 없습니다.

## SMS, LMS, MMS — 어떤 걸 써야 하나

| 타입 | 본문 한도 | 제목 | 첨부 | 언제 |
| --- | --- | --- | --- | --- |
| **SMS** | 90바이트 (한글 ~45자) | ❌ | ❌ | 인증번호, 짧은 알림 |
| **LMS** | 2,000바이트 (한글 ~1,000자) | ✅ | ❌ | 공지, 안내문 |
| **MMS** | 2,000바이트 | ✅ | 이미지 | 이벤트 배너, 쿠폰 이미지 |

**바이트 계산**: 한글 2바이트, 영문·숫자·기호 1바이트, 줄바꿈 1~2바이트. 90바이트를 넘기면 SMS 로 보낼 수 없습니다. 길이가 유동적인 본문이라면 처음부터 LMS 를 쓰거나, 길이에 따라 분기하세요.

## 언어별 예제

### Node.js / TypeScript

```typescript
// SMS — 단문
await sendgo.sms.sendSms({
  content: '[샌드고] 인증번호: 123456 (5분 이내 입력)',
  contacts: [{ contact: '01012345678' }],
});

// LMS — 장문 (제목 포함)
await sendgo.sms.sendLms({
  subject: '[중요] 서비스 점검 안내',
  content: `안녕하세요.
서비스 점검이 예정되어 있습니다.

■ 점검 일시: 2026-09-01 02:00 ~ 06:00
■ 영향 범위: 전체 서비스

이용에 불편을 드려 죄송합니다.`,
  contacts: [{ contact: '01012345678' }],
});

// MMS — 이미지 첨부
await sendgo.sms.sendMms({
  subject: '[이벤트] 9월 특가',
  content: '이번 달 특가 상품을 확인하세요!',
  contacts: [{ contact: '01012345678' }],
});
```

### Python

```python
client.sms.send_sms(
    content="[샌드고] 인증번호: 123456 (5분 이내 입력)",
    contacts=[{"contact": "01012345678"}],
)

client.sms.send_lms(
    subject="[중요] 서비스 점검 안내",
    content="안녕하세요.\n\n서비스 점검이 예정되어 있습니다.\n일시: 2026-09-01 02:00 ~ 06:00",
    contacts=[{"contact": "01012345678"}],
)

client.sms.send_mms(
    subject="[이벤트] 9월 특가",
    content="이번 달 특가 상품을 확인하세요!",
    contacts=[{"contact": "01012345678"}],
)
```

### PHP · Laravel

```php
<?php

$sendgo->sms->sendSms([
    'content'  => '[샌드고] 인증번호: 123456 (5분 이내 입력)',
    'contacts' => [['contact' => '01012345678']],
]);

$sendgo->sms->sendLms([
    'subject'  => '[중요] 서비스 점검 안내',
    'content'  => "안녕하세요.\n\n서비스 점검이 예정되어 있습니다.",
    'contacts' => [['contact' => '01012345678']],
]);

$sendgo->sms->sendMms([
    'subject'  => '[이벤트] 9월 특가',
    'content'  => '이번 달 특가 상품을 확인하세요!',
    'contacts' => [['contact' => '01011111111'], ['contact' => '01022222222']],
]);
```

Laravel 에서는 `app(Sendgo::class)->sms->sendSms([...])` 또는 생성자 주입으로 씁니다.

### REST 직접 호출

```bash
curl -X POST https://sendgo.io/api/v2/messages/send \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "campaignType": "MESSAGE",
    "messageType": "SMS",
    "scheduleType": "DIRECTLY",
    "content": "인증번호: 123456",
    "contacts": [{ "contact": "01012345678" }],
    "senderKey": "your_sms_sender_key"
  }'
```

`messageType` 을 `LMS` 나 `MMS` 로 바꾸면 해당 타입으로 나갑니다. LMS/MMS 는 `subject` 를 함께 보냅니다.

## 인증번호 발송 패턴

인증번호는 문자의 가장 흔한 용도입니다. 몇 가지 주의점이 있습니다.

```typescript
// 인증번호는 서버에서 생성하고, 발송 실패를 사용자에게 알려야 한다.
const code = String(Math.floor(100000 + Math.random() * 900000));

await redis.setex(`verify:${phone}`, 300, code);   // 5분 만료

try {
  await sendgo.sms.sendSms({
    content: `[서비스명] 인증번호: ${code} (5분 이내 입력)`,
    contacts: [{ contact: phone }],
  });
} catch (error) {
  // 인증번호는 실패를 삼키면 안 된다 — 사용자가 오지 않는 문자를 기다린다.
  throw new Error('인증번호 발송에 실패했습니다. 잠시 후 다시 시도해 주세요.');
}
```

- **발송 실패를 삼키지 마세요.** 주문 알림과 달리 인증번호는 도착하지 않으면 사용자가 다음 단계로 갈 수 없습니다.
- **재발송에 제한을 거세요.** 번호당 분당 횟수를 제한하지 않으면 문자 폭탄에 악용되고 크레딧이 소진됩니다.
- **본문에 서비스명을 넣으세요.** 어디서 온 인증번호인지 모르면 사용자가 입력하지 않습니다.

## 광고 문자 규칙

홍보성 문자에는 정보통신망법이 적용됩니다.

```text
(광고)[브랜드명] 가을 세일 최대 50%!
...
무료수신거부 080-000-0000
```

- 본문 **맨 앞**에 `(광고)` 표기
- **무료 수신거부** 번호 또는 방법 명시
- **21시 ~ 익일 08시** 발송 금지
- 사전 수신동의를 받은 대상에게만

자세한 내용은 [광고성 메시지 규칙](/ko/cookbook/ad-message-rules)에 있습니다. 인증번호·주문 알림 같은 정보성 문자에는 적용되지 않습니다.

## 다음 단계

- [알림톡이 실패하면 문자로 대체 발송](/ko/cookbook/sms-fallback)
- [짧은주소로 클릭 추적하기](/ko/cookbook/short-url)
- [대량 발송과 치환 변수](/ko/cookbook/bulk-send)