← 패키지 목록

Sendgo Notification

인증된 제출자

techigh/sendgo-notification

제출자 이우진
최신 v1.1.0라이센스 MIT배포 2026년 7월 6일
큐·작업SaaS 킷

Laravel용 알림 패키지

SendGo Notification — Laravel 카카오톡·SMS 연동 패키지

License: MIT Version Laravel PHP

Laravel에서 카카오 알림톡, 친구톡, SMS / LMS / MMS를 전송하는 공식 Notification 패키지입니다. SendGo.io API v1 / v2를 모두 지원합니다.


목차


요구사항

  • PHP 8.2+
  • Laravel 8.x | 9.x | 10.x | 11.x
  • SendGo 계정 (sendgo.io)

설치

composer require techigh/sendgo-notification

설정 파일을 프로젝트에 복사하려면 아래 명령어를 실행하세요 (선택):

php artisan vendor:publish --tag=sendgo

환경 설정

.env 파일에 아래 값을 추가합니다:

SENDGO_URL=https://api.sendgo.io SENDGO_ACCESS_KEY=your_access_key SENDGO_SECRET_KEY=your_secret_key SENDGO_SENDER_KEY=your_sms_sender_key SENDGO_KAKAO_SENDER_KEY=your_kakao_sender_key # API 버전 (기본값: v1 / v2 사용 시 명시) SENDGO_API_VERSION=v1

NOTE

API 키는 SendGo.io 콘솔 → 연동 정보 메뉴에서 확인할 수 있습니다.


사용 방법

이 패키지는 Laravel의 표준 Notification 시스템과 통합됩니다. 채널 클래스(AlimTalkChannel, FriendTalkChannel, SmsChannel)를 via() 메서드에 등록하고, 각 채널에 맞는 메시지 객체를 반환하는 메서드(toAlim(), toFriend(), toSms())를 구현하면 됩니다.


수신자 전달 방식

수신자는 to() 또는 toMany() 메서드로 지정합니다.

단일 수신자to(array $to):

->to([ 'contact' => '01066443892', 'name' => '홍길동', 'var1' => '주문번호 001', ])

다중 수신자toMany(array $to):

->toMany([ [ 'contact' => '01066443892', 'name' => '홍길동', 'var1' => '주문번호 001', ], [ 'contact' => '01012345678', 'name' => '김철수', 'var1' => '주문번호 002', ], ])

각 수신자 항목에서 contact는 필수이며, namevar1~var8는 선택 항목입니다.

NOTE

toMany()는 Laravel Notification 채널에서는 사용할 수 없습니다. Sms, AlimTalk, FriendTalk 서비스를 직접 호출할 때만 지원됩니다. Notification 채널에서 toMany()를 사용하면 MULTIPLE_RECIPIENTS_NOT_SUPPORTED_IN_NOTIFICATION 예외가 발생합니다.

서비스를 직접 호출하는 경우의 다중 발송 예시:

use Techigh\SendgoNotification\Attributes\Sms\Sms; use Techigh\SendgoNotification\Attributes\Sms\SmsMessage; app(Sms::class)->send( SmsMessage::make() ->messageType('SMS') ->content('[공지] 시스템 점검 안내') ->toMany([ ['contact' => '01066443892', 'name' => '홍길동'], ['contact' => '01012345678', 'name' => '김철수'], ]) ->toArray() );

알림톡 (AlimTalk)

사전에 카카오에서 승인된 템플릿으로 공식 비즈니스 메시지를 전송합니다. 주문 확인, 배송 안내, 예약 알림 등 정형화된 메시지에 적합합니다.

use Techigh\SendgoNotification\Attributes\Alim\AlimTalkChannel; use Techigh\SendgoNotification\Attributes\Alim\AlimTalkMessage; class OrderConfirmedNotification extends Notification { use Queueable; public function __construct(private readonly string $orderNumber) {} public function via(object $notifiable): array { return [AlimTalkChannel::class]; } public function toAlim(object $notifiable): AlimTalkMessage { return AlimTalkMessage::make() ->templateCode('ORDER_CONFIRM_001') ->replaceSms('Y') ->smsTitle('[주문 확인]') ->smsContent("주문 {$this->orderNumber}이 확인되었습니다.") ->to([ 'contact' => $notifiable->phone, 'name' => $notifiable->name, 'var1' => $this->orderNumber, ]) ->at(); } }
$user->notify(new OrderConfirmedNotification('ORD-20260101-001'));

