알림
업데이트됨번역일: 2026년 10월 8일
이 페이지는 원문이 업데이트되어 번역이 갱신되었습니다.
- 원문 수정
- 2026년 10월 7일
- 번역 갱신
- 2026년 10월 8일
알림
소개
Laravel은 이메일 전송 외에도 이메일, SMS(Vonage, 이전 이름 Nexmo), Slack 등 다양한 채널을 통한 알림 전송을 지원합니다. 수십 가지 다른 채널을 위한 커뮤니티 알림 채널도 제공됩니다. 알림을 데이터베이스에 저장하여 웹 인터페이스에 표시할 수도 있습니다.
알림은 일반적으로 애플리케이션에서 발생한 일을 사용자에게 알려주는 짧은 정보 메시지입니다. 예를 들어 청구 애플리케이션에서는 이메일과 SMS로 청구서 결제 완료 알림을 보낼 수 있습니다.
알림 생성
Laravel에서 각 알림은 보통 app/Notifications에 저장하는 하나의 클래스로 표현됩니다. 디렉터리가 없어도 make:notification Artisan 명령어를 실행하면 생성됩니다:
php artisan make:notification InvoicePaid이 명령어는 app/Notifications에 새 알림 클래스를 만듭니다. 각 클래스에는 via와 함께 toMail, toDatabase 등 채널에 맞는 메시지를 구성하는 메서드들이 포함됩니다.
알림 전송
Notifiable 트레이트 사용
알림은 Notifiable 트레이트의 notify 또는 Notification 파사드로 전송할 수 있습니다. 기본적으로 App\Models\User 모델에는 Notifiable이 포함됩니다:
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
}트레이트가 제공하는 notify는 알림 인스턴스를 받습니다:
use App\Notifications\InvoicePaid;
$user->notify(new InvoicePaid($invoice));NOTE
Notifiable은 User뿐 아니라 모든 모델에 사용할 수 있습니다.
Notification 파사드 사용
Notification 파사드로도 알림을 보낼 수 있습니다. 사용자 컬렉션처럼 알림을 받을 여러 대상에게 전송할 때 유용합니다. send에 전체 수신 대상과 알림 인스턴스를 전달합니다:
use Illuminate\Support\Facades\Notification;
Notification::send($users, new InvoicePaid($invoice));sendNow로 즉시 전송할 수도 있습니다. 알림이 ShouldQueue를 구현하더라도 바로 전송합니다:
Notification::sendNow($developers, new DeploymentCompleted($deployment));전달 채널 지정
각 알림 클래스의 via는 전달 채널을 결정합니다. mail, database, broadcast, vonage, slack 채널로 보낼 수 있습니다.
NOTE
Telegram이나 Pusher 같은 다른 채널은 커뮤니티의 Laravel Notification Channels 웹사이트를 확인하세요.
via는 알림을 받을 클래스의 $notifiable 인스턴스를 받습니다. 이를 이용해 전달 채널을 결정할 수 있습니다:
/**
* Get the notification's delivery channels.
*
* @return array<int, string>
*/
public function via(object $notifiable): array
{
return $notifiable->prefers_sms ? ['vonage'] : ['mail', 'database'];
}알림 큐 처리
WARNING
알림을 큐에 넣기 전에 큐를 설정하고 워커를 시작해야 합니다.
외부 API를 호출하는 채널 등에서는 알림 전송에 시간이 걸릴 수 있습니다. 응답 시간을 줄이려면 클래스에 ShouldQueue 인터페이스와 Queueable 트레이트를 추가하여 큐에서 처리합니다. make:notification으로 생성한 클래스에는 두 항목이 이미 가져와져 있어 바로 추가할 수 있습니다:
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
class InvoicePaid extends Notification implements ShouldQueue
{
use Queueable;
// ...
}ShouldQueue를 추가한 뒤에도 평소처럼 알림을 전송하면 됩니다. Laravel이 인터페이스를 감지하여 전송 작업을 자동으로 큐에 넣습니다:
$user->notify(new InvoicePaid($invoice));알림을 큐로 처리할 때는 수신자와 채널의 각 조합마다 Job이 생성됩니다. 예를 들어 수신자가 세 명이고 채널이 두 개이면 여섯 개의 Job이 큐에 전달됩니다.
알림 지연
전송을 늦추려면 알림 인스턴스를 생성할 때 delay를 연결합니다:
$delay = now()->plus(minutes: 10);
$user->notify((new InvoicePaid($invoice))->delay($delay));delay에 배열을 전달하면 채널별 지연 시간을 지정할 수 있습니다:
$user->notify((new InvoicePaid($invoice))->delay([
'mail' => now()->plus(minutes: 5),
'sms' => now()->plus(minutes: 10),
]));알림 클래스 자체에 withDelay를 정의할 수도 있습니다. 채널 이름과 지연 값의 배열을 반환해야 합니다:
/**
* Determine the notification's delivery delay.
*
* @return array<string, \Illuminate\Support\Carbon>
*/
public function withDelay(object $notifiable): array
{
return [
'mail' => now()->plus(minutes: 5),
'sms' => now()->plus(minutes: 10),
];
}알림 큐 연결 변경
큐 알림은 기본적으로 애플리케이션의 기본 큐 연결을 사용합니다. 특정 알림에 다른 연결을 지정하려면 생성자에서 onConnection을 호출합니다:
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
class InvoicePaid extends Notification implements ShouldQueue
{
use Queueable;
/**
* Create a new notification instance.
*/
public function __construct()
{
$this->onConnection('redis');
}
}채널별로 큐 연결을 지정하려면 알림에 viaConnections를 정의합니다. 채널 이름과 큐 연결 이름의 쌍으로 구성된 배열을 반환해야 합니다:
/**
* Determine which connections should be used for each notification channel.
*
* @return array<string, string>
*/
public function viaConnections(): array
{
return [
'mail' => 'redis',
'database' => 'sync',
];
}알림 채널별 큐 변경
채널마다 특정 큐를 사용하려면 viaQueues를 정의합니다. 채널 이름과 큐 이름의 쌍으로 구성된 배열을 반환합니다:
/**
* Determine which queues should be used for each notification channel.
*
* @return array<string, string>
*/
public function viaQueues(): array
{
return [
'mail' => 'mail-queue',
'slack' => 'slack-queue',
];
}큐 알림 Job 속성 변경
알림 클래스에 큐 속성을 정의하여 내부 Job의 동작을 조정할 수 있습니다. 알림을 전송하는 큐 Job이 이 속성들을 상속합니다:
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
use Illuminate\Queue\Attributes\FailOnTimeout;
use Illuminate\Queue\Attributes\MaxExceptions;
use Illuminate\Queue\Attributes\Timeout;
use Illuminate\Queue\Attributes\Tries;
#[Tries(5)]
#[Timeout(120)]
#[MaxExceptions(3)]
#[FailOnTimeout]
class InvoicePaid extends Notification implements ShouldQueue
{
use Queueable;
// ...
}암호화로 큐 알림 데이터의 기밀성과 무결성을 보호하려면 클래스에 ShouldBeEncrypted를 추가합니다:
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
class InvoicePaid extends Notification implements ShouldQueue, ShouldBeEncrypted
{
use Queueable;
// ...
}알림 클래스에 속성을 직접 정의하는 것 외에도 backoff와 retryUntil로 Job의 재시도 대기 전략과 재시도 기한을 지정할 수 있습니다:
use DateTime;
/**
* Calculate the number of seconds to wait before retrying the notification.
*/
public function backoff(): int
{
return 3;
}
/**
* Determine the time at which the notification should timeout.
*/
public function retryUntil(): DateTime
{
return now()->plus(minutes: 5);
}NOTE
Job 속성과 메서드의 자세한 내용은 큐 Job 문서를 참고하세요.
큐 알림 미들웨어
큐 알림도 큐 Job과 같은 방식으로 미들웨어를 정의할 수 있습니다. 알림 클래스에 middleware를 정의합니다. $notifiable과 $channel을 받아 목적지에 맞게 반환할 미들웨어를 조정할 수 있습니다:
use Illuminate\Queue\Middleware\RateLimited;
/**
* Get the middleware the notification job should pass through.
*
* @return array<int, object>
*/
public function middleware(object $notifiable, string $channel)
{
return match ($channel) {
'mail' => [new RateLimited('postmark')],
'slack' => [new RateLimited('slack')],
default => [],
};
}큐 알림과 데이터베이스 트랜잭션
트랜잭션 안에서 큐 알림을 전달하면 트랜잭션 커밋 전에 큐에서 처리될 수 있습니다. 트랜잭션 중 수정한 모델이나 레코드가 아직 반영되지 않았거나, 새 레코드가 존재하지 않을 수 있습니다. 알림이 이런 모델에 의존한다면 알림 전송 Job을 처리할 때 예상치 못한 오류가 발생할 수 있습니다.
큐 연결의 after_commit이 false여도 전송 시 afterCommit을 호출하면 열려 있는 모든 트랜잭션이 커밋된 후 해당 알림을 전달하도록 지정할 수 있습니다:
use App\Notifications\InvoicePaid;
$user->notify((new InvoicePaid($invoice))->afterCommit());알림 생성자에서 afterCommit을 호출할 수도 있습니다:
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
class InvoicePaid extends Notification implements ShouldQueue
{
use Queueable;
/**
* Create a new notification instance.
*/
public function __construct()
{
$this->afterCommit();
}
}NOTE
이 문제를 해결하는 자세한 방법은 큐 Job과 데이터베이스 트랜잭션 문서를 참고하세요.
큐 알림 전송 여부 결정
백그라운드 처리를 위해 큐에 전달한 알림은 보통 큐 워커가 받아 지정한 수신자에게 전송합니다.
워커가 처리하는 시점에 최종 전송 여부를 판단하려면 알림 클래스에 shouldSend를 정의합니다. false를 반환하면 전송하지 않습니다:
/**
* Determine if the notification should be sent.
*/
public function shouldSend(object $notifiable, string $channel): bool
{
return $this->invoice->isPaid();
}알림 전송 후 처리
알림을 보낸 후 코드를 실행하려면 afterSending을 정의합니다. 수신 대상, 채널 이름, 채널의 응답을 받습니다:
/**
* Handle the notification after it has been sent.
*/
public function afterSending(object $notifiable, string $channel, mixed $response): void
{
// ...
}필요에 따라 수신자 지정
애플리케이션의 사용자로 저장되지 않은 사람에게 알림을 보내야 할 수 있습니다. Notification 파사드의 route로 전송 전에 임시 라우팅 정보를 지정합니다:
use Illuminate\Broadcasting\Channel;
use Illuminate\Support\Facades\Notification;
Notification::route('mail', 'taylor@example.com')
->route('vonage', '5555555555')
->route('slack', '#slack-channel')
->route('broadcast', [new Channel('channel-name')])
->notify(new InvoicePaid($invoice));이 방식으로 mail 채널에 보낼 때 수신자 이름도 지정하려면 이메일 주소를 키로, 이름을 값으로 하는 첫 번째 항목을 가진 배열을 전달합니다:
Notification::route('mail', [
'barrett@example.com' => 'Barrett Blair',
])->notify(new InvoicePaid($invoice));routes로 여러 채널의 임시 라우팅 정보를 한 번에 지정할 수 있습니다:
Notification::routes([
'mail' => ['barrett@example.com' => 'Barrett Blair'],
'vonage' => '5555555555',
])->notify(new InvoicePaid($invoice));메일 알림
메일 메시지 구성
이메일로 보낼 수 있는 알림에는 toMail을 정의해야 합니다. $notifiable 대상을 받아 Illuminate\Notifications\Messages\MailMessage 인스턴스를 반환합니다.
MailMessage는 트랜잭션 이메일을 구성하는 간단한 메서드들을 제공합니다. 메시지에는 텍스트 줄과 행동 유도 버튼을 넣을 수 있습니다. 다음 toMail 예제를 살펴보겠습니다:
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): MailMessage
{
$url = url('/invoice/'.$this->invoice->id);
return (new MailMessage)
->greeting('Hello!')
->line('One of your invoices has been paid!')
->lineIf($this->amount > 0, "Amount paid: {$this->amount}")
->action('View Invoice', $url)
->line('Thank you for using our application!');
}NOTE
toMail에서 $this->invoice->id를 사용합니다. 메시지 생성에 필요한 데이터는 알림 생성자에 전달할 수 있습니다.
예제는 인사말, 텍스트, 행동 유도 버튼, 추가 텍스트를 등록합니다. MailMessage 메서드로 간단한 트랜잭션 이메일을 빠르게 구성할 수 있습니다. mail 채널은 메시지 구성 요소를 반응형 HTML 이메일 템플릿과 일반 텍스트 버전으로 변환합니다. 다음은 생성되는 이메일의 예입니다:
NOTE
메일 알림을 보낼 때는 config/app.php의 name을 설정하세요. 메일 메시지의 머리글과 바닥글에 사용됩니다.
오류 메시지
청구서 결제 실패처럼 오류를 알리는 알림은 메시지 구성 시 error를 호출하여 오류 메시지임을 표시할 수 있습니다. 이 경우 행동 유도 버튼이 검은색 대신 빨간색으로 표시됩니다:
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->error()
->subject('Invoice Payment Failed')
->line('...');
}기타 메일 알림 구성 방법
클래스에서 텍스트 줄을 정의하는 대신 view로 이메일 렌더링에 사용할 사용자 정의 템플릿을 지정할 수 있습니다:
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)->view(
'mail.invoice.paid', ['invoice' => $this->invoice]
);
}view에 전달하는 배열의 두 번째 요소에 뷰 이름을 넣어 일반 텍스트 뷰를 지정할 수 있습니다:
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)->view(
['mail.invoice.paid', 'mail.invoice.paid-text'],
['invoice' => $this->invoice]
);
}일반 텍스트 뷰만 있다면 text를 사용합니다:
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)->text(
'mail.invoice.paid-text', ['invoice' => $this->invoice]
);
}발신자 변경
기본 발신 주소는 config/mail.php에 정의됩니다. 특정 알림의 발신 주소는 from으로 지정할 수 있습니다:
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->from('barrett@example.com', 'Barrett Blair')
->line('...');
}수신자 변경
mail 채널은 수신 대상의 email 속성을 자동으로 찾습니다. 다른 주소로 보내려면 수신 대상에 routeNotificationForMail을 정의합니다:
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Notifications\Notification;
class User extends Authenticatable
{
use Notifiable;
/**
* Route notifications for the mail channel.
*
* @return array<string, string>|string
*/
public function routeNotificationForMail(Notification $notification): array|string
{
// Return email address only...
return $this->email_address;
// Return email address and name...
return [$this->email_address => $this->name];
}
}제목 변경
기본 이메일 제목은 알림 클래스 이름을 Title Case로 변환한 값입니다. 예를 들어 InvoicePaid이면 Invoice Paid입니다. 다른 제목을 지정하려면 메시지를 구성할 때 subject를 호출합니다:
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->subject('Notification Subject')
->line('...');
}메일러 변경
메일 알림은 기본적으로 config/mail.php의 기본 메일러를 사용합니다. 메시지 구성 시 mailer를 호출하면 실행 시점에 다른 메일러를 지정할 수 있습니다:
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->mailer('postmark')
->line('...');
}템플릿 변경
알림 패키지 리소스를 게시하면 메일 알림의 HTML 및 일반 텍스트 템플릿을 수정할 수 있습니다. 다음 명령어 실행 후 템플릿은 resources/views/vendor/notifications에 위치합니다:
php artisan vendor:publish --tag=laravel-notifications첨부 파일
메시지를 구성할 때 attach로 파일을 첨부합니다. 첫 번째 인수로 파일의 절대 경로를 받습니다:
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->greeting('Hello!')
->attach('/path/to/file');
}NOTE
알림 메일 메시지의 attach는 첨부 가능 객체도 받습니다. 자세한 내용은 첨부 가능 객체 문서를 참고하세요.
attach의 두 번째 인수로 배열을 전달하면 표시 이름이나 MIME 유형도 지정할 수 있습니다:
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->greeting('Hello!')
->attach('/path/to/file', [
'as' => 'name.pdf',
'mime' => 'application/pdf',
]);
}여러 파일을 첨부하려면 attachMany를 사용할 수 있습니다:
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->greeting('Hello!')
->attachMany([
'/path/to/forge.svg',
'/path/to/vapor.svg' => [
'as' => 'Logo.svg',
'mime' => 'image/svg+xml',
],
]);
}특정 파일시스템 디스크의 파일은 attachFromStorageDisk로 첨부할 수 있습니다. 디스크 이름과 해당 디스크의 파일 경로를 받습니다:
use App\Mail\InvoicePaid as InvoicePaidMailable;
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): Mailable
{
return (new InvoicePaidMailable($this->invoice))
->to($notifiable->email)
->attachFromStorageDisk('s3', '/path/to/file', 'invoice.pdf', [
'mime' => 'application/pdf',
]);
}원시 데이터 첨부
attachData는 바이트 문자열을 첨부 파일로 추가합니다. 첨부 파일에 사용할 이름을 함께 지정해야 합니다:
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->greeting('Hello!')
->attachData($this->pdf, 'name.pdf', [
'mime' => 'application/pdf',
]);
}태그와 메타데이터 추가
Mailgun이나 Postmark 같은 일부 외부 이메일 프로바이더는 태그와 메타데이터로 발송 이메일을 묶고 추적할 수 있게 합니다. tag와 metadata로 메시지에 추가할 수 있습니다:
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->greeting('Comment Upvoted!')
->tag('upvote')
->metadata('comment_id', $this->comment->id);
}Mailgun 드라이버를 사용한다면 태그와 메타데이터 문서를 참고하세요. Postmark도 태그와 메타데이터 지원 문서를 제공합니다.
Amazon SES로 이메일을 보낸다면 metadata로 SES 태그를 메시지에 추가해야 합니다.
Symfony 메시지 조정
MailMessage의 withSymfonyMessage로 등록한 클로저는 전송 전에 Symfony 메시지 인스턴스를 받아 실행됩니다. 메시지를 전달하기 전에 세부 내용을 조정할 수 있습니다:
use Symfony\Component\Mime\Email;
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->withSymfonyMessage(function (Email $message) {
$message->getHeaders()->addTextHeader(
'Custom-Header', 'Header Value'
);
});
}Mailable 사용
필요하면 알림의 toMail에서 완전한 Mailable 객체를 반환할 수 있습니다. MailMessage 대신 Mailable을 반환할 때는 객체의 to로 수신자를 지정해야 합니다:
use App\Mail\InvoicePaid as InvoicePaidMailable;
use Illuminate\Mail\Mailable;
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): Mailable
{
return (new InvoicePaidMailable($this->invoice))
->to($notifiable->email);
}Mailable과 임시 수신자 알림
임시 수신자 알림을 보낼 때 toMail에 전달되는 $notifiable은 Illuminate\Notifications\AnonymousNotifiable입니다. 이 객체의 routeNotificationFor로 전송할 이메일 주소를 가져올 수 있습니다:
use App\Mail\InvoicePaid as InvoicePaidMailable;
use Illuminate\Notifications\AnonymousNotifiable;
use Illuminate\Mail\Mailable;
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): Mailable
{
$address = $notifiable instanceof AnonymousNotifiable
? $notifiable->routeNotificationFor('mail')
: $notifiable->email;
return (new InvoicePaidMailable($this->invoice))
->to($address);
}메일 알림 미리보기
메일 템플릿을 디자인할 때는 일반적인 Blade 템플릿처럼 렌더링된 메시지를 브라우저에서 빠르게 확인하면 편리합니다. Laravel은 메일 알림이 생성한 메시지를 라우트 클로저나 컨트롤러에서 직접 반환할 수 있게 합니다. MailMessage를 반환하면 브라우저에 렌더링되므로 실제 이메일 주소로 보내지 않고 디자인을 확인할 수 있습니다:
use App\Models\Invoice;
use App\Notifications\InvoicePaid;
Route::get('/notification', function () {
$invoice = Invoice::find(1);
return (new InvoicePaid($invoice))
->toMail($invoice->user);
});Markdown 메일 알림
Markdown 메일 알림은 기존 메일 템플릿을 활용하면서 더 길고 자유로운 메시지를 작성할 수 있게 합니다. Markdown으로 작성하면 Laravel이 반응형 HTML 템플릿을 렌더링하면서 일반 텍스트 버전도 자동 생성합니다.
메시지 생성
Markdown 템플릿을 함께 생성하려면 make:notification의 --markdown 옵션을 사용합니다:
php artisan make:notification InvoicePaid --markdown=mail.invoice.paidMarkdown 템플릿을 사용하는 알림도 다른 메일 알림처럼 toMail을 정의합니다. 다만 line과 action 대신 markdown으로 템플릿 이름을 지정합니다. 두 번째 인수에는 템플릿에서 사용할 데이터 배열을 전달할 수 있습니다:
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): MailMessage
{
$url = url('/invoice/'.$this->invoice->id);
return (new MailMessage)
->subject('Invoice Paid')
->markdown('mail.invoice.paid', ['url' => $url]);
}메시지 작성
Markdown 메일 알림은 Blade 컴포넌트와 Markdown 문법을 함께 사용합니다. Laravel이 제공하는 알림 컴포넌트로 메시지를 쉽게 구성할 수 있습니다:
<x-mail::message>
# Invoice Paid
Your invoice has been paid!
<x-mail::button :url="$url">
View Invoice
</x-mail::button>
Thanks,<br>
{{ config('app.name') }}
</x-mail::message>NOTE
Markdown 이메일에서는 과도한 들여쓰기를 피하세요. Markdown 표준에 따라 들여쓴 내용은 코드 블록으로 렌더링됩니다.
버튼 컴포넌트
버튼 컴포넌트는 가운데 정렬된 버튼 링크를 표시합니다. url과 선택 사항인 color를 받으며, 지원하는 색상은 primary, green, red입니다. 알림에 필요한 만큼 버튼을 추가할 수 있습니다:
<x-mail::button :url="$url" color="green">
View Invoice
</x-mail::button>패널 컴포넌트
패널 컴포넌트는 나머지 알림과 조금 다른 배경색의 패널에 텍스트 블록을 표시합니다. 특정 내용에 주의를 끌 때 유용합니다:
<x-mail::panel>
This is the panel content.
</x-mail::panel>테이블 컴포넌트
테이블 컴포넌트는 내용으로 전달한 Markdown 표를 HTML 표로 변환합니다. 기본 Markdown 표 정렬 문법으로 컬럼 정렬을 지정할 수 있습니다:
<x-mail::table>
| Laravel | Table | Example |
| ------------- | :-----------: | ------------: |
| Col 2 is | Centered | $10 |
| Col 3 is | Right-Aligned | $20 |
</x-mail::table>컴포넌트 변경
모든 Markdown 알림 컴포넌트를 애플리케이션에 내보내 수정할 수 있습니다. vendor:publish Artisan 명령어로 laravel-mail 태그의 리소스를 게시합니다:
php artisan vendor:publish --tag=laravel-mail컴포넌트는 resources/views/vendor/mail에 게시됩니다. mail에는 html과 text 디렉터리가 있으며 각 컴포넌트의 HTML 및 텍스트 표현을 담고 있습니다. 필요에 맞게 수정할 수 있습니다.
CSS 변경
컴포넌트를 내보내면 resources/views/vendor/mail/html/themes에 default.css가 생성됩니다. 이 파일을 수정하면 스타일이 Markdown 알림의 HTML에 자동으로 인라인 적용됩니다.
새 테마를 만들려면 html/themes에 CSS 파일을 저장한 뒤 mail 설정의 theme을 새 테마 이름으로 변경합니다.
특정 알림의 테마만 변경하려면 메일 메시지를 구성할 때 theme을 호출합니다. 전송에 사용할 테마 이름을 받습니다:
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->theme('invoice')
->subject('Invoice Paid')
->markdown('mail.invoice.paid', ['url' => $url]);
}데이터베이스 알림
사전 준비
database 채널은 알림 정보를 데이터베이스 테이블에 저장합니다. 테이블에는 알림 유형과 알림을 설명하는 JSON 데이터 구조 등이 포함됩니다.
테이블을 조회해 사용자 인터페이스에 알림을 표시할 수 있습니다. 먼저 저장용 테이블을 만들어야 합니다. make:notifications-table로 적절한 스키마의 마이그레이션을 생성합니다:
php artisan make:notifications-tablephp artisan migrateNOTE
수신 대상 모델이 UUID 또는 ULID 기본 키를 사용한다면 알림 테이블 마이그레이션의 morphs를 uuidMorphs 또는 ulidMorphs로 바꿔야 합니다.
데이터베이스 알림 구성
데이터베이스에 저장할 알림은 toDatabase나 toArray를 정의해야 합니다. $notifiable을 받아 일반 PHP 배열을 반환합니다. 배열은 JSON으로 인코딩되어 notifications의 data 컬럼에 저장됩니다. 다음은 toArray 예제입니다:
/**
* Get the array representation of the notification.
*
* @return array<string, mixed>
*/
public function toArray(object $notifiable): array
{
return [
'invoice_id' => $this->invoice->id,
'amount' => $this->invoice->amount,
];
}데이터베이스에 저장할 때 type은 기본적으로 알림 클래스 이름이며 read_at은 null입니다. databaseType과 initialDatabaseReadAtValue를 정의하여 변경할 수 있습니다:
use Illuminate\Support\Carbon;
/**
* Get the notification's database type.
*/
public function databaseType(object $notifiable): string
{
return 'invoice-paid';
}
/**
* Get the initial value for the "read_at" column.
*/
public function initialDatabaseReadAtValue(): ?Carbon
{
return null;
}`toDatabase`와 `toArray`
toArray는 broadcast 채널에서도 JavaScript 프런트엔드에 전송할 데이터를 결정하는 데 사용됩니다. database와 broadcast 채널에 서로 다른 배열 표현을 사용하려면 toArray 대신 toDatabase를 정의해야 합니다.
알림 조회
데이터베이스에 저장한 알림은 수신 대상에서 쉽게 조회할 수 있어야 합니다. 기본 App\Models\User에 포함된 Illuminate\Notifications\Notifiable 트레이트는 해당 대상의 알림을 반환하는 notifications Eloquent 관계를 제공합니다. 다른 관계처럼 접근하면 됩니다. 기본적으로 created_at 기준 최신 알림이 컬렉션의 앞에 오도록 정렬합니다:
$user = App\Models\User::find(1);
foreach ($user->notifications as $notification) {
echo $notification->type;
}읽지 않은 알림만 가져오려면 unreadNotifications 관계를 사용합니다. 역시 created_at 기준으로 최신 알림이 앞에 옵니다:
$user = App\Models\User::find(1);
foreach ($user->unreadNotifications as $notification) {
echo $notification->type;
}읽은 알림만 가져오려면 readNotifications를 사용합니다:
$user = App\Models\User::find(1);
foreach ($user->readNotifications as $notification) {
echo $notification->type;
}NOTE
JavaScript 클라이언트에서 알림에 접근하려면 현재 사용자 등 수신 대상의 알림을 반환하는 컨트롤러를 정의하세요. JavaScript에서 해당 URL로 HTTP 요청을 보내면 됩니다.
읽음 표시
사용자가 알림을 확인하면 읽음으로 표시하는 것이 일반적입니다. Illuminate\Notifications\Notifiable 트레이트가 제공하는 markAsRead는 알림 레코드의 read_at을 갱신합니다:
$user = App\Models\User::find(1);
foreach ($user->unreadNotifications as $notification) {
$notification->markAsRead();
}각 알림을 순회하는 대신 알림 컬렉션에서 markAsRead를 직접 호출할 수도 있습니다:
$user->unreadNotifications->markAsRead();알림을 조회하지 않고 일괄 갱신 쿼리로 모두 읽음 표시할 수도 있습니다:
$user = App\Models\User::find(1);
$user->unreadNotifications()->update(['read_at' => now()]);테이블에서 완전히 제거하려면 delete를 사용합니다:
$user->notifications()->delete();브로드캐스트 알림
사전 준비
알림을 브로드캐스트하기 전에 Laravel 이벤트 브로드캐스팅을 설정하고 사용법을 익혀야 합니다. JavaScript 프런트엔드에서 서버의 Laravel 이벤트에 반응할 수 있게 하는 서비스입니다.
브로드캐스트 알림 구성
broadcast 채널은 Laravel 이벤트 브로드캐스팅으로 알림을 전달하여 JavaScript 프런트엔드에서 실시간으로 받을 수 있게 합니다. 알림 클래스에 toBroadcast를 정의하면 $notifiable을 받아 BroadcastMessage를 반환합니다. 없으면 toArray로 전송할 데이터를 구성합니다. 데이터는 JSON으로 인코딩되어 프런트엔드에 브로드캐스트됩니다:
use Illuminate\Notifications\Messages\BroadcastMessage;
/**
* Get the broadcastable representation of the notification.
*/
public function toBroadcast(object $notifiable): BroadcastMessage
{
return new BroadcastMessage([
'invoice_id' => $this->invoice->id,
'amount' => $this->invoice->amount,
]);
}브로드캐스트 큐 설정
모든 브로드캐스트 알림은 큐에서 처리됩니다. 브로드캐스트 작업의 큐 연결이나 이름은 BroadcastMessage의 onConnection과 onQueue로 지정합니다:
return (new BroadcastMessage($data))
->onConnection('sqs')
->onQueue('broadcasts');알림 유형 변경
지정한 데이터 외에도 모든 브로드캐스트 알림에는 알림의 전체 클래스 이름을 담는 type이 있습니다. broadcastType을 정의하여 변경할 수 있습니다:
/**
* Get the type of the notification being broadcast.
*/
public function broadcastType(): string
{
return 'broadcast.message';
}알림 수신
알림은 {notifiable}.{id} 형식의 비공개 채널로 브로드캐스트됩니다. ID가 1인 App\Models\User에 보내면 App.Models.User.1 채널을 사용합니다. Laravel Echo의 notification으로 쉽게 수신할 수 있습니다:
Echo.private('App.Models.User.' + userId)
.notification((notification) => {
console.log(notification.type);
});React, Vue, Svelte 사용
Laravel Echo는 알림 수신을 위한 React, Vue, Svelte 훅을 제공합니다. useEchoNotification을 호출하면 알림을 수신하며, 사용하는 컴포넌트가 언마운트될 때 채널을 자동으로 떠납니다:
React
import { useEchoNotification } from "@laravel/echo-react";
useEchoNotification(
`App.Models.User.${userId}`,
(notification) => {
console.log(notification.type);
},
);Vue
<script setup lang="ts">
import { useEchoNotification } from "@laravel/echo-vue";
useEchoNotification(
`App.Models.User.${userId}`,
(notification) => {
console.log(notification.type);
},
);
</script>Svelte
<script>
import { useEchoNotification } from "@laravel/echo-svelte";
useEchoNotification(
`App.Models.User.${userId}`,
(notification) => {
console.log(notification.type);
},
);
</script>기본적으로 모든 알림을 수신합니다. 유형을 제한하려면 useEchoNotification에 유형 문자열이나 배열을 전달합니다:
React
import { useEchoNotification } from "@laravel/echo-react";
useEchoNotification(
`App.Models.User.${userId}`,
(notification) => {
console.log(notification.type);
},
'App.Notifications.InvoicePaid',
);Vue
<script setup lang="ts">
import { useEchoNotification } from "@laravel/echo-vue";
useEchoNotification(
`App.Models.User.${userId}`,
(notification) => {
console.log(notification.type);
},
'App.Notifications.InvoicePaid',
);
</script>Svelte
<script>
import { useEchoNotification } from "@laravel/echo-svelte";
useEchoNotification(
`App.Models.User.${userId}`,
(notification) => {
console.log(notification.type);
},
'App.Notifications.InvoicePaid',
);
</script>알림 페이로드의 데이터 구조도 지정할 수 있어 타입 안전성과 편집 편의성을 높일 수 있습니다:
type InvoicePaidNotification = {
invoice_id: number;
created_at: string;
};
useEchoNotification<InvoicePaidNotification>(
`App.Models.User.${userId}`,
(notification) => {
console.log(notification.invoice_id);
console.log(notification.created_at);
console.log(notification.type);
},
'App.Notifications.InvoicePaid',
);알림 채널 변경
수신 대상의 브로드캐스트 채널을 변경하려면 대상에 receivesBroadcastNotificationsOn을 정의합니다:
<?php
namespace App\Models;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
/**
* The channels the user receives notification broadcasts on.
*/
public function receivesBroadcastNotificationsOn(): string
{
return 'users.'.$this->id;
}
}SMS 알림
사전 준비
Laravel의 SMS 알림은 Vonage(이전 이름 Nexmo)를 사용합니다. 먼저 laravel/vonage-notification-channel과 guzzlehttp/guzzle을 설치해야 합니다:
composer require laravel/vonage-notification-channel guzzlehttp/guzzle패키지는 설정 파일을 포함하지만 애플리케이션에 내보낼 필요는 없습니다. VONAGE_KEY와 VONAGE_SECRET 환경 변수로 공개 키와 비밀 키를 정의할 수 있습니다.
키를 정의한 뒤 기본 발신 번호를 나타내는 VONAGE_SMS_FROM을 설정합니다. 번호는 Vonage 제어판에서 생성할 수 있습니다:
VONAGE_SMS_FROM=15556666666SMS 알림 구성
SMS를 지원하는 알림에는 toVonage를 정의합니다. $notifiable을 받아 Illuminate\Notifications\Messages\VonageMessage를 반환해야 합니다:
use Illuminate\Notifications\Messages\VonageMessage;
/**
* Get the Vonage / SMS representation of the notification.
*/
public function toVonage(object $notifiable): VonageMessage
{
return (new VonageMessage)
->content('Your SMS message content');
}유니코드 내용
SMS에 유니코드 문자가 포함된다면 VonageMessage를 구성할 때 unicode를 호출해야 합니다:
use Illuminate\Notifications\Messages\VonageMessage;
/**
* Get the Vonage / SMS representation of the notification.
*/
public function toVonage(object $notifiable): VonageMessage
{
return (new VonageMessage)
->content('Your unicode message')
->unicode();
}발신 번호 변경
VONAGE_SMS_FROM과 다른 번호로 특정 알림을 보내려면 VonageMessage의 from을 사용합니다:
use Illuminate\Notifications\Messages\VonageMessage;
/**
* Get the Vonage / SMS representation of the notification.
*/
public function toVonage(object $notifiable): VonageMessage
{
return (new VonageMessage)
->content('Your SMS message content')
->from('15554443333');
}클라이언트 참조 추가
사용자, 팀, 클라이언트별 비용을 추적하려면 알림에 클라이언트 참조를 추가할 수 있습니다. Vonage는 이 참조로 보고서를 생성할 수 있어 고객별 SMS 사용량을 파악하기 쉽습니다. 최대 40자의 문자열을 사용할 수 있습니다:
use Illuminate\Notifications\Messages\VonageMessage;
/**
* Get the Vonage / SMS representation of the notification.
*/
public function toVonage(object $notifiable): VonageMessage
{
return (new VonageMessage)
->clientReference((string) $notifiable->id)
->content('Your SMS message content');
}SMS 알림 라우팅
Vonage 알림을 올바른 번호로 보내려면 수신 대상에 routeNotificationForVonage를 정의합니다:
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Notifications\Notification;
class User extends Authenticatable
{
use Notifiable;
/**
* Route notifications for the Vonage channel.
*/
public function routeNotificationForVonage(Notification $notification): string
{
return $this->phone_number;
}
}Slack 알림
사전 준비
Slack 알림을 보내기 전에 Composer로 알림 채널을 설치합니다:
composer require laravel/slack-notification-channelSlack 워크스페이스에 Slack 앱도 생성해야 합니다.
앱이 생성된 워크스페이스에만 보낸다면 chat:write, chat:write.public, chat:write.customize 범위를 앱에 부여해야 합니다. Slack 앱 관리의 OAuth & Permissions 탭에서 추가할 수 있습니다.
다음으로 앱의 Bot User OAuth Token을 복사하여 애플리케이션의 services.php에 있는 slack 설정 배열에 넣습니다. 토큰은 Slack의 OAuth & Permissions 탭에서 확인할 수 있습니다:
'slack' => [
'notifications' => [
'bot_user_oauth_token' => env('SLACK_BOT_USER_OAUTH_TOKEN'),
'channel' => env('SLACK_BOT_USER_DEFAULT_CHANNEL'),
],
],앱 배포
애플리케이션 사용자가 소유한 외부 Slack 워크스페이스에 알림을 보내려면 Slack을 통해 앱을 배포해야 합니다. Manage Distribution 탭에서 관리합니다. 배포 후 Socialite로 사용자를 대신해 Slack 봇 토큰을 얻을 수 있습니다.
Slack 알림 구성
Slack 메시지를 지원하는 알림에는 toSlack을 정의합니다. $notifiable을 받아 Illuminate\Notifications\Slack\SlackMessage를 반환합니다. Slack Block Kit API로 풍부한 알림을 구성할 수 있습니다. 다음 예제는 Slack Block Kit 빌더에서 미리 볼 수 있습니다:
use Illuminate\Notifications\Slack\BlockKit\Blocks\ContextBlock;
use Illuminate\Notifications\Slack\BlockKit\Blocks\SectionBlock;
use Illuminate\Notifications\Slack\SlackMessage;
/**
* Get the Slack representation of the notification.
*/
public function toSlack(object $notifiable): SlackMessage
{
return (new SlackMessage)
->text('One of your invoices has been paid!')
->headerBlock('Invoice Paid')
->contextBlock(function (ContextBlock $block) {
$block->text('Customer #1234');
})
->sectionBlock(function (SectionBlock $block) {
$block->text('An invoice has been paid.');
$block->field("*Invoice No:*\n1000")->markdown();
$block->field("*Invoice Recipient:*\ntaylor@laravel.com")->markdown();
})
->dividerBlock()
->sectionBlock(function (SectionBlock $block) {
$block->text('Congratulations!');
});
}Slack Block Kit 빌더 템플릿 사용
메서드를 연결하여 메시지를 구성하는 대신, Slack Block Kit 빌더가 생성한 원시 JSON 페이로드를 usingBlockKitTemplate에 전달할 수 있습니다:
use Illuminate\Notifications\Slack\SlackMessage;
use Illuminate\Support\Str;
/**
* Get the Slack representation of the notification.
*/
public function toSlack(object $notifiable): SlackMessage
{
$template = <<<JSON
{
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
"text": "Team Announcement"
}
},
{
"type": "section",
"text": {
"type": "plain_text",
"text": "We are hiring!"
}
}
]
}
JSON;
return (new SlackMessage)
->usingBlockKitTemplate($template);
}Slack 상호작용
Slack Block Kit 알림은 사용자 상호작용 처리 기능을 제공합니다. 사용하려면 Slack 앱에서 Interactivity를 활성화하고 애플리케이션이 제공하는 URL을 Request URL로 설정해야 합니다. Slack의 Interactivity & Shortcuts 탭에서 관리합니다.
아래 actionsBlock 예제에서는 버튼을 클릭한 사용자, 버튼 ID 등을 담은 페이로드를 Slack이 Request URL에 POST로 보냅니다. 애플리케이션은 이를 바탕으로 수행할 작업을 결정합니다. 요청이 Slack에서 온 것인지도 검증해야 합니다:
use Illuminate\Notifications\Slack\BlockKit\Blocks\ActionsBlock;
use Illuminate\Notifications\Slack\BlockKit\Blocks\ContextBlock;
use Illuminate\Notifications\Slack\BlockKit\Blocks\SectionBlock;
use Illuminate\Notifications\Slack\SlackMessage;
/**
* Get the Slack representation of the notification.
*/
public function toSlack(object $notifiable): SlackMessage
{
return (new SlackMessage)
->text('One of your invoices has been paid!')
->headerBlock('Invoice Paid')
->contextBlock(function (ContextBlock $block) {
$block->text('Customer #1234');
})
->sectionBlock(function (SectionBlock $block) {
$block->text('An invoice has been paid.');
})
->actionsBlock(function (ActionsBlock $block) {
// ID defaults to "button_acknowledge_invoice"...
$block->button('Acknowledge Invoice')->primary();
// Manually configure the ID...
$block->button('Deny')->danger()->id('deny_invoice');
});
}확인 모달
작업을 실행하기 전에 사용자 확인이 필요하면 버튼을 정의할 때 confirm을 호출합니다. 메시지와 ConfirmObject를 받는 클로저를 전달합니다:
use Illuminate\Notifications\Slack\BlockKit\Blocks\ActionsBlock;
use Illuminate\Notifications\Slack\BlockKit\Blocks\ContextBlock;
use Illuminate\Notifications\Slack\BlockKit\Blocks\SectionBlock;
use Illuminate\Notifications\Slack\BlockKit\Composites\ConfirmObject;
use Illuminate\Notifications\Slack\SlackMessage;
/**
* Get the Slack representation of the notification.
*/
public function toSlack(object $notifiable): SlackMessage
{
return (new SlackMessage)
->text('One of your invoices has been paid!')
->headerBlock('Invoice Paid')
->contextBlock(function (ContextBlock $block) {
$block->text('Customer #1234');
})
->sectionBlock(function (SectionBlock $block) {
$block->text('An invoice has been paid.');
})
->actionsBlock(function (ActionsBlock $block) {
$block->button('Acknowledge Invoice')
->primary()
->confirm(
'Acknowledge the payment and send a thank you email?',
function (ConfirmObject $dialog) {
$dialog->confirm('Yes');
$dialog->deny('No');
}
);
});
}Slack 블록 확인
작성 중인 블록을 빠르게 확인하려면 SlackMessage의 dd를 호출합니다. 브라우저에서 페이로드와 알림을 미리 볼 수 있는 Block Kit 빌더 URL을 생성해 출력합니다. true를 전달하면 원시 페이로드를 출력합니다:
return (new SlackMessage)
->text('One of your invoices has been paid!')
->headerBlock('Invoice Paid')
->dd();Slack 알림 라우팅
올바른 Slack 팀과 채널로 보내려면 수신 모델에 routeNotificationForSlack을 정의합니다. 다음 세 가지 값 중 하나를 반환할 수 있습니다:
null: 알림 자체에 설정한 채널을 사용합니다.SlackMessage를 구성할 때to로 채널을 지정할 수 있습니다.- 전송할 채널 문자열: 예를 들어
#support-channel입니다. SlackRoute인스턴스: OAuth 토큰과 채널을 지정합니다. 예를 들어SlackRoute::make($this->slack_channel, $this->slack_token)이며 외부 워크스페이스에 보낼 때 사용해야 합니다.
예를 들어 #support-channel을 반환하면 services.php의 Bot User OAuth 토큰과 연결된 워크스페이스의 해당 채널에 알림을 보냅니다:
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Notifications\Notification;
class User extends Authenticatable
{
use Notifiable;
/**
* Route notifications for the Slack channel.
*/
public function routeNotificationForSlack(Notification $notification): mixed
{
return '#support-channel';
}
}외부 Slack 워크스페이스 알림
NOTE
외부 워크스페이스에 알림을 보내기 전에 Slack 앱을 배포해야 합니다.
애플리케이션 사용자의 Slack 워크스페이스에 알림을 보내려면 먼저 사용자의 Slack OAuth 토큰이 필요합니다. Laravel Socialite의 Slack 드라이버로 사용자를 인증하고 봇 토큰을 얻을 수 있습니다.
토큰을 얻어 데이터베이스에 저장한 뒤 SlackRoute::make로 사용자 워크스페이스에 라우팅합니다. 또한 사용자가 알림을 받을 채널을 지정할 수 있는 기능도 제공하는 것이 좋습니다:
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Slack\SlackRoute;
class User extends Authenticatable
{
use Notifiable;
/**
* Route notifications for the Slack channel.
*/
public function routeNotificationForSlack(Notification $notification): mixed
{
return SlackRoute::make($this->slack_channel, $this->slack_token);
}
}알림 현지화
Laravel은 현재 HTTP 요청과 다른 로케일로 알림을 보낼 수 있으며, 큐에서 처리할 때도 해당 로케일을 기억합니다.
Illuminate\Notifications\Notification의 locale로 언어를 지정합니다. 알림을 평가하는 동안 해당 로케일로 전환하고 완료 후 이전 로케일로 돌아갑니다:
$user->notify((new InvoicePaid($invoice))->locale('es'));Notification 파사드로 여러 수신 대상에 같은 로케일을 적용할 수도 있습니다:
Notification::locale('es')->send(
$users, new InvoicePaid($invoice)
);사용자 선호 로케일
사용자별 선호 로케일을 저장한다면 수신 모델에 HasLocalePreference 계약을 구현하여 알림에 사용하도록 할 수 있습니다:
use Illuminate\Contracts\Translation\HasLocalePreference;
class User extends Model implements HasLocalePreference
{
/**
* Get the user's preferred locale.
*/
public function preferredLocale(): string
{
return $this->locale;
}
}구현 후 Laravel은 해당 모델에 알림과 Mailable을 보낼 때 선호 로케일을 자동 사용하므로 locale을 따로 호출할 필요가 없습니다:
$user->notify(new InvoicePaid($invoice));테스트
Notification 파사드의 fake로 실제 전송을 막을 수 있습니다. 알림 전송 자체는 테스트 대상 코드와 무관한 경우가 많으므로 특정 알림을 보내도록 지시했는지만 확인해도 충분할 수 있습니다.
fake를 호출한 후 사용자에게 전송하도록 지시했는지 검증하고 알림에 전달된 데이터도 확인할 수 있습니다:
Pest
<?php
use App\Notifications\OrderShipped;
use Illuminate\Support\Facades\Notification;
test('orders can be shipped', function () {
Notification::fake();
// Perform order shipping...
// Assert that no notifications were sent...
Notification::assertNothingSent();
// Assert a notification was sent to the given users...
Notification::assertSentTo(
[$user], OrderShipped::class
);
// Assert a notification was not sent...
Notification::assertNotSentTo(
[$user], AnotherNotification::class
);
// Assert a notification was sent twice...
Notification::assertSentTimes(WeeklyReminder::class, 2);
// Assert that a notification was sent to a user exactly once...
Notification::assertSentToOnce($user, OrderShipped::class);
// Assert that a given number of notifications were sent...
Notification::assertCount(3);
});PHPUnit
<?php
namespace Tests\Feature;
use App\Notifications\OrderShipped;
use Illuminate\Support\Facades\Notification;
use Tests\TestCase;
class ExampleTest extends TestCase
{
public function test_orders_can_be_shipped(): void
{
Notification::fake();
// Perform order shipping...
// Assert that no notifications were sent...
Notification::assertNothingSent();
// Assert a notification was sent to the given users...
Notification::assertSentTo(
[$user], OrderShipped::class
);
// Assert a notification was not sent...
Notification::assertNotSentTo(
[$user], AnotherNotification::class
);
// Assert a notification was sent twice...
Notification::assertSentTimes(WeeklyReminder::class, 2);
// Assert that a notification was sent to a user exactly once...
Notification::assertSentToOnce($user, OrderShipped::class);
// Assert that a given number of notifications were sent...
Notification::assertCount(3);
}
}assertSentTo나 assertNotSentTo에 클로저를 전달하여 특정 조건을 만족하는 알림의 전송 여부를 검증할 수 있습니다. 조건에 부합하는 알림이 하나 이상 전송되었다면 전송되었음을 확인하는 검증은 성공합니다:
Notification::assertSentTo(
$user,
function (OrderShipped $notification, array $channels) use ($order) {
return $notification->order->id === $order->id;
}
);assertSentTo나 assertNotSentTo의 세 번째 인수로 예상 속성 값 배열을 전달할 수도 있습니다:
Notification::assertSentTo($user, OrderShipped::class, ['order' => $order]);지정한 모든 속성이 일치해야 합니다. 값은 엄격한 동등 비교를 사용하고 Eloquent 모델은 is로 비교합니다. assertSentOnDemand의 두 번째 인수에도 예상 속성 배열을 전달할 수 있습니다.
임시 수신자 알림
테스트 대상 코드가 임시 수신자 알림을 보낸다면 assertSentOnDemand로 전송 여부를 검증할 수 있습니다:
Notification::assertSentOnDemand(OrderShipped::class);
Notification::assertSentOnDemandOnce(OrderShipped::class);assertSentOnDemand의 두 번째 인수에 클로저를 전달하면 올바른 라우팅 주소로 보냈는지 확인할 수 있습니다:
Notification::assertSentOnDemand(
OrderShipped::class,
function (OrderShipped $notification, array $channels, object $notifiable) use ($user) {
return $notifiable->routes['mail'] === $user->email;
}
);알림 이벤트
알림 전송 중 이벤트
알림을 전송할 때 시스템은 Illuminate\Notifications\Events\NotificationSending을 전달합니다. 수신 대상과 알림 인스턴스가 포함되며, 애플리케이션에 해당 이벤트의 리스너를 만들 수 있습니다:
use Illuminate\Notifications\Events\NotificationSending;
class CheckNotificationStatus
{
/**
* Handle the event.
*/
public function handle(NotificationSending $event): void
{
// ...
}
}NotificationSending 리스너의 handle이 false를 반환하면 알림을 전송하지 않습니다:
/**
* Handle the event.
*/
public function handle(NotificationSending $event): bool
{
return false;
}리스너에서는 이벤트의 notifiable, notification, channel로 수신자와 알림 정보를 확인할 수 있습니다:
/**
* Handle the event.
*/
public function handle(NotificationSending $event): void
{
// $event->channel
// $event->notifiable
// $event->notification
}알림 전송 완료 이벤트
전송 후에는 Illuminate\Notifications\Events\NotificationSent 이벤트가 전달됩니다. 수신 대상과 알림 인스턴스가 포함되며 해당 리스너를 만들 수 있습니다:
use Illuminate\Notifications\Events\NotificationSent;
class LogNotification
{
/**
* Handle the event.
*/
public function handle(NotificationSent $event): void
{
// ...
}
}리스너에서는 notifiable, notification, channel, response로 수신자와 알림 정보를 확인할 수 있습니다:
/**
* Handle the event.
*/
public function handle(NotificationSent $event): void
{
// $event->channel
// $event->notifiable
// $event->notification
// $event->response
}사용자 정의 채널
Laravel은 여러 알림 채널을 기본 제공하지만 다른 채널에 보내기 위한 드라이버를 직접 만들 수도 있습니다. send가 있는 클래스를 정의하면 됩니다. 메서드는 $notifiable과 $notification 두 인수를 받아야 합니다.
send 안에서 알림의 메서드를 호출하여 채널이 이해하는 메시지 객체를 가져온 다음, 원하는 방식으로 $notifiable에 전송합니다:
<?php
namespace App\Notifications;
use Illuminate\Notifications\Notification;
class VoiceChannel
{
/**
* Send the given notification.
*/
public function send(object $notifiable, Notification $notification): void
{
$message = $notification->toVoice($notifiable);
// Send notification to the $notifiable instance...
}
}채널 클래스를 정의한 뒤 알림의 via에서 클래스 이름을 반환합니다. 아래 예제에서 toVoice는 음성 메시지를 표현할 원하는 객체를 반환할 수 있습니다. 예를 들어 VoiceMessage 클래스를 직접 정의할 수 있습니다:
<?php
namespace App\Notifications;
use App\Notifications\Messages\VoiceMessage;
use App\Notifications\VoiceChannel;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
class InvoicePaid extends Notification
{
use Queueable;
/**
* Get the notification channels.
*/
public function via(object $notifiable): string
{
return VoiceChannel::class;
}
/**
* Get the voice representation of the notification.
*/
public function toVoice(object $notifiable): VoiceMessage
{
// ...
}
}