Notification이란
Laravel의 알림(Notification) 시스템은 메일·SMS·Slack·데이터베이스 등 여러 배송 채널에 대해 통일된 API로 알림을 보내는 구조입니다.
Mail과 Notification의 차이
| 비교 | Mail | Notification |
|---|
| 주된 용도 | 리치한 HTML 메일 | 짧은 정보 알림 |
| 배송 채널 | 메일만 | 메일·DB·Slack·SMS 등 여러 개 |
| 템플릿 | 완전히 자유 | 심플한 메시지 형식 |
청구서 결제 완료 알림처럼 여러 채널에 같은 알림을 보내고 싶다면 Notification이 적합합니다.
Notification 클래스 생성
make:notification Artisan 명령으로 클래스를 생성합니다.
php artisan make:notification InvoicePaid
생성된 클래스는 app/Notifications/ 디렉터리에 배치됩니다. 클래스에는 via() 메서드와 각 채널용 메시지 생성 메서드가 포함됩니다.
알림 전송 방법
Notifiable 트레이트 사용하기
App\Models\User에는 기본적으로 Notifiable 트레이트가 포함되어 있습니다. notify() 메서드로 알림을 보냅니다.
use App\Notifications\InvoicePaid;
$user->notify(new InvoicePaid($invoice));
Notifiable 트레이트는 User 모델뿐만 아니라 임의의 모델에 추가할 수 있습니다.
Notification 파사드 사용하기
여러 사용자에게 동시에 전송하려면 Notification 파사드를 사용합니다.
use Illuminate\Support\Facades\Notification;
Notification::send($users, new InvoicePaid($invoice));
즉시 전송(큐를 건너뜀)하려면 sendNow()를 사용합니다.
Notification::sendNow($developers, new DeploymentCompleted($deployment));
배송 채널 지정
via() 메서드에서 사용할 채널을 배열로 반환합니다.
public function via(object $notifiable): array
{
return ['mail', 'database'];
}
사용자의 설정에 따라 채널을 전환할 수도 있습니다.
public function via(object $notifiable): array
{
return $notifiable->prefers_sms ? ['vonage'] : ['mail', 'database'];
}
이용 가능한 주요 채널은 다음과 같습니다.
| 채널 | 키 | 설명 |
|---|
| 메일 | mail | 메일로 알림을 보냄 |
| 데이터베이스 | database | DB에 저장하고 UI 상에 표시 |
| 브로드캐스트 | broadcast | 실시간 알림(WebSocket) |
| SMS | vonage | Vonage(구 Nexmo) 경유로 SMS 전송 |
| Slack | slack | Slack 채널에 게시 |
메일 채널로 알림 보내기
toMail() 메서드에서 MailMessage 인스턴스를 반환합니다.
use Illuminate\Notifications\Messages\MailMessage;
public function toMail(object $notifiable): MailMessage
{
$url = url('/invoice/'.$this->invoice->id);
return (new MailMessage)
->greeting('안녕하세요!')
->line('청구서 결제를 확인했습니다.')
->action('청구서 확인하기', $url)
->line('이용해 주셔서 감사합니다.');
}
MailMessage의 주요 메서드는 다음과 같습니다.
| 메서드 | 설명 |
|---|
greeting() | 서두의 인사말 |
line() | 본문 한 줄 |
action() | 버튼 링크 |
subject() | 제목 |
from() | 발신자 주소 |
mailer() | 사용할 메일러 |
에러를 알리는 경우 error() 메서드를 추가하면 버튼이 빨간색으로 표시됩니다.
return (new MailMessage)
->error()
->subject('결제에 실패했습니다')
->line('청구서 결제 처리에 실패했습니다.');
마크다운 알림 메일
마크다운 형식의 리치한 메일도 사용할 수 있습니다. --markdown 옵션으로 클래스를 생성합니다.
php artisan make:notification InvoicePaid --markdown=mail.invoice.paid
toMail() 대신 마크다운 메서드를 사용합니다.
use Illuminate\Notifications\Messages\MailMessage;
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->markdown('mail.invoice.paid', [
'url' => url('/invoice/'.$this->invoice->id),
'invoice' => $this->invoice,
]);
}
데이터베이스 채널로 알림 보내기
데이터베이스 채널을 사용하면 알림을 DB에 저장하고 앱의 UI 상에 표시할 수 있습니다.
테이블 준비
먼저 notifications 테이블을 생성합니다.
php artisan make:notifications-table
php artisan migrate
toArray 메서드 정의
toArray() 메서드에서 저장할 데이터를 배열로 반환합니다.
public function toArray(object $notifiable): array
{
return [
'invoice_id' => $this->invoice->id,
'amount' => $this->invoice->amount,
'message' => '청구서 결제를 확인했습니다.',
];
}
이 데이터는 notifications 테이블의 data 컬럼에 JSON 형식으로 저장됩니다.
알림 조회
Notifiable 트레이트가 제공하는 notifications 릴레이션으로 알림을 조회할 수 있습니다.
$user = App\Models\User::find(1);
foreach ($user->notifications as $notification) {
echo $notification->type;
echo $notification->data['message'];
}
읽지 않은 알림만 조회하려면 unreadNotifications를 사용합니다.
foreach ($user->unreadNotifications as $notification) {
echo $notification->data['message'];
}
읽음 처리
markAsRead()로 알림을 읽음 상태로 만듭니다.
// 개별적으로 읽음 처리
foreach ($user->unreadNotifications as $notification) {
$notification->markAsRead();
}
// 일괄 읽음 처리
$user->unreadNotifications->markAsRead();
// 쿼리로 일괄 갱신
$user->unreadNotifications()->update(['read_at' => now()]);
알림 큐 처리
알림 전송에 시간이 걸리는 경우 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를 구현하면 notify()를 호출하는 것만으로 자동으로 큐에 들어갑니다.
$user->notify(new InvoicePaid($invoice));
지연 전송도 가능합니다.
$user->notify(
(new InvoicePaid($invoice))->delay(now()->plus(minutes: 10))
);
여러 채널로의 동시 전송
via() 메서드에서 여러 채널을 반환하고 각각의 메서드를 정의하는 것만으로, 같은 알림을 여러 채널에 동시에 전송할 수 있습니다.
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class InvoicePaid extends Notification implements ShouldQueue
{
use Queueable;
public function __construct(
private readonly Invoice $invoice,
) {}
public function via(object $notifiable): array
{
// 메일과 데이터베이스 양쪽에 전송
return ['mail', 'database'];
}
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->subject('청구서 결제를 확인했습니다')
->line('청구서 #'.$this->invoice->id.'의 결제를 확인했습니다.')
->action('청구서 확인하기', url('/invoice/'.$this->invoice->id));
}
public function toArray(object $notifiable): array
{
return [
'invoice_id' => $this->invoice->id,
'amount' => $this->invoice->amount,
];
}
}
온디맨드 알림
앱에 계정이 없는 사용자에게도 알림을 보내고 싶다면 Notification::route()를 사용합니다.
use Illuminate\Support\Facades\Notification;
Notification::route('mail', '[email protected]')
->route('vonage', '5555551212')
->notify(new InvoicePaid($invoice));
| 하고 싶은 일 | 방법 |
|---|
| Notification 생성 | php artisan make:notification ClassName |
| 사용자에게 알림 | $user->notify(new MyNotification()) |
| 여러 사용자에게 알림 | Notification::send($users, new MyNotification()) |
| 메일로 전송 | via()에서 mail 반환 후 toMail() 정의 |
| DB에 저장 | via()에서 database 반환 후 toArray() 정의 |
| 큐로 비동기 전송 | ShouldQueue 구현 |
| 여러 채널로 전송 | via()에서 여러 키를 반환 |