홍보·마케팅 메시지에는 **정보통신망법**이 적용됩니다. 지키지 않으면 과태료 대상이고, 반복되면 발신 채널 자체가 제재를 받습니다.

정보성 메시지(주문 확인, 배송 안내, 인증번호)에는 적용되지 않습니다. 알림톡은 정보성만 승인되므로 실질적으로 이 규칙은 **광고 문자와 브랜드메시지**의 문제입니다.

## 지켜야 할 네 가지

### 1. 사전 수신 동의

수신자에게 **미리 동의를 받은 경우에만** 보낼 수 있습니다. 회원가입 시 마케팅 수신 동의 체크박스가 그것입니다. 동의는 기본 선택 상태로 두면 안 되고, 동의 시점과 내역을 보관해야 합니다.

### 2. (광고) 표기

본문 **맨 앞**에 붙입니다.

```text
(광고)[브랜드명] 가을 세일 최대 50%
...
```

LMS 처럼 제목이 있으면 제목 맨 앞에 넣습니다. 중간이나 끝에 넣으면 인정되지 않습니다.

### 3. 무료 수신거부 방법

수신자가 **비용을 부담하지 않고** 거부할 수 있어야 합니다. 080 무료 수신거부 번호가 일반적입니다.

```text
(광고)[브랜드명] 가을 세일 최대 50%
자세히 보기 https://sendgo.io/s/k7Rm2xQ

무료수신거부 080-000-0000
```

### 4. 야간 발송 금지 (21:00 ~ 08:00)

**21시부터 익일 08시까지** 광고성 메시지를 보낼 수 없습니다. 이 시간대에 보내려면 야간 수신에 대한 **별도 동의**를 따로 받아야 합니다.

샌드고는 이 구간의 광고성 발송 요청을 검증합니다. 다만 코드 쪽에서도 막아 두는 편이 안전합니다 — 배치 작업이 예정보다 늦게 실행돼 21시를 넘기는 일이 흔합니다.

## 코드에서 강제하기

### 발송 시각 가드

```php
<?php

use Carbon\CarbonImmutable;

final class AdSendWindow
{
    // 광고성 메시지는 21시~익일 08시에 나갈 수 없다.
    public static function isAllowed(?CarbonImmutable $at = null): bool
    {
        $at ??= CarbonImmutable::now('Asia/Seoul');

        return $at->hour >= 8 && $at->hour < 21;
    }

    /** 제한 구간이면 다음 허용 시각(익일 08:00)으로 미룬다. */
    public static function nextAllowed(CarbonImmutable $at): CarbonImmutable
    {
        if (self::isAllowed($at)) {
            return $at;
        }

        return $at->hour >= 21
            ? $at->addDay()->setTime(8, 0)
            : $at->setTime(8, 0);
    }
}
```

```typescript
// 서버 시간대에 의존하지 않고 KST 기준으로 판단한다.
function kstHour(date = new Date()): number {
  return Number(
    new Intl.DateTimeFormat('en-GB', {
      timeZone: 'Asia/Seoul', hour: '2-digit', hour12: false,
    }).format(date),
  );
}

const canSendAd = () => {
  const h = kstHour();
  return h >= 8 && h < 21;
};
```

```python
from datetime import datetime
from zoneinfo import ZoneInfo

def can_send_ad(at: datetime | None = None) -> bool:
    at = at or datetime.now(ZoneInfo("Asia/Seoul"))
    return 8 <= at.hour < 21
```

### 본문 검증

```php
<?php

function assertAdFormat(string $content, string $optOut): void
{
    if (! str_starts_with($content, '(광고)')) {
        throw new InvalidArgumentException('광고성 메시지는 (광고) 로 시작해야 합니다.');
    }

    if (! str_contains($content, $optOut)) {
        throw new InvalidArgumentException('무료 수신거부 안내가 본문에 없습니다.');
    }
}
```

## 브랜드메시지의 `adFlag`

브랜드메시지와 친구톡에는 광고 여부를 표시하는 `adFlag` 가 있습니다.

```typescript
await sendgo.brandMessage.send({
  targeting: 'M',
  messageType: 'FL',
  friendTemplateUuid: '...',
  adFlag: 'Y',        // 광고성 메시지임을 표시
  contacts: [...],
});
```

`adFlag: 'Y'` 로 두면 카카오 쪽에서 광고 메시지 규칙(수신거부 버튼 등)이 적용됩니다. 광고인데 `N` 으로 보내는 것은 위반입니다.

## 예약 발송의 함정

야간 제한은 **실제 발송 시각** 기준입니다. "지금부터 3시간 뒤"처럼 상대 시각으로 예약하면, 배치 실행 시각에 따라 제한 구간에 들어갈 수 있습니다.

```php
<?php

$at = AdSendWindow::nextAllowed(CarbonImmutable::now('Asia/Seoul')->addHours(3));

$sendgo->brandMessage->send([
    'targeting'    => 'M',
    'scheduleType' => 'SCHEDULED',
    'at'           => $at->format('Y-m-d H:i:s'),
    'adFlag'       => 'Y',
    // ...
]);
```

## 다음 단계

- [브랜드메시지 보내기](/ko/cookbook/send-brand-message)
- [예약 발송](/ko/cookbook/scheduled-send)
- [SMS · LMS · MMS 보내기](/ko/cookbook/send-sms)