AlimTalk 메서드

메서드필수설명
templateCode(string)SendGo에서 승인받은 템플릿 코드
scheduleType(string)'DIRECTLY'(기본) 또는 'SCHEDULED'
replaceSms(string)알림톡 실패 시 SMS 대체 ('N' 기본)
smsTitle(string)조건부대체 SMS 제목 (replaceSms('Y') 시 필수)
smsContent(string)조건부대체 SMS 내용 (replaceSms('Y') 시 필수)
to(array)단일 수신자 정보 (contact 필수, name / var1~var8 선택)
toMany(array)배치 전용다중 수신자 정보. Notification 채널에서는 사용 불가
at(string|null)조건부예약 시각 (SCHEDULED일 때 필수, 형식: Y-m-d H:i:s)

더 많은 예제 → examples/AlimTalk.md


친구톡 (FriendTalk)

카카오톡 채널 친구에게 이미지, 버튼 등을 포함한 자유로운 형태의 메시지를 전송합니다. 이벤트 안내, 신상품 홍보 등 마케팅 목적에 적합합니다.

use Techigh\SendgoNotification\Attributes\Friend\FriendTalkChannel; use Techigh\SendgoNotification\Attributes\Friend\FriendTalkMessage; class NewProductNotification extends Notification { use Queueable; public function __construct(private readonly object $product) {} public function via(object $notifiable): array { return [FriendTalkChannel::class]; } public function toFriend(object $notifiable): FriendTalkMessage { return FriendTalkMessage::make() ->messageType('FI') ->content("신상품 출시!\n\n{$this->product->name}\n{$this->product->price}원") ->imageUrl($this->product->image_url) ->imageLink($this->product->detail_url) ->buttons([ [ 'type' => 'WL', 'name' => '자세히 보기', 'linkMo' => $this->product->detail_url, 'linkPc' => $this->product->detail_url, ], ]) ->to([ 'contact' => $notifiable->phone, 'name' => $notifiable->name, ]) ->at(); } }

메시지 타입

타입설명
FT텍스트형
FI이미지형
FW와이드 이미지형 (wide('Y') 필수)
FL와이드 아이템 리스트형
FM커머스형
FC캐러셀 피드형
FA캐러셀 커머스형
FP프리미엄 동영상형

FriendTalk 메서드

메서드필수설명
messageType(string)메시지 타입 (위 표 참고)
content(string)메시지 내용
scheduleType(string)'DIRECTLY'(기본) 또는 'SCHEDULED'
imageUrl(string)이미지 URL
imageLink(string)이미지 클릭 시 이동할 링크
buttons(array)버튼 배열
wide(string)조건부와이드 이미지 여부 (FW일 때 'Y' 필수)
adFlag(string)광고성 메시지 표기 ('N' 기본)
replaceSms(string)친구톡 실패 시 SMS 대체
smsTitle(string)조건부대체 SMS 제목 (replaceSms('Y') 시 필수)
smsContent(string)조건부대체 SMS 내용 (replaceSms('Y') 시 필수)
to(array)단일 수신자 정보 (contact 필수, name 선택)
toMany(array)배치 전용다중 수신자 정보. Notification 채널에서는 사용 불가
at(string|null)조건부예약 시각 (SCHEDULED일 때 필수, 형식: Y-m-d H:i:s)

더 많은 예제 → examples/FriendTalk.md


SMS / LMS / MMS

use Techigh\SendgoNotification\Attributes\Sms\SmsChannel; use Techigh\SendgoNotification\Attributes\Sms\SmsMessage; class VerificationNotification extends Notification { use Queueable; public function __construct(private readonly string $code) {} public function via(object $notifiable): array { return [SmsChannel::class]; } public function toSms(object $notifiable): SmsMessage { return SmsMessage::make() ->messageType('SMS') ->content("[인증번호] {$this->code} (3분 내 입력)") ->to([ 'contact' => $notifiable->phone, 'name' => $notifiable->name, ]) ->at(); } }

LMS (장문 메시지, subject 필수):

return SmsMessage::make() ->messageType('LMS') ->subject('[점검 안내]') ->content('2026-04-01 02:00~06:00 서비스 점검이 예정되어 있습니다.') ->to(['contact' => $notifiable->phone]) ->at();

MMS (subject + files 필수, 최대 3개):

return SmsMessage::make() ->messageType('MMS') ->subject('[이벤트]') ->content('첨부 이미지를 확인해주세요.') ->files([ storage_path('app/public/event_01.jpg'), storage_path('app/public/event_02.jpg'), ]) ->to(['contact' => $notifiable->phone]) ->at();

SMS 메서드

메서드필수설명
messageType(string)'SMS' / 'LMS' / 'MMS'
content(string)메시지 내용
campaignType(string)'MESSAGE' (기본값)
scheduleType(string)'DIRECTLY'(기본) 또는 'SCHEDULED'
subject(string)조건부제목 (LMS / MMS 필수)
files(array)조건부파일 경로 배열 (MMS 필수, 최대 3개)
to(array)단일 수신자 정보 (contact 필수, var1~var8 선택)
toMany(array)배치 전용다중 수신자 정보. Notification 채널에서는 사용 불가
at(string|null)조건부예약 시각 (SCHEDULED일 때 필수, 형식: Y-m-d H:i:s)

더 많은 예제 → examples/SMS.md


예제 문서


변경 이력

전체 변경 이력은 CHANGELOG.md를 참고하세요.


예외 처리

발송에 실패하면 SendGoException이 던져집니다. context() 메서드로 API 응답의 상세 정보를 확인할 수 있습니다.

use Techigh\SendgoNotification\Exceptions\SendGoException; try { $user->notify(new OrderConfirmedNotification($order->number)); } catch (SendGoException $e) { $ctx = $e->context(); // $ctx['error_code'] — 에러 코드 (예: 'INVALID_TEMPLATE_CODE') // $ctx['status'] — HTTP 상태 코드 // $ctx['endpoint'] — 호출 엔드포인트 // $ctx['api_version'] — 사용 중인 API 버전 // $ctx['body'] — 원본 응답 body logger()->error('SendGo 발송 실패', [ 'error_code' => $ctx['error_code'] ?? null, 'status' => $ctx['status'] ?? null, 'message' => $e->getMessage(), ]); }

큐 비동기 발송

ShouldQueue 인터페이스를 구현하면 Laravel 큐를 통해 비동기로 처리됩니다. 대량 발송이나 응답 속도가 중요한 상황에서 권장합니다.

use Illuminate\Contracts\Queue\ShouldQueue; use Techigh\SendgoNotification\Exceptions\SendGoException; class OrderConfirmedNotification extends Notification implements ShouldQueue { use Queueable; public string $queue = 'notifications'; public int $tries = 3; public int $backoff = 10; public function failed(SendGoException $e): void { logger()->critical('알림 최종 실패', ['error' => $e->getMessage()]); } }

큐 워커를 실행하려면:

php artisan queue:work --queue=notifications

다중 워커 환경에서는 토큰 캐시를 공유할 수 있도록 redis 또는 database 드라이버를 사용하세요:

CACHE_DRIVER=redis QUEUE_CONNECTION=redis

NOTE

여러 큐 워커가 동시에 실행되는 환경에서 file 캐시 드라이버를 사용하면 인증 토큰이 워커 간에 공유되지 않아 불필요한 토큰 재발급이 발생할 수 있습니다. redis를 권장합니다.


v1 → v2 마이그레이션

기존 Notification 코드를 수정할 필요 없이 .env 파일에서 API 버전만 변경하면 됩니다.

SENDGO_API_VERSION=v2

v2 주요 변경 사항:

항목v1v2
토큰 형식base64 인코딩그대로 사용 (sgv2. prefix)
토큰 재발급401 / 403 응답 시 무조건 재발급에러 코드별 분기 처리 (설정 오류는 재발급하지 않음)
에러 응답별도 구조 없음code / message / traceId 포함

v2 에러 코드 전체 목록 → API_V2_ERROR_CODES.md


에러 코드

SendGoException::context()['error_code']로 확인합니다.

인증 오류 (401)

코드설명
INVALID_AUTH_HEADERAuthorization 헤더 없음
INVALID_BASIC_AUTHBasic 인증 형식 오류
INVALID_BASIC_AUTH_PAYLOADBasic 인증 페이로드 오류
INVALID_ACCESS_KEY유효하지 않은 Access Key
INVALID_SECRET_KEY유효하지 않은 Secret Key
INVALID_BEARER_TOKENBearer 토큰 없음
INVALID_BEARER_TOKEN_PREFIXBearer 토큰 prefix 오류 (v2)
INVALID_BEARER_TOKEN_PAYLOADBearer 토큰 페이로드 오류 (v2)
INVALID_BEARER_SIGNATUREBearer 토큰 서명 불일치 (v2)
INVALID_BEARER_APPLICATION토큰에 해당하는 앱 없음 (v2)
MALFORMED_BEARER_TOKEN잘못된 형식의 Bearer 토큰 (v2)
UNSUPPORTED_BEARER_TOKEN_VERSION지원하지 않는 토큰 버전 (v2)
TOKEN_MISMATCH발급된 토큰과 불일치 (v2)
TOKEN_EXPIRED만료된 토큰 (패키지가 자동으로 재발급 처리)
TOKEN_RECORD_NOT_FOUND토큰 레코드 없음 (v2)

권한 오류 (403)

코드설명
ACCESS_KEY_NOT_APPROVED미승인 Access Key
IP_NOT_ALLOWED허용되지 않은 IP
TEAM_REQUIRED_FOR_KAKAO카카오 API는 팀 소속 앱만 사용 가능
SENDER_APPLICATION_MISMATCHSMS 발신키가 앱과 불일치
KAKAO_SENDER_APPLICATION_MISMATCH카카오 발신키가 앱과 불일치

리소스 오류 (404)

코드설명
INVALID_SENDER_KEY유효하지 않은 SMS 발신키
INVALID_KAKAO_SENDER_KEY유효하지 않은 카카오 발신키
INVALID_TEMPLATE_CODE유효하지 않은 템플릿 코드
OWNER_NOT_FOUND캠페인 소유자 확인 불가
SENDER_OWNER_NOT_FOUNDSMS 발신키 소유자 확인 불가
KAKAO_SENDER_OWNER_NOT_FOUND카카오 발신키 소유자 확인 불가

요청 오류 (422)

코드설명
EMPTY_CONTACTS수신자 없음
PAYMENT_REQUIRED크레딧 부족
MESSAGE_PROCESSING_FAILEDSMS / MMS 처리 실패
NOTICE_PROCESSING_FAILED알림톡 처리 실패
FRIEND_PROCESSING_FAILED친구톡 처리 실패

패키지 내부 오류

코드설명
INVALID_API_VERSION지원하지 않는 API 버전 (v1 또는 v2만 허용)
MULTIPLE_RECIPIENTS_NOT_SUPPORTED_IN_NOTIFICATIONLaravel Notification 채널에서 toMany() 사용 불가

v2 에러 코드 상세 → API_V2_ERROR_CODES.md


트러블슈팅

메시지가 전송되지 않을 때

  1. .env의 API 키 값이 올바른지 확인합니다.
  2. SendGo 계정의 잔액(크레딧)을 확인합니다.
  3. 전화번호 형식을 확인합니다. (01012345678 형태, 하이픈 제외)
  4. storage/logs/laravel.log에서 에러 메시지를 확인합니다.

알림톡이 SMS로 대체 발송될 때

  1. SendGo 콘솔에서 템플릿 승인 상태를 확인합니다.
  2. 템플릿 변수(var1~var8) 매핑이 올바른지 확인합니다.
  3. 카카오 채널 연동 상태를 확인합니다.

다중 워커 환경에서 토큰 충돌이 발생할 때

  • CACHE_DRIVER=redis로 변경하여 공유 캐시를 사용합니다.

INVALID_API_VERSION 에러가 발생할 때

  • SENDGO_API_VERSION 값이 v1 또는 v2로 설정되어 있는지 확인합니다.

라이선스

MIT — LICENSE 참조


Made with ❤️ by Techigh | Powered by SendGo.io