알림

번역일: 2026년 6월 27일

알림

소개

Laravel은 이메일 전송 외에도 이메일, SMS, Slack 등 다양한 채널을 통해 알림을 보낼 수 있는 기능을 제공합니다. 알림은 데이터베이스에 저장하여 웹 인터페이스에서 표시할 수도 있습니다.

일반적으로 알림은 애플리케이션 내에서 발생한 어떤 사실을 사용자에게 간결하게 전달하는 메시지입니다. 예를 들어 결제 앱을 개발한다면 "결제가 완료되었습니다"라는 알림을 이메일과 SMS 채널을 통해 동시에 발송할 수 있습니다.

알림

목차

소개

Laravel은 이메일 전송 외에도 이메일, SMS(Vonage 이용), Slack 등 다양한 채널을 통해 알림을 전송할 수 있도록 지원합니다. 또한 커뮤니티가 만든 다양한 알림 채널을 활용하면 수십 가지 방식으로 알림을 보낼 수도 있습니다. 알림 내역은 데이터베이스에 저장하여 웹 인터페이스에서 표시하는 것도 가능합니다.

알림은 보통 애플리케이션에서 발생한 특정 사건을 사용자에게 간결하게 전달하는 짧은 정보성 메시지입니다. 예를 들어, 청구서 관련 애플리케이션을 개발한다면 "청구서 결제 완료" 알림을 이메일과 SMS 채널로 사용자에게 전송할 수 있습니다.

알림 생성하기

Laravel에서 알림은 각각 하나의 클래스로 표현되며, 기본적으로 app/Notifications 디렉터리에 저장됩니다. 이 디렉터리가 없더라도 걱정하지 않아도 됩니다. make:notification Artisan 명령을 실행하면 자동으로 생성됩니다.

php artisan make:notification InvoicePaid

명령을 실행하면 app/Notifications 디렉터리에 새로운 알림 클래스가 생성됩니다. 생성된 클래스에는 via 메서드와 toMail, toDatabase 등 각 채널에 맞는 메시지 작성 메서드가 포함되어 있습니다.

알림 전송하기

Notifiable 트레이트 사용하기

알림을 전송하는 방법은 두 가지입니다. 첫 번째는 Notifiable 트레이트의 notify 메서드를 사용하는 방법이고, 두 번째는 Notification 파사드를 사용하는 방법입니다.

Notifiable 트레이트는 기본적으로 App\Models\User 모델에 포함되어 있습니다.

<?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 파사드를 이용하는 것입니다. 여러 사용자처럼 여러 notifiable 엔티티에게 한 번에 알림을 보낼 때 특히 유용합니다.

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, Kakao 알림 채널 등 다른 채널을 사용하고 싶다면 Laravel 알림 채널 커뮤니티 사이트를 참고하세요.

via 메서드는 $notifiable 인스턴스를 받으므로, 사용자 특성에 따라 채널을 동적으로 결정할 수도 있습니다.

/** * 알림을 전달할 채널을 반환합니다. * * @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));

알림 전송을 지연시키려면 알림 인스턴스에 delay 메서드를 체이닝하면 됩니다.

$delay = now()->addMinutes(10); $user->notify((new InvoicePaid($invoice))->delay($delay));

채널별로 지연 시간을 다르게 설정하려면 배열로 전달하세요.

$user->notify((new InvoicePaid($invoice))->delay([ 'mail' => now()->addMinutes(5), 'sms' => now()->addMinutes(10), ]));

알림을 큐에 넣을 때 각 수신자와 채널 조합마다 별도의 큐 Job이 생성됩니다. 예를 들어 수신자 6명에 채널이 2개라면 12개의 Job이 큐에 추가됩니다.

알림 큐 커스터마이징

사용할 큐 이름이나 커넥션을 변경하려면 알림 클래스에 $connection, $queue, $afterCommit 속성을 설정하거나, viaQueues 메서드를 정의하면 됩니다.

/** * 채널별로 사용할 큐 이름을 지정합니다. * * @return array<string, string> */ public function viaQueues(): array { return [ 'mail' => 'mail-queue', 'slack' => 'slack-queue', ]; }

큐 처리된 알림과 데이터베이스 트랜잭션

큐 처리된 알림이 데이터베이스 트랜잭션 내에서 디스패치되면, 트랜잭션이 커밋되기 전에 큐 워커가 Job을 처리할 수 있습니다. 이 경우 트랜잭션 중에 변경한 모델이나 데이터베이스 레코드가 아직 반영되지 않았을 수 있습니다. 또한 트랜잭션 안에서 생성한 모델이나 레코드가 데이터베이스에 존재하지 않을 수도 있습니다.

이를 방지하려면 $afterCommit 속성을 true로 설정하거나, 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; public function __construct() { $this->afterCommit(); } }

NOTE

이 문제를 우회하는 방법에 대한 자세한 내용은 큐 Job과 데이터베이스 트랜잭션 문서를 참고하세요.

알림 큐 처리 여부를 조건부로 결정하기

런타임 조건에 따라 알림을 큐에 넣을지 여부를 결정해야 할 때가 있습니다. 이런 경우 알림 클래스에 shouldSend 메서드를 추가하면 됩니다. 이 메서드가 false를 반환하면 알림이 전송되지 않습니다.

/** * 알림을 전송해야 하는지 결정합니다. */ public function shouldSend(object $notifiable, string $channel): bool { return $this->invoice->isPaid(); }

온디맨드 알림

애플리케이션의 사용자로 등록되지 않은 대상에게 알림을 보내야 할 때가 있습니다. 이럴 때는 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));

메일 채널에 수신자 이름도 함께 지정하려면 이메일 주소를 키로, 이름을 값으로 하는 배열을 전달하세요.

Notification::route('mail', [ 'barrett@example.com' => '바렛 블레어', ])->notify(new InvoicePaid($invoice));

routes 메서드를 사용하면 여러 채널의 임시 라우팅 정보를 한 번에 지정할 수 있습니다.

Notification::routes([ 'mail' => ['barrett@example.com' => '바렛 블레어'], 'vonage' => '5555555555', ])->notify(new InvoicePaid($invoice));

메일 알림

메일 메시지 포맷 지정하기

알림을 이메일로 보내려면 알림 클래스에 toMail 메서드를 정의해야 합니다. 이 메서드는 $notifiable 객체를 받아 Illuminate\Notifications\Messages\MailMessage 인스턴스를 반환해야 합니다.

MailMessage 클래스는 트랜잭션 이메일을 쉽게 구성할 수 있는 간단한 메서드들을 제공합니다. 텍스트 라인과 액션(버튼 링크)을 조합해 메시지를 만들 수 있습니다. 아래 예시를 참고하세요.

/** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): MailMessage { $url = url('/invoice/'.$this->invoice->id); return (new MailMessage) ->greeting('안녕하세요!') ->line('청구서가 결제되었습니다. 감사합니다.') ->lineIf($this->amount > 0, "결제 금액: {$this->amount}원") ->action('청구서 확인', $url) ->line('이용해 주셔서 감사합니다.'); }

NOTE

toMail 메서드에서 $this->invoice->id 등의 데이터를 사용하고 있습니다. 알림 메시지를 생성하는 데 필요한 데이터는 알림 클래스의 생성자를 통해 전달하는 것이 일반적입니다.

이 예시에서는 인사말, 텍스트 라인, 액션 링크, 그리고 마지막 텍스트 라인을 순서대로 등록합니다. MailMessage 객체가 제공하는 이 메서드들을 활용하면 간단한 트랜잭션 이메일을 빠르게 포맷할 수 있습니다. 메일 채널은 이 메시지 구성 요소들을 보기 좋고 반응형인 HTML 이메일 템플릿으로 변환합니다. 아래는 mail 채널이 생성한 이메일 예시입니다.

메일 알림 예시

NOTE

메일 알림을 전송할 때는 config/app.php 설정 파일의 name 값을 반드시 지정하세요. 이 값이 메일 알림 메시지의 헤더와 푸터에 사용됩니다.

기타 메일 알림 포맷 옵션

알림 클래스에서 텍스트 "라인"을 직접 정의하는 대신, view 메서드를 사용해 이메일을 렌더링할 커스텀 템플릿을 지정할 수 있습니다.

/** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): MailMessage { return (new MailMessage)->view( 'mail.invoice.paid', ['invoice' => $this->invoice] ); }

HTML 뷰와 텍스트 뷰를 모두 지정하려면 배열로 두 번째 원소에 텍스트 뷰 이름을 전달하세요.

/** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): MailMessage { return (new MailMessage)->view( ['mail.invoice.paid', 'mail.invoice.paid-text'], ['invoice' => $this->invoice] ); }

발신자 지정하기

기본적으로 이메일 발신자(from) 주소는 config/mail.php 설정 파일에서 가져옵니다. 특정 알림에서 발신자를 변경하려면 from 메서드를 사용하세요.

/** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): MailMessage { return (new MailMessage) ->from('no-reply@myapp.kr', '내 애플리케이션') ->line('...'); }

수신자 지정하기

mail 채널로 알림을 보낼 때, Laravel은 notifiable 엔티티의 email 속성을 자동으로 수신자 주소로 사용합니다. 수신 주소를 직접 지정하려면 notifiable 엔티티 클래스에 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; /** * 메일 채널에서 사용할 이메일 주소를 반환합니다. */ public function routeNotificationForMail(Notification $notification): array|string { // 이메일 주소만 반환하는 경우 return $this->email_address; // 이름과 이메일 주소를 함께 반환하는 경우 return [$this->email_address => $this->name]; } }

제목 지정하기

기본적으로 이메일 제목은 알림 클래스 이름을 "Title Case" 형식으로 변환한 값입니다. 예를 들어 InvoicePaid 클래스라면 제목은 "Invoice Paid"가 됩니다. 제목을 직접 지정하려면 subject 메서드를 사용하세요.

/** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): MailMessage { return (new MailMessage) ->subject('청구서 결제 완료') ->line('...'); }

메일러 지정하기

기본적으로 이메일 알림은 config/mail.php 설정 파일의 기본 메일러를 사용합니다. 특정 알림에서 다른 메일러를 사용하려면 mailer 메서드를 사용하세요.

/** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): MailMessage { return (new MailMessage) ->mailer('postmark') ->line('...'); }

템플릿 지정하기

메일 알림에 사용하는 HTML 및 텍스트 템플릿을 커스터마이징하려면 알림 패키지의 리소스를 퍼블리시(publish)하면 됩니다.

php artisan vendor:publish --tag=laravel-notifications

이 명령을 실행하면 resources/views/vendor/notifications 디렉터리에 템플릿 파일이 생성됩니다. 이 파일들을 수정하면 알림 이메일의 HTML과 텍스트 형식을 자유롭게 커스터마이징할 수 있습니다.

첨부 파일

이메일 알림에 파일을 첨부하려면 attach 메서드를 사용하세요. 첫 번째 인자로 파일의 절대 경로를 전달합니다.

/** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): MailMessage { return (new MailMessage) ->greeting('안녕하세요!') ->attach('/path/to/file'); }

NOTE

알림 메일 메시지에서 제공하는 attach 메서드는 attachable 객체도 지원합니다. 자세한 내용은 해당 문서를 참고하세요.

파일을 첨부할 때 표시 이름이나 MIME 타입을 지정하려면 두 번째 인자로 배열을 전달하세요.

/** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): MailMessage { return (new MailMessage) ->greeting('안녕하세요!') ->attach('/path/to/file', [ 'as' => '청구서.pdf', 'mime' => 'application/pdf', ]); }

Mailable 객체에서처럼 디스크에서 직접 파일을 첨부하려면 attachFromStorage 메서드를 사용하세요.

/** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): MailMessage { return (new MailMessage) ->greeting('안녕하세요!') ->attachFromStorage('/path/to/file'); }

특정 디스크를 명시하려면 attachFromStorageDisk 메서드를 사용하세요.

/** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): MailMessage { return (new MailMessage) ->greeting('안녕하세요!') ->attachFromStorageDisk('s3', '/path/to/file'); }

원시 바이트 데이터를 첨부 파일로 추가하려면 attachData 메서드를 사용하세요. 파일 이름을 두 번째 인자로 전달합니다.

/** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): MailMessage { return (new MailMessage) ->greeting('안녕하세요!') ->attachData($this->pdf, '청구서.pdf', [ 'mime' => 'application/pdf', ]); }

태그 및 메타데이터 추가하기

Mailgun, Postmark 같은 이메일 서비스는 메시지 태그와 메타데이터를 지원합니다. 태그와 메타데이터를 이용해 애플리케이션에서 발송한 이메일을 그룹화하고 추적할 수 있습니다. tagmetadata 메서드를 사용하여 태그와 메타데이터를 추가하세요.

/** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): MailMessage { return (new MailMessage) ->greeting('안녕하세요!') ->tag('invoice-paid') ->metadata('invoice_id', $this->invoice->id); }

Mailgun을 사용하는 경우 태그메타데이터 관련 문서를 참고하세요. Postmark를 사용하는 경우에도 태그메타데이터 관련 문서를 확인하세요.

Amazon SES를 사용하는 경우, metadata 메서드를 통해 메시지에 SES 태그를 추가할 수 있습니다.

Symfony 메시지 커스터마이징하기

MailMessagewithSymfonyMessage 메서드를 사용하면 메시지를 전송하기 전에 Symfony Message 인스턴스에 직접 접근하여 추가 커스터마이징을 할 수 있습니다.

use Symfony\Component\Mime\Email; /** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): MailMessage { return (new MailMessage) ->withSymfonyMessage(function (Email $message) { $message->getHeaders()->addTextHeader( 'Custom-Header', '헤더 값' ); }); }

Mailable 사용하기

필요하다면 알림의 toMail 메서드에서 완전한 Mailable 객체를 반환할 수 있습니다. MailMessage 대신 Mailable을 반환할 때는 Mailable 객체의 to 메서드로 수신자를 직접 지정해야 합니다.

use App\Mail\InvoicePaid as InvoicePaidMailable; use Illuminate\Mail\Mailable; /** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): Mailable { return (new InvoicePaidMailable($this->invoice)) ->to($notifiable->email); }

메일 알림 미리보기

메일 알림 템플릿을 디자인할 때, 렌더링된 메일 메시지를 브라우저에서 바로 확인하면 매우 편리합니다. 이를 위해 Laravel은 라우트의 클로저나 컨트롤러에서 메일 알림을 직접 반환하는 방법을 제공합니다. 메일 알림이 반환되면 브라우저에서 렌더링되어 실제 이메일 전송 없이도 디자인을 빠르게 검토할 수 있습니다.

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 메일 알림을 사용하면 Laravel이 제공하는 미리 만들어진 메일 알림 템플릿을 활용하면서 더 길고 복잡한 메시지도 자유롭게 작성할 수 있습니다. Markdown으로 작성된 메시지는 보기 좋은 반응형 HTML 이메일과 텍스트 버전으로 자동 변환됩니다.

메시지 생성하기

--markdown 옵션으로 알림을 생성하면 해당 Markdown 템플릿 파일도 함께 생성됩니다.

php artisan make:notification InvoicePaid --markdown=mail.invoice.paid

다른 메일 알림과 마찬가지로, Markdown 템플릿을 사용하는 알림 클래스에도 toMail 메서드를 정의해야 합니다. 단, lineaction 메서드 대신 markdown 메서드로 사용할 Markdown 템플릿 이름을 지정합니다. 두 번째 인자로 뷰에서 사용할 데이터를 배열로 전달할 수 있습니다.

/** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): MailMessage { $url = url('/invoice/'.$this->invoice->id); return (new MailMessage) ->subject('청구서 결제 완료') ->markdown('mail.invoice.paid', ['url' => $url]); }

메시지 작성하기

Markdown 메일 알림은 Blade 컴포넌트와 Markdown 문법을 조합하여 사용합니다. Laravel이 제공하는 이메일 컴포넌트들을 활용해 손쉽게 메일을 구성할 수 있습니다.

<x-mail::message> <h1 id="markdown-mail-notifications">청구서 결제 완료</h1> 청구서가 결제되었습니다. <x-mail::button :url="$url"> 청구서 확인 </x-mail::button> 감사합니다,<br> {{ config('app.name') }} </x-mail::message>

Button 컴포넌트

버튼 컴포넌트는 가운데 정렬된 버튼 링크를 렌더링합니다. url과 선택적으로 color(primary, green, red)를 인자로 받습니다.

<x-mail::button :url="$url" color="green"> 청구서 확인 </x-mail::button>

Panel 컴포넌트

패널 컴포넌트는 지정한 텍스트 블록을 나머지 내용과 구분되는 배경색 패널 안에 렌더링합니다. 특정 내용을 강조할 때 유용합니다.

<x-mail::panel> 여기에 패널 내용을 작성하세요. </x-mail::panel>

Table 컴포넌트

테이블 컴포넌트는 Markdown 테이블을 HTML 테이블로 변환합니다. 컬럼 정렬은 일반적인 Markdown 테이블 정렬 문법을 따릅니다.

<x-mail::table> | 상품명 | 가격 | 수량 | | --------- | -----: | ----: | | 라라벨 | 19,000 | 100 | | 서버 비용 | 99,000 | 200 | </x-mail::table>

컴포넌트 커스터마이징하기

Markdown 알림 컴포넌트들을 직접 수정하려면 먼저 퍼블리시 명령으로 파일을 내보내세요.

php artisan vendor:publish --tag=laravel-mail

이 명령을 실행하면 resources/views/vendor/mail 디렉터리에 Markdown 메일 컴포넌트가 생성됩니다. mail 디렉터리에는 htmltext 디렉터리가 있으며, 각각 컴포넌트의 HTML 버전과 텍스트 버전이 들어 있습니다. 이 파일들을 원하는 대로 수정하면 됩니다.

CSS 커스터마이징

컴포넌트를 내보내고 나면 resources/views/vendor/mail/html/themes/default.css 파일에서 기본 CSS를 수정할 수 있습니다. 변경된 스타일은 Markdown 알림의 HTML 이메일에 자동으로 인라인 CSS로 적용됩니다.

Laravel의 Markdown 컴포넌트용 새 테마를 만들려면 html/themes 디렉터리에 CSS 파일을 추가하고 config/mail.php 설정의 theme 옵션을 해당 파일 이름으로 변경하면 됩니다. 특정 알림에만 다른 테마를 적용하려면 theme 메서드를 사용하세요.

/** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): MailMessage { return (new MailMessage) ->theme('invoice') ->subject('청구서 결제 완료') ->markdown('mail.invoice.paid', ['url' => $url]); }

데이터베이스 알림

사전 준비

database 알림 채널은 알림 정보를 데이터베이스 테이블에 저장합니다. 이 테이블에는 알림 타입과 알림을 설명하는 JSON 데이터 구조 같은 정보가 담겨 있습니다.

테이블에 저장된 알림을 조회하여 애플리케이션의 UI에 표시할 수 있습니다. 하지만 먼저 알림을 저장할 데이터베이스 테이블을 생성해야 합니다. make:notifications-table 명령을 사용해 적절한 테이블 스키마의 마이그레이션 파일을 생성하세요.

php artisan make:notifications-tablephp artisan migrate

NOTE

notifiable 모델에서 UUID 또는 ULID 기본 키를 사용하는 경우, 알림 테이블 마이그레이션에서 morphs 메서드 대신 uuidMorphs 또는 ulidMorphs를 사용해야 합니다.

데이터베이스 알림 포맷 지정하기

알림을 데이터베이스 테이블에 저장하려면 알림 클래스에 toDatabase 또는 toArray 메서드를 정의해야 합니다. 이 메서드는 $notifiable 객체를 받아 일반 PHP 배열을 반환합니다. 반환된 배열은 JSON으로 직렬화되어 notifications 테이블의 data 컬럼에 저장됩니다. 아래 예시를 참고하세요.

/** * 알림의 배열 표현을 반환합니다. * * @return array<string, mixed> */ public function toArray(object $notifiable): array { return [ 'invoice_id' => $this->invoice->id, 'amount' => $this->invoice->amount, ]; }

알림이 애플리케이션의 notifications 테이블에 저장될 때, type 컬럼에는 알림 클래스의 전체 이름이 저장됩니다. 이 값을 커스터마이징하려면 알림 클래스에 databaseType 메서드를 정의하면 됩니다.

/** * 데이터베이스에 저장될 알림 타입을 반환합니다. */ public function databaseType(object $notifiable): string { return 'invoice-paid'; }

`toDatabase`와 `toArray`의 차이점

toArray 메서드는 broadcast 채널에서도 사용되어 JavaScript 프론트엔드로 브로드캐스트할 데이터를 결정합니다. databasebroadcast 채널에 서로 다른 배열 표현이 필요하다면 toArray 대신 toDatabase 메서드를 별도로 정의하세요.

알림 접근하기

알림이 데이터베이스에 저장되면 notifiable 엔티티에서 손쉽게 접근할 수 있어야 합니다. Notifiable 트레이트가 포함된 App\Models\User 모델에는 notifications Eloquent 관계 메서드가 기본으로 제공됩니다. 이 관계를 통해 알림을 조회할 수 있으며, 다른 Eloquent 관계와 동일하게 사용할 수 있습니다. 기본적으로 알림은 created_at 타임스탬프 기준으로 최신 순으로 정렬됩니다.

$user = App\Models\User::find(1); foreach ($user->notifications as $notification) { echo $notification->type; }

읽지 않은(unread) 알림만 가져오려면 unreadNotifications 관계를 사용하세요.

$user = App\Models\User::find(1); foreach ($user->unreadNotifications as $notification) { echo $notification->type; }

NOTE

JavaScript 프론트엔드에서 알림을 접근하려면 현재 사용자의 알림을 반환하는 알림 컨트롤러를 만들어야 합니다.

알림 읽음 처리하기

사용자가 알림을 확인하면 읽음 상태로 변경해야 합니다. Notifiable 트레이트는 markAsRead 메서드를 제공하며, 이 메서드는 알림 레코드의 read_at 컬럼을 업데이트합니다.

$user = App\Models\User::find(1); foreach ($user->unreadNotifications as $notification) { $notification->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의 이벤트 브로드캐스팅 서비스를 이용해 알림을 브로드캐스트합니다. 알림 클래스에 toBroadcast 메서드를 정의하면 됩니다. 이 메서드는 $notifiable 객체를 받아 BroadcastMessage 인스턴스를 반환해야 합니다. toBroadcast 메서드가 없으면 toArray 메서드의 반환값이 브로드캐스트 데이터로 사용됩니다. 반환된 데이터는 JSON으로 직렬화되어 JavaScript 프론트엔드로 전달됩니다. 아래 toBroadcast 예시를 확인하세요.

use Illuminate\Notifications\Messages\BroadcastMessage; /** * 알림의 브로드캐스트 표현을 반환합니다. */ public function toBroadcast(object $notifiable): BroadcastMessage { return new BroadcastMessage([ 'invoice_id' => $this->invoice->id, 'amount' => $this->invoice->amount, ]); }

브로드캐스트 큐 설정

모든 브로드캐스트 알림은 큐에서 처리됩니다. 브로드캐스트에 사용할 큐 커넥션이나 이름을 지정하려면 BroadcastMessageonConnectiononQueue 메서드를 사용하세요.

return (new BroadcastMessage($data)) ->onConnection('sqs') ->onQueue('broadcasts');

알림 타입 지정하기

브로드캐스트 데이터에는 알림의 전체 클래스 이름을 담은 type 필드가 자동으로 포함됩니다. 이 값을 커스터마이징하려면 알림 클래스에 broadcastType 메서드를 정의하세요.

/** * 브로드캐스트될 알림 타입을 반환합니다. */ 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); });

알림 채널 커스터마이징

브로드캐스트 알림이 전달되는 채널을 커스터마이징하려면 notifiable 엔티티 클래스에 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; /** * 브로드캐스트 알림을 수신할 채널을 반환합니다. */ public function receivesBroadcastNotificationsOn(): string { return 'users.'.$this->id; } }

SMS 알림

사전 준비

Laravel의 SMS 알림 전송은 Vonage(구 Nexmo)를 통해 이루어집니다. Vonage로 알림을 보내려면 먼저 laravel/vonage-notification-channelguzzlehttp/guzzle 패키지를 설치하세요.

composer require laravel/vonage-notification-channel guzzlehttp/guzzle

패키지에는 설정 파일이 포함되어 있습니다. 하지만 이 파일을 직접 퍼블리시하지 않아도 됩니다. 환경 변수 VONAGE_KEYVONAGE_SECRET으로 Vonage의 공개 키와 비밀 키를 설정하면 됩니다.

키 설정 후 VONAGE_SMS_FROM 환경 변수로 SMS를 발신할 전화번호를 지정하세요. 이 전화번호는 Vonage 콘솔에서 생성할 수 있습니다.

VONAGE_SMS_FROM=15556666666

SMS 알림 포맷 지정하기

SMS로 알림을 보내려면 알림 클래스에 toVonage 메서드를 정의하세요. 이 메서드는 $notifiable 객체를 받아 Illuminate\Notifications\Messages\VonageMessage 인스턴스를 반환해야 합니다.

use Illuminate\Notifications\Messages\VonageMessage; /** * 알림의 Vonage(SMS) 표현을 반환합니다. */ public function toVonage(object $notifiable): VonageMessage { return (new VonageMessage) ->content('SMS 알림 내용입니다.'); }

유니코드 콘텐츠

SMS 메시지에 유니코드 문자(한국어 포함)가 포함되어 있다면 VonageMessage 인스턴스를 생성할 때 unicode 메서드를 호출하세요.

use Illuminate\Notifications\Messages\VonageMessage; /** * 알림의 Vonage(SMS) 표현을 반환합니다. */ public function toVonage(object $notifiable): VonageMessage { return (new VonageMessage) ->content('한국어 알림 메시지입니다.') ->unicode(); }

발신 번호 지정하기

VONAGE_SMS_FROM에 지정한 기본 번호 대신 다른 번호로 SMS를 보내려면 VonageMessage에서 from 메서드를 사용하세요.

use Illuminate\Notifications\Messages\VonageMessage; /** * 알림의 Vonage(SMS) 표현을 반환합니다. */ public function toVonage(object $notifiable): VonageMessage { return (new VonageMessage) ->content('SMS 알림 내용입니다.') ->from('15554444444'); }

클라이언트 참조 추가하기

사용자, 팀, 기타 엔티티별로 비용을 추적하려면 알림에 클라이언트 참조를 추가하면 됩니다. Vonage에서는 이 참조로 사용량 보고서를 필터링하여 확인할 수 있습니다. 클라이언트 참조는 최대 40자의 문자열입니다.

use Illuminate\Notifications\Messages\VonageMessage; /** * 알림의 Vonage(SMS) 표현을 반환합니다. */ public function toVonage(object $notifiable): VonageMessage { return (new VonageMessage) ->clientReference((string) $notifiable->id) ->content('SMS 알림 내용입니다.'); }

SMS 알림 라우팅하기

Vonage 알림을 올바른 전화번호로 전달하려면 notifiable 엔티티 클래스에 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; /** * Vonage 채널에서 사용할 전화번호를 반환합니다. */ public function routeNotificationForVonage(Notification $notification): string { return $this->phone_number; } }

Slack 알림

사전 준비

Slack 알림을 보내려면 Composer로 Slack 알림 채널 패키지를 설치하세요.

composer require laravel/slack-notification-channel

추가로 Slack 워크스페이스에 Slack App을 생성해야 합니다.

같은 Slack 워크스페이스 내의 채널에만 알림을 보내면 된다면 Slack App에 chat:write, chat:write.public, chat:write.customize 스코프를 부여하세요. 이 스코프는 Slack의 "OAuth & Permissions" App 관리 탭에서 추가할 수 있습니다.

다음으로, App의 "Bot User OAuth Token"을 복사하여 애플리케이션의 services.php 설정 파일에서 slack 설정 배열 내 bot_user_oauth_token에 입력하세요. 이 토큰은 Slack의 "OAuth & Permissions" 탭에서 찾을 수 있습니다.

// config/services.php 'slack' => [ 'notifications' => [ 'bot_user_oauth_token' => env('SLACK_BOT_USER_OAUTH_TOKEN'), 'channel' => env('SLACK_BOT_USER_DEFAULT_CHANNEL'), ], ],

App 배포

Slack 알림은 애플리케이션 서버가 Slack API와 통신합니다. 메시지 전송은 notify() 또는 Notification::send() 메서드를 통해 이루어지며, Slack 워크스페이스의 Webhook 설정이나 Bot 토큰 인증을 활용합니다.

Slack 알림 포맷 지정하기

알림을 Slack 메시지로 보내려면 알림 클래스에 toSlack 메서드를 정의하세요. 이 메서드는 $notifiable 객체를 받아 Illuminate\Notifications\Slack\SlackMessage 인스턴스를 반환해야 합니다. Slack의 Block Kit API를 이용해 다양한 형태의 메시지를 작성할 수 있습니다. 아래 예시는 [Slack의 Block Kit Builder](https://app.slack.com/block-kit-builder/T01KWS6K23Z#%7B%22blocks%22:%5B%7B%22type%22:%22header%22,%22text%22:%7B%22type%22:%22plain_text%22,%22text%22:%22Invoice%20Paid%22%7D%7D,%7B%22type%22:%22context%22,%22elements%22:%5B%7B%22type%22:%22plain_text%22,%22text%22:%22Customer%20%231234%22%7D%5D%7D,%7B%22type%22:%22section%22,%22text%22:%7B%22type%22:%22mrkdwn%22,%22text%22:%22An%20invoice%20has%20been%20paid.%22%7D,%22accessory%22

알림

알림 생성

Laravel에서 각 알림은 하나의 클래스로 표현되며, 일반적으로 app/Notifications 디렉터리에 저장됩니다. 이 디렉터리가 없더라도 걱정하지 않아도 됩니다. make:notification Artisan 명령어를 실행하면 자동으로 생성됩니다.

php artisan make:notification InvoicePaid

이 명령어를 실행하면 app/Notifications 디렉터리에 새로운 알림 클래스가 생성됩니다. 각 알림 클래스에는 via 메서드와, toMail 또는 toDatabase와 같이 알림을 특정 채널에 맞는 메시지로 변환하는 여러 메시지 빌딩 메서드가 포함됩니다.

알림

알림 전송하기

Notifiable 트레이트 사용하기

알림을 전송하는 방법은 두 가지입니다. Notifiable 트레이트의 notify 메서드를 사용하거나, Notification 파사드를 사용하는 방법입니다. Notifiable 트레이트는 기본적으로 App\Models\User 모델에 포함되어 있습니다.

<?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));

ShouldQueue 인터페이스를 구현한 알림이라도 즉시 전송해야 한다면 sendNow 메서드를 사용하세요. 큐를 거치지 않고 바로 발송됩니다.

Notification::sendNow($developers, new DeploymentCompleted($deployment));

전송 채널 지정하기

알림 클래스의 via 메서드에서 어떤 채널로 알림을 전송할지 결정합니다. 기본으로 제공되는 채널은 mail, database, broadcast, vonage, slack입니다.

NOTE

Telegram, Pusher 등 다른 채널을 사용하고 싶다면 커뮤니티에서 관리하는 Laravel Notification Channels 사이트를 확인해 보세요.

via 메서드는 알림을 받는 대상 인스턴스($notifiable)를 인자로 받습니다. 이를 활용해 수신자에 따라 채널을 동적으로 결정할 수 있습니다.

/** * 알림 전송 채널을 반환합니다. * * @return array<int, string> */ public function via(object $notifiable): array { return $notifiable->prefers_sms ? ['vonage'] : ['mail', 'database']; }

알림 큐 처리하기

WARNING

알림을 큐에 넣기 전에 큐 설정을 완료하고 큐 워커를 실행해야 합니다.

외부 API를 호출하는 채널(메일, SMS 등)은 알림 전송에 시간이 걸릴 수 있습니다. 응답 속도를 높이려면 알림 클래스에 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이 생성됩니다. 예를 들어 수신자가 3명이고 채널이 2개라면 총 6개의 Job이 큐에 추가됩니다.

알림 지연 전송

알림을 특정 시간 이후에 전송하고 싶다면 delay 메서드를 체이닝하세요.

$delay = now()->addMinutes(10); $user->notify((new InvoicePaid($invoice))->delay($delay));

채널별로 지연 시간을 다르게 설정할 수도 있습니다.

$user->notify((new InvoicePaid($invoice))->delay([ 'mail' => now()->addMinutes(5), 'sms' => now()->addMinutes(10), ]));

또는 알림 클래스 자체에 withDelay 메서드를 정의해 지연 설정을 클래스 안에 캡슐화할 수 있습니다.

/** * 알림의 채널별 지연 시간을 반환합니다. * * @return array<string, \Illuminate\Support\Carbon> */ public function withDelay(object $notifiable): array { return [ 'mail' => now()->addMinutes(5), 'sms' => now()->addMinutes(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; /** * 새 알림 인스턴스를 생성합니다. */ public function __construct() { $this->onConnection('redis'); } }

채널별로 서로 다른 큐 커넥션을 사용하려면 viaConnections 메서드를 정의하세요. 채널 이름과 큐 커넥션 이름을 쌍으로 반환합니다.

/** * 각 채널에서 사용할 큐 커넥션을 반환합니다. * * @return array<string, string> */ public function viaConnections(): array { return [ 'mail' => 'redis', 'database' => 'sync', ]; }

알림 채널별 큐 이름 지정하기

채널마다 사용할 큐 이름을 지정하려면 viaQueues 메서드를 정의하세요. 채널 이름과 큐 이름을 쌍으로 반환합니다.

/** * 각 채널에서 사용할 큐 이름을 반환합니다. * * @return array<string, string> */ public function viaQueues(): array { return [ 'mail' => 'mail-queue', 'slack' => 'slack-queue', ]; }

큐 알림 미들웨어

큐 알림도 큐 Job처럼 미들웨어를 정의할 수 있습니다. 알림 클래스에 middleware 메서드를 추가하면 됩니다. 이 메서드는 $notifiable$channel을 인자로 받으므로, 수신자나 채널에 따라 미들웨어를 다르게 적용할 수 있습니다.

use Illuminate\Queue\Middleware\RateLimited; /** * 알림 Job이 통과해야 할 미들웨어를 반환합니다. * * @return array<int, object> */ public function middleware(object $notifiable, string $channel) { return match ($channel) { 'email' => [new RateLimited('postmark')], 'slack' => [new RateLimited('slack')], default => [], }; }

큐 알림과 데이터베이스 트랜잭션

데이터베이스 트랜잭션 내에서 큐 알림을 발송하면, 트랜잭션이 커밋되기 전에 큐 워커가 알림을 처리할 수 있습니다. 이 경우 트랜잭션 내에서 변경하거나 생성한 데이터가 아직 데이터베이스에 반영되지 않은 상태일 수 있어, 알림 처리 중 예기치 않은 오류가 발생할 수 있습니다.

큐 커넥션의 after_commit 설정이 false인 경우, 특정 알림만 트랜잭션 커밋 후에 발송되도록 afterCommit 메서드를 사용할 수 있습니다.

use App\Notifications\InvoicePaid; $user->notify((new InvoicePaid($invoice))->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; /** * 새 알림 인스턴스를 생성합니다. */ public function __construct() { $this->afterCommit(); } }

NOTE

이 문제를 해결하는 더 자세한 방법은 큐 Job과 데이터베이스 트랜잭션 문서를 참고하세요.

큐 알림 전송 여부 최종 판단하기

큐 워커가 알림을 처리하는 시점에 전송 여부를 최종적으로 결정해야 하는 경우, 알림 클래스에 shouldSend 메서드를 정의할 수 있습니다. 이 메서드가 false를 반환하면 알림이 전송되지 않습니다.

/** * 알림을 전송해야 하는지 여부를 반환합니다. */ public function shouldSend(object $notifiable, string $channel): bool { return $this->invoice->isPaid(); }

즉석 알림 (On-Demand Notifications)

애플리케이션의 사용자로 등록되지 않은 대상에게 알림을 보내야 하는 경우가 있습니다. 예를 들어 비회원 주문자에게 이메일을 발송하거나, 특정 Slack 채널에 알림을 전송하는 경우입니다. 이럴 때는 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 클래스는 트랜잭션 이메일을 간편하게 구성할 수 있는 여러 메서드를 제공합니다. 텍스트 줄과 "행동 유도(Call to Action)" 버튼을 조합해 메시지를 만들 수 있습니다. 아래는 toMail 메서드의 예시입니다.

/** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): MailMessage { $url = url('/invoice/'.$this->invoice->id); return (new MailMessage) ->greeting('안녕하세요!') ->line('청구서가 결제되었습니다!') ->lineIf($this->amount > 0, "결제 금액: {$this->amount}원") ->action('청구서 확인', $url) ->line('서비스를 이용해 주셔서 감사합니다!'); }

NOTE

위 예시에서 $this->invoice->id를 사용하고 있습니다. 알림 메시지 생성에 필요한 데이터는 알림 클래스의 생성자를 통해 전달할 수 있습니다.

이 예시에서는 인사말, 텍스트 줄, 행동 유도 버튼, 그리고 마무리 텍스트를 순서대로 구성합니다. MailMessage가 제공하는 이 메서드들 덕분에 소규모 트랜잭션 이메일을 빠르고 쉽게 만들 수 있습니다. 메일 채널은 이 구성 요소들을 반응형 HTML 이메일 템플릿과 일반 텍스트 버전으로 자동 변환합니다. 결과물은 다음과 같습니다.

NOTE

메일 알림을 발송하기 전에 config/app.phpname 설정 값을 반드시 확인하세요. 이 값은 메일 알림의 헤더와 푸터에 사용됩니다.

오류 메시지

결제 실패처럼 오류 상황을 사용자에게 알려야 할 때는 메시지를 구성할 때 error 메서드를 호출하면 됩니다. error 메서드를 사용하면 행동 유도 버튼이 검은색 대신 빨간색으로 표시됩니다.

/** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): MailMessage { return (new MailMessage) ->error() ->subject('청구서 결제 실패') ->line('...'); }

커스텀 뷰 사용

알림 클래스 안에 텍스트 줄을 직접 정의하는 대신, view 메서드를 사용해 이메일 렌더링에 사용할 커스텀 템플릿을 지정할 수도 있습니다.

/** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): MailMessage { return (new MailMessage)->view( 'mail.invoice.paid', ['invoice' => $this->invoice] ); }

일반 텍스트 뷰를 함께 사용하려면, 뷰 이름을 배열의 두 번째 요소로 전달합니다.

/** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): MailMessage { return (new MailMessage)->view( ['mail.invoice.paid', 'mail.invoice.paid-text'], ['invoice' => $this->invoice] ); }

일반 텍스트 뷰만 사용하는 경우에는 text 메서드를 사용할 수 있습니다.

/** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): MailMessage { return (new MailMessage)->text( 'mail.invoice.paid-text', ['invoice' => $this->invoice] ); }

발신자 커스터마이징

기본적으로 발신자 이메일 주소는 config/mail.php 설정 파일에 정의된 값을 사용합니다. 특정 알림에서만 발신자를 바꾸고 싶다면 from 메서드를 사용하세요.

/** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): MailMessage { return (new MailMessage) ->from('noreply@example.com', '발신자 이름') ->line('...'); }

수신자 커스터마이징

mail 채널로 알림을 발송할 때, 알림 시스템은 notifiable 엔티티의 email 속성을 자동으로 찾아 사용합니다. 수신 이메일 주소를 직접 지정하고 싶다면 notifiable 엔티티에 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; /** * 메일 채널의 알림 수신 주소를 반환합니다. * * @return array<string, string>|string */ public function routeNotificationForMail(Notification $notification): array|string { // 이메일 주소만 반환... return $this->email_address; // 이메일 주소와 이름을 함께 반환... return [$this->email_address => $this->name]; } }

제목 커스터마이징

기본적으로 이메일 제목은 알림 클래스명을 "Title Case" 형식으로 변환한 값이 사용됩니다. 예를 들어 클래스명이 InvoicePaid라면 제목은 Invoice Paid가 됩니다. 제목을 직접 지정하려면 subject 메서드를 사용하세요.

/** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): MailMessage { return (new MailMessage) ->subject('청구서 결제 완료') ->line('...'); }

메일러 커스터마이징

기본적으로 config/mail.php에 정의된 기본 메일러가 사용됩니다. 특정 알림에서 다른 메일러를 사용하려면 mailer 메서드를 호출하면 됩니다.

/** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): MailMessage { return (new MailMessage) ->mailer('postmark') ->line('...'); }

템플릿 커스터마이징

메일 알림에 사용되는 HTML 및 일반 텍스트 템플릿을 수정하려면 아래 Artisan 명령으로 패키지 리소스를 퍼블리시하면 됩니다. 퍼블리시 후 템플릿은 resources/views/vendor/notifications 디렉터리에 위치합니다.

php artisan vendor:publish --tag=laravel-notifications

첨부 파일

이메일 알림에 파일을 첨부하려면 attach 메서드를 사용합니다. 첫 번째 인수로 파일의 절대 경로를 전달합니다.

/** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): MailMessage { return (new MailMessage) ->greeting('안녕하세요!') ->attach('/path/to/file'); }

NOTE

알림 메일 메시지의 attach 메서드는 첨부 가능한 객체(attachable objects)도 지원합니다. 자세한 내용은 첨부 객체 문서를 참고하세요.

파일을 첨부할 때 표시 이름이나 MIME 타입을 지정하려면 두 번째 인수로 배열을 전달하세요.

/** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): MailMessage { return (new MailMessage) ->greeting('안녕하세요!') ->attach('/path/to/file', [ 'as' => 'name.pdf', 'mime' => 'application/pdf', ]); }

Mailable 객체와 달리 알림의 MailMessage에서는 attachFromStorage를 직접 사용할 수 없습니다. 스토리지 디스크에 있는 파일을 첨부할 때는 attach에 절대 경로를 사용하거나, toMail 메서드에서 Mailable을 반환하는 방식을 사용하세요.

use App\Mail\InvoicePaid as InvoicePaidMailable; /** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): Mailable { return (new InvoicePaidMailable($this->invoice)) ->to($notifiable->email) ->attachFromStorage('/path/to/file'); }

여러 파일을 한 번에 첨부하려면 attachMany 메서드를 사용하세요.

/** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): MailMessage { return (new MailMessage) ->greeting('안녕하세요!') ->attachMany([ '/path/to/forge.svg', '/path/to/vapor.svg' => [ 'as' => 'Logo.svg', 'mime' => 'image/svg+xml', ], ]); }

원시 데이터 첨부

메모리에 있는 원시 바이트 데이터를 파일로 첨부하려면 attachData 메서드를 사용합니다. 첨부 파일에 사용할 파일명을 함께 지정해야 합니다.

/** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): MailMessage { return (new MailMessage) ->greeting('안녕하세요!') ->attachData($this->pdf, 'name.pdf', [ 'mime' => 'application/pdf', ]); }

태그 및 메타데이터 추가

Mailgun, Postmark 같은 외부 이메일 서비스는 메시지 "태그"와 "메타데이터"를 지원합니다. 이를 활용하면 발송된 이메일을 그룹화하거나 추적할 수 있습니다. tagmetadata 메서드로 이 값들을 추가할 수 있습니다.

/** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): MailMessage { return (new MailMessage) ->greeting('댓글에 추천이 달렸습니다!') ->tag('upvote') ->metadata('comment_id', $this->comment->id); }

Symfony 메시지 커스터마이징

MailMessagewithSymfonyMessage 메서드를 사용하면 메시지 발송 직전에 Symfony Message 인스턴스를 직접 조작할 수 있습니다. 커스텀 헤더 추가 등 세밀한 제어가 필요할 때 유용합니다.

use Symfony\Component\Mime\Email; /** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): MailMessage { return (new MailMessage) ->withSymfonyMessage(function (Email $message) { $message->getHeaders()->addTextHeader( 'Custom-Header', 'Header Value' ); }); }

Mailable 사용

필요에 따라 toMail 메서드에서 MailMessage 대신 완전한 Mailable 객체를 반환할 수도 있습니다. Mailable을 반환하는 경우에는 Mailable 객체의 to 메서드로 수신자를 직접 지정해야 합니다.

use App\Mail\InvoicePaid as InvoicePaidMailable; use Illuminate\Mail\Mailable; /** * 알림의 메일 표현을 반환합니다. */ 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; /** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): Mailable { $address = $notifiable instanceof AnonymousNotifiable ? $notifiable->routeNotificationFor('mail') : $notifiable->email; return (new InvoicePaidMailable($this->invoice)) ->to($address); }

메일 알림 미리보기

메일 알림 템플릿을 디자인할 때 실제 이메일을 발송하지 않고 브라우저에서 바로 확인할 수 있으면 편리합니다. 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 메일 알림을 사용하면 Laravel이 제공하는 사전 구성된 메일 템플릿을 활용하면서도, 더 길고 풍부한 내용의 메시지를 자유롭게 작성할 수 있습니다. 메시지를 Markdown 문법으로 작성하면, Laravel이 아름다운 반응형 HTML 템플릿을 자동으로 렌더링하고, 동시에 일반 텍스트(plain-text) 버전도 함께 생성합니다.

메시지 생성하기

Markdown 템플릿을 사용하는 알림 클래스를 생성하려면 make:notification Artisan 명령에 --markdown 옵션을 사용합니다:

php artisan make:notification InvoicePaid --markdown=mail.invoice.paid

다른 메일 알림과 마찬가지로, Markdown 템플릿을 사용하는 알림 클래스에도 toMail 메서드를 정의해야 합니다. 다만 line이나 action 메서드로 내용을 구성하는 대신, markdown 메서드를 사용해 사용할 Markdown 템플릿 이름을 지정합니다. 두 번째 인자로 템플릿에 전달할 데이터 배열을 넘길 수 있습니다:

/** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): MailMessage { $url = url('/invoice/'.$this->invoice->id); return (new MailMessage) ->subject('청구서 결제 완료') ->markdown('mail.invoice.paid', ['url' => $url]); }

메시지 작성하기

Markdown 메일 알림은 Blade 컴포넌트와 Markdown 문법을 함께 사용합니다. Laravel이 제공하는 알림 전용 컴포넌트를 활용해 깔끔하고 일관된 메시지를 손쉽게 작성할 수 있습니다:

<x-mail::message> # 청구서 결제 완료 청구서 결제가 완료되었습니다! <x-mail::button :url="$url"> 청구서 확인하기 </x-mail::button> 감사합니다,<br> {{ config('app.name') }} </x-mail::message>

버튼 컴포넌트

버튼 컴포넌트는 가운데 정렬된 링크 버튼을 렌더링합니다. url과 선택적 color 인자를 받으며, 지원하는 색상은 primary, green, red입니다. 알림 하나에 버튼을 여러 개 추가할 수도 있습니다:

<x-mail::button :url="$url" color="green"> 청구서 확인하기 </x-mail::button>

패널 컴포넌트

패널 컴포넌트는 지정한 텍스트 블록을 주변과 살짝 다른 배경색의 패널 안에 렌더링합니다. 특정 내용을 시각적으로 강조하고 싶을 때 유용합니다:

<x-mail::panel> 이 부분은 패널 안에 표시됩니다. </x-mail::panel>

테이블 컴포넌트

테이블 컴포넌트는 Markdown 테이블을 HTML 테이블로 변환해 줍니다. Markdown의 기본 테이블 정렬 문법(:---:, ---: 등)을 그대로 사용해 열 정렬을 지정할 수 있습니다:

<x-mail::table> | 항목 | 수량 | 금액 | | ------------- | :-----------: | ------------: | | 상품 A | 2 |10,000 | | 상품 B | 1 |20,000 | </x-mail::table>

컴포넌트 커스터마이징

Markdown 알림 컴포넌트를 직접 수정하고 싶다면, vendor:publish Artisan 명령으로 laravel-mail 에셋 태그를 퍼블리시합니다:

php artisan vendor:publish --tag=laravel-mail

이 명령을 실행하면 Markdown 메일 컴포넌트가 resources/views/vendor/mail 디렉터리에 복사됩니다. mail 디렉터리 아래에는 htmltext 디렉터리가 생성되며, 각각 HTML 버전과 일반 텍스트 버전의 컴포넌트 파일이 담겨 있습니다. 이 파일들을 원하는 대로 자유롭게 수정할 수 있습니다.

CSS 커스터마이징

컴포넌트를 퍼블리시하고 나면 resources/views/vendor/mail/html/themes 디렉터리에 default.css 파일이 생성됩니다. 이 파일의 CSS를 수정하면 스타일이 HTML 알림 메일에 인라인으로 자동 적용됩니다.

완전히 새로운 테마를 만들고 싶다면 html/themes 디렉터리에 새 CSS 파일을 추가하고, config/mail.phptheme 옵션을 해당 파일 이름(확장자 제외)으로 변경하면 됩니다.

특정 알림에만 별도 테마를 적용하려면, 알림 메일 메시지를 구성할 때 theme 메서드를 호출하면 됩니다:

/** * 알림의 메일 표현을 반환합니다. */ public function toMail(object $notifiable): MailMessage { return (new MailMessage) ->theme('invoice') ->subject('청구서 결제 완료') ->markdown('mail.invoice.paid', ['url' => $url]); }

데이터베이스 알림

사전 준비

database 알림 채널은 알림 정보를 데이터베이스 테이블에 저장합니다. 이 테이블에는 알림 타입과 알림 내용을 담은 JSON 데이터 구조가 함께 저장됩니다.

저장된 알림은 테이블을 조회해 애플리케이션 UI에 표시할 수 있습니다. 먼저 알림을 저장할 테이블을 생성해야 합니다. make:notifications-table 명령어를 실행하면 적절한 스키마가 포함된 마이그레이션 파일이 생성됩니다.

php artisan make:notifications-tablephp artisan migrate

NOTE

알림을 받는 모델(Notifiable 모델)이 UUID 또는 ULID 기본 키를 사용하는 경우, 알림 테이블 마이그레이션에서 morphs 메서드를 uuidMorphs 또는 ulidMorphs로 교체해야 합니다.

데이터베이스 알림 포맷 지정

알림을 데이터베이스에 저장하려면 알림 클래스에 toDatabase 또는 toArray 메서드를 정의해야 합니다. 이 메서드는 $notifiable 엔티티를 인자로 받고 일반 PHP 배열을 반환합니다. 반환된 배열은 JSON으로 인코딩되어 notifications 테이블의 data 컬럼에 저장됩니다. 아래는 toArray 메서드의 예시입니다.

/** * 알림의 배열 표현을 반환합니다. * * @return array<string, mixed> */ public function toArray(object $notifiable): array { return [ 'invoice_id' => $this->invoice->id, 'amount' => $this->invoice->amount, ]; }

알림이 데이터베이스에 저장될 때 type 컬럼에는 기본적으로 알림 클래스명이 저장되고, read_at 컬럼은 null로 설정됩니다. 이 동작을 변경하려면 알림 클래스에 databaseTypeinitialDatabaseReadAtValue 메서드를 정의하면 됩니다.

use Illuminate\Support\Carbon; /** * 알림의 데이터베이스 타입을 반환합니다. */ public function databaseType(object $notifiable): string { return 'invoice-paid'; } /** * "read_at" 컬럼의 초기값을 반환합니다. */ public function initialDatabaseReadAtValue(): ?Carbon { return null; }

toDatabase vs. toArray

toArray 메서드는 broadcast 채널에서도 사용됩니다. 브로드캐스트 시 JavaScript 프론트엔드로 전송할 데이터를 결정할 때 동일한 메서드를 참조합니다. database 채널과 broadcast 채널에 각각 다른 데이터를 전달하고 싶다면, toArray 대신 toDatabase 메서드를 별도로 정의하세요.

알림 조회하기

알림이 데이터베이스에 저장된 후에는 Notifiable 엔티티에서 간편하게 조회할 수 있습니다. Laravel 기본 App\Models\User 모델에 포함된 Illuminate\Notifications\Notifiable 트레이트는 notifications Eloquent 관계를 제공합니다. 다른 Eloquent 관계와 동일하게 접근할 수 있으며, 기본적으로 created_at 기준 내림차순(최신 순)으로 정렬됩니다.

$user = App\Models\User::find(1); foreach ($user->notifications as $notification) { echo $notification->type; }

읽지 않은 알림만 조회하려면 unreadNotifications 관계를 사용하세요. 마찬가지로 최신 순으로 정렬됩니다.

$user = App\Models\User::find(1); foreach ($user->unreadNotifications as $notification) { echo $notification->type; }

NOTE

JavaScript 클라이언트에서 알림에 접근하려면 현재 로그인한 사용자와 같은 Notifiable 엔티티의 알림을 반환하는 알림 전용 컨트롤러를 별도로 만들고, 해당 컨트롤러 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의 이벤트 브로드캐스팅 서비스를 설정하고 숙지해야 합니다. 이벤트 브로드캐스팅은 서버에서 발생한 Laravel 이벤트를 JavaScript 프론트엔드에서 실시간으로 처리할 수 있게 해주는 기능입니다.

브로드캐스트 알림 포맷 지정

broadcast 채널은 Laravel의 이벤트 브로드캐스팅 서비스를 통해 알림을 전송하며, JavaScript 프론트엔드에서 실시간으로 알림을 받을 수 있습니다. 알림 클래스에 toBroadcast 메서드를 정의하면 브로드캐스트할 데이터를 직접 지정할 수 있습니다. 이 메서드는 $notifiable 엔티티를 인자로 받아 BroadcastMessage 인스턴스를 반환해야 합니다.

toBroadcast 메서드가 정의되어 있지 않으면, toArray 메서드의 반환값이 대신 사용됩니다. 반환된 데이터는 JSON으로 인코딩되어 프론트엔드로 전송됩니다.

use Illuminate\Notifications\Messages\BroadcastMessage; /** * 브로드캐스트로 전송할 알림 데이터를 반환합니다. */ public function toBroadcast(object $notifiable): BroadcastMessage { return new BroadcastMessage([ 'invoice_id' => $this->invoice->id, 'amount' => $this->invoice->amount, ]); }

브로드캐스트 큐 설정

모든 브로드캐스트 알림은 큐를 통해 처리됩니다. 브로드캐스트 작업에 사용할 큐 커넥션이나 큐 이름을 변경하려면 BroadcastMessageonConnectiononQueue 메서드를 사용하세요.

return (new BroadcastMessage($data)) ->onConnection('sqs') ->onQueue('broadcasts');

알림 타입 커스터마이징

브로드캐스트 알림에는 지정한 데이터 외에도 알림 클래스의 전체 클래스명이 담긴 type 필드가 자동으로 포함됩니다. 이 값을 직접 지정하려면 알림 클래스에 broadcastType 메서드를 정의하세요.

/** * 브로드캐스트할 알림의 타입을 반환합니다. */ public function broadcastType(): string { return 'broadcast.message'; }

알림 수신 대기

알림은 {notifiable}.{id} 형식의 프라이빗 채널을 통해 브로드캐스트됩니다. 예를 들어, ID가 1App\Models\User 인스턴스에 알림을 보내면 App.Models.User.1 프라이빗 채널로 브로드캐스트됩니다. Laravel Echo를 사용하면 notification 메서드로 해당 채널의 알림을 간단하게 수신할 수 있습니다.

Echo.private('App.Models.User.' + userId) .notification((notification) => { console.log(notification.type); });

알림 채널 커스터마이징

알림을 수신하는 엔티티가 브로드캐스트를 받을 채널을 직접 지정하려면, 해당 모델에 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; /** * 사용자가 브로드캐스트 알림을 수신할 채널을 반환합니다. */ public function receivesBroadcastNotificationsOn(): string { return 'users.'.$this->id; } }

알림

SMS 알림

사전 준비

Laravel의 SMS 알림 기능은 Vonage(구 Nexmo)를 통해 동작합니다. Vonage로 SMS를 발송하려면 먼저 아래 패키지를 설치해야 합니다:

composer require laravel/vonage-notification-channel guzzlehttp/guzzle

이 패키지에는 설정 파일이 포함되어 있지만, 반드시 애플리케이션으로 내보낼 필요는 없습니다. VONAGE_KEYVONAGE_SECRET 환경 변수만 설정해도 충분합니다.

키를 설정한 뒤에는 VONAGE_SMS_FROM 환경 변수를 추가하여 SMS 발신 번호를 지정합니다. 이 번호는 Vonage 관리 패널에서 생성할 수 있습니다:

VONAGE_SMS_FROM=15556666666

SMS 알림 포맷 지정

알림 클래스에서 SMS 채널을 지원하려면 toVonage 메서드를 정의합니다. 이 메서드는 $notifiable 엔티티를 인자로 받아 Illuminate\Notifications\Messages\VonageMessage 인스턴스를 반환해야 합니다:

use Illuminate\Notifications\Messages\VonageMessage; /** * Vonage / SMS 채널용 알림 내용 반환 */ public function toVonage(object $notifiable): VonageMessage { return (new VonageMessage) ->content('SMS 메시지 내용을 입력하세요.'); }

유니코드 내용

한국어처럼 유니코드 문자가 포함된 SMS를 보낼 때는 unicode 메서드를 호출해야 합니다. 이를 생략하면 문자가 깨질 수 있습니다:

use Illuminate\Notifications\Messages\VonageMessage; /** * Vonage / SMS 채널용 알림 내용 반환 */ public function toVonage(object $notifiable): VonageMessage { return (new VonageMessage) ->content('안녕하세요! 주문이 완료되었습니다.') ->unicode(); }

NOTE

한국어 등 멀티바이트 문자를 포함한 메시지는 반드시 ->unicode()를 호출해야 정상적으로 수신됩니다.

발신 번호 변경

VONAGE_SMS_FROM에 지정된 기본 발신 번호 대신 다른 번호를 사용하고 싶다면, VonageMessage 인스턴스에서 from 메서드를 호출합니다:

use Illuminate\Notifications\Messages\VonageMessage; /** * Vonage / SMS 채널용 알림 내용 반환 */ public function toVonage(object $notifiable): VonageMessage { return (new VonageMessage) ->content('SMS 메시지 내용을 입력하세요.') ->from('15554443333'); }

클라이언트 레퍼런스 추가

사용자, 팀, 또는 고객별로 SMS 비용을 추적하고 싶다면 클라이언트 레퍼런스를 설정할 수 있습니다. Vonage는 이 값을 기준으로 리포트를 생성해주므로, 특정 고객의 SMS 사용량을 파악하는 데 유용합니다. 클라이언트 레퍼런스는 최대 40자까지 설정할 수 있습니다:

use Illuminate\Notifications\Messages\VonageMessage; /** * Vonage / SMS 채널용 알림 내용 반환 */ public function toVonage(object $notifiable): VonageMessage { return (new VonageMessage) ->clientReference((string) $notifiable->id) ->content('SMS 메시지 내용을 입력하세요.'); }

SMS 알림 라우팅

Vonage 알림이 올바른 전화번호로 전달되도록 하려면, 알림 대상 엔티티(notifiable)에 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; /** * Vonage 채널용 알림 수신 번호 반환 */ public function routeNotificationForVonage(Notification $notification): string { return $this->phone_number; } }

Slack 알림

사전 준비

Slack 알림을 보내려면 먼저 Composer로 Slack 알림 채널 패키지를 설치해야 합니다:

composer require laravel/slack-notification-channel

그리고 Slack 워크스페이스에서 사용할 Slack App을 생성해야 합니다.

같은 워크스페이스 내에서만 알림을 보낼 경우, App에 chat:write, chat:write.public, chat:write.customize 스코프가 필요합니다. Slack App 이름으로 메시지를 보내려면 chat:write:bot 스코프도 추가하세요. 이 스코프들은 Slack의 App 관리 페이지에서 "OAuth & Permissions" 탭에서 추가할 수 있습니다.

설정이 완료되면 "OAuth & Permissions" 탭에서 "Bot User OAuth Token"을 복사하여 애플리케이션의 services.php 설정 파일에 아래와 같이 추가합니다:

'slack' => [ 'notifications' => [ 'bot_user_oauth_token' => env('SLACK_BOT_USER_OAUTH_TOKEN'), 'channel' => env('SLACK_BOT_USER_DEFAULT_CHANNEL'), ], ],

App 배포 (외부 워크스페이스 지원)

애플리케이션의 사용자가 소유한 외부 Slack 워크스페이스로 알림을 보내야 한다면, Slack의 "Manage Distribution" 탭에서 App을 배포(distribute)해야 합니다. 배포 후에는 Laravel Socialite를 활용해 사용자를 Slack으로 인증하고, Slack Bot 토큰을 발급받을 수 있습니다.

Slack 알림 형식 지정

알림 클래스에서 Slack 메시지 전송을 지원하려면 toSlack 메서드를 정의해야 합니다. 이 메서드는 $notifiable 엔티티를 인수로 받고, Illuminate\Notifications\Slack\SlackMessage 인스턴스를 반환합니다.

Slack Block Kit API를 활용하면 구조화된 풍부한 알림을 만들 수 있습니다. 아래 예시는 Slack Block Kit Builder에서 미리 확인해볼 수 있습니다:

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; /** * 알림의 Slack 표현을 반환합니다. */ public function toSlack(object $notifiable): SlackMessage { return (new SlackMessage) ->text('청구서가 결제되었습니다!') ->headerBlock('청구서 결제 완료') ->contextBlock(function (ContextBlock $block) { $block->text('고객 #1234'); }) ->sectionBlock(function (SectionBlock $block) { $block->text('청구서 결제가 확인되었습니다.'); $block->field("*청구서 번호:*\n1000")->markdown(); $block->field("*수신자:*\ntaylor@laravel.com")->markdown(); }) ->dividerBlock() ->sectionBlock(function (SectionBlock $block) { $block->text('감사합니다!'); }); }

Block Kit Builder 템플릿 직접 사용

메서드 체이닝으로 블록을 구성하는 대신, Slack Block Kit Builder에서 생성한 JSON 페이로드를 usingBlockKitTemplate 메서드에 그대로 전달할 수도 있습니다:

use Illuminate\Notifications\Slack\SlackMessage; use Illuminate\Support\Str; /** * 알림의 Slack 표현을 반환합니다. */ public function toSlack(object $notifiable): SlackMessage { $template = <<<JSON { "blocks": [ { "type": "header", "text": { "type": "plain_text", "text": "팀 공지사항" } }, { "type": "section", "text": { "type": "plain_text", "text": "현재 채용 중입니다!" } } ] } JSON; return (new SlackMessage) ->usingBlockKitTemplate($template); }

Slack 인터랙티비티

Slack Block Kit은 사용자 상호작용을 처리할 수 있는 강력한 기능을 제공합니다. 이 기능을 사용하려면 Slack App의 "Interactivity & Shortcuts" 탭에서 "Interactivity"를 활성화하고, 애플리케이션의 URL을 "Request URL"로 등록해야 합니다.

아래 예시처럼 actionsBlock을 사용하면, 사용자가 버튼을 클릭했을 때 Slack이 등록된 Request URL로 POST 요청을 보냅니다. 요청 페이로드에는 클릭한 사용자 정보, 버튼 ID 등이 포함되며, 애플리케이션은 이를 기반으로 후속 처리를 수행할 수 있습니다. 단, 반드시 요청이 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; /** * 알림의 Slack 표현을 반환합니다. */ public function toSlack(object $notifiable): SlackMessage { return (new SlackMessage) ->text('청구서가 결제되었습니다!') ->headerBlock('청구서 결제 완료') ->contextBlock(function (ContextBlock $block) { $block->text('고객 #1234'); }) ->sectionBlock(function (SectionBlock $block) { $block->text('청구서 결제가 확인되었습니다.'); }) ->actionsBlock(function (ActionsBlock $block) { // ID를 지정하지 않으면 "button_acknowledge_invoice"가 기본값으로 사용됩니다. $block->button('청구서 확인')->primary(); // ID를 직접 지정하는 경우 $block->button('거절')->danger()->id('deny_invoice'); }); }

확인 모달

버튼 클릭 시 사용자에게 추가 확인을 요구하려면 confirm 메서드를 사용하세요. 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; /** * 알림의 Slack 표현을 반환합니다. */ public function toSlack(object $notifiable): SlackMessage { return (new SlackMessage) ->text('청구서가 결제되었습니다!') ->headerBlock('청구서 결제 완료') ->contextBlock(function (ContextBlock $block) { $block->text('고객 #1234'); }) ->sectionBlock(function (SectionBlock $block) { $block->text('청구서 결제가 확인되었습니다.'); }) ->actionsBlock(function (ActionsBlock $block) { $block->button('청구서 확인') ->primary() ->confirm( '결제를 확인하고 감사 이메일을 발송할까요?', function (ConfirmObject $dialog) { $dialog->confirm('예'); $dialog->deny('아니오'); } ); }); }

Slack 블록 디버깅

구성 중인 블록을 빠르게 확인하려면 SlackMessage 인스턴스에서 dd 메서드를 호출하세요. 이 메서드는 Block Kit Builder URL을 생성하고 브라우저에서 미리보기를 열 수 있는 링크를 출력합니다. true를 전달하면 원시 JSON 페이로드를 바로 덤프합니다:

return (new SlackMessage) ->text('청구서가 결제되었습니다!') ->headerBlock('청구서 결제 완료') ->dd();

Slack 알림 라우팅

Slack 알림을 원하는 팀과 채널로 보내려면, 알림 대상 모델(Notifiable 모델)에 routeNotificationForSlack 메서드를 정의합니다. 이 메서드는 다음 세 가지 값 중 하나를 반환할 수 있습니다:

  • null — 알림 클래스의 to 메서드로 지정된 채널을 사용합니다.
  • 문자열 — 전송할 Slack 채널명을 지정합니다. 예: #support-channel
  • SlackRoute 인스턴스 — OAuth 토큰과 채널명을 함께 지정합니다. 예: SlackRoute::make($this->slack_channel, $this->slack_token). 외부 워크스페이스로 보낼 때 사용합니다.

아래 예시에서 #support-channel을 반환하면, services.php에 설정된 Bot User OAuth Token과 연결된 워크스페이스의 #support-channel 채널로 알림이 전송됩니다:

<?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; /** * Slack 알림을 수신할 채널을 반환합니다. */ public function routeNotificationForSlack(Notification $notification): mixed { return '#support-channel'; } }

외부 Slack 워크스페이스로 알림 보내기

NOTE

외부 Slack 워크스페이스로 알림을 보내려면 먼저 Slack App이 배포(distributed) 상태여야 합니다.

사용자가 소유한 외부 Slack 워크스페이스로 알림을 보내려면, 해당 사용자의 Slack OAuth 토큰을 먼저 발급받아야 합니다. Laravel Socialite의 Slack 드라이버를 사용하면 사용자를 Slack으로 인증하고 Bot 토큰을 발급받는 작업을 손쉽게 처리할 수 있습니다.

Bot 토큰을 발급받아 데이터베이스에 저장했다면, SlackRoute::make 메서드를 사용해 해당 사용자의 워크스페이스로 알림을 라우팅하면 됩니다. 일반적으로 사용자가 알림을 받을 채널도 직접 지정할 수 있도록 UI를 제공하는 것이 좋습니다:

<?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; /** * Slack 알림을 수신할 채널을 반환합니다. */ public function routeNotificationForSlack(Notification $notification): mixed { return SlackRoute::make($this->slack_channel, $this->slack_token); } }

알림 현지화 (Localization)

Laravel은 현재 HTTP 요청의 로케일과 다른 언어로 알림을 발송할 수 있습니다. 알림이 큐에 등록된 경우에도 지정한 로케일이 기억됩니다.

이를 위해 Illuminate\Notifications\Notification 클래스의 locale 메서드로 원하는 언어를 지정하면 됩니다. 알림이 처리되는 동안 애플리케이션은 해당 로케일로 전환되었다가, 처리가 완료되면 이전 로케일로 자동 복원됩니다.

$user->notify((new InvoicePaid($invoice))->locale('ko'));

여러 수신자에게 동시에 현지화된 알림을 보낼 때는 Notification 파사드를 활용하세요.

Notification::locale('ko')->send( $users, new InvoicePaid($invoice) );

사용자별 선호 로케일

사용자마다 선호하는 언어를 DB에 저장해두는 경우가 많습니다. 이때 알림을 보낼 때마다 locale을 직접 지정하는 대신, Notifiable 모델에 HasLocalePreference 계약(contract)을 구현하면 Laravel이 자동으로 해당 로케일을 사용합니다.

use Illuminate\Contracts\Translation\HasLocalePreference; class User extends Model implements HasLocalePreference { /** * 사용자의 선호 로케일을 반환합니다. */ public function preferredLocale(): string { return $this->locale; } }

인터페이스를 구현하면 알림과 메일러블(Mailable) 발송 시 Laravel이 자동으로 preferredLocale()의 반환값을 사용합니다. 따라서 별도로 locale 메서드를 호출할 필요가 없습니다.

$user->notify(new InvoicePaid($invoice));

NOTE

HasLocalePreference는 알림뿐만 아니라 메일러블에도 동일하게 적용됩니다. 사용자 모델에 한 번만 구현해두면 두 채널 모두에서 자동으로 활용됩니다.

알림

테스트

알림이 실제로 발송되는 것을 막으려면 Notification 파사드의 fake 메서드를 사용하세요. 일반적으로 알림 발송은 테스트하려는 핵심 로직과 직접적인 관련이 없습니다. 대부분의 경우, Laravel에 특정 알림을 발송하도록 지시했는지 여부만 검증하는 것으로 충분합니다.

Notification::fake()를 호출한 뒤에는 특정 사용자에게 알림이 발송되었는지 검증하거나, 알림에 전달된 데이터를 직접 확인할 수 있습니다.

Pest

<?php use App\Notifications\OrderShipped; use Illuminate\Support\Facades\Notification; test('주문을 배송할 수 있다', function () { Notification::fake(); // 주문 배송 처리... // 아무 알림도 발송되지 않았는지 검증... Notification::assertNothingSent(); // 지정한 사용자에게 알림이 발송되었는지 검증... Notification::assertSentTo( [$user], OrderShipped::class ); // 특정 알림이 발송되지 않았는지 검증... Notification::assertNotSentTo( [$user], AnotherNotification::class ); // 발송된 알림의 총 개수를 검증... 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_주문을_배송할__있다(): void { Notification::fake(); // 주문 배송 처리... // 아무 알림도 발송되지 않았는지 검증... Notification::assertNothingSent(); // 지정한 사용자에게 알림이 발송되었는지 검증... Notification::assertSentTo( [$user], OrderShipped::class ); // 특정 알림이 발송되지 않았는지 검증... Notification::assertNotSentTo( [$user], AnotherNotification::class ); // 발송된 알림의 총 개수를 검증... Notification::assertCount(3); } }

assertSentTo 또는 assertNotSentTo 메서드에 클로저를 전달하면, 발송된 알림이 특정 조건을 만족하는지 세밀하게 검증할 수 있습니다. 조건을 통과하는 알림이 하나 이상 존재하면 검증이 성공합니다.

Notification::assertSentTo( $user, function (OrderShipped $notification, array $channels) use ($order) { return $notification->order->id === $order->id; } );

온디맨드 알림 테스트

테스트 대상 코드가 온디맨드 알림을 발송하는 경우, assertSentOnDemand 메서드로 해당 알림이 올바르게 발송되었는지 검증할 수 있습니다.

Notification::assertSentOnDemand(OrderShipped::class);

assertSentOnDemand의 두 번째 인수로 클로저를 전달하면, 온디맨드 알림이 올바른 "라우트" 주소로 발송되었는지도 확인할 수 있습니다.

Notification::assertSentOnDemand( OrderShipped::class, function (OrderShipped $notification, array $channels, object $notifiable) use ($user) { return $notifiable->routes['mail'] === $user->email; } );

알림 이벤트

NotificationSending 이벤트

알림이 발송되기 직전에 알림 시스템은 Illuminate\Notifications\Events\NotificationSending 이벤트를 디스패치합니다. 이 이벤트에는 알림 수신 대상(notifiable) 엔티티와 알림 인스턴스가 포함됩니다. 애플리케이션에서 이 이벤트에 대한 이벤트 리스너를 등록해 활용할 수 있습니다.

use Illuminate\Notifications\Events\NotificationSending; class CheckNotificationStatus { /** * 이벤트를 처리합니다. */ public function handle(NotificationSending $event): void { // ... } }

NotificationSending 이벤트의 리스너 handle 메서드에서 false를 반환하면, 해당 알림은 실제로 발송되지 않습니다. 특정 조건에서 알림 발송을 중단해야 할 때 유용하게 활용할 수 있습니다.

/** * 이벤트를 처리합니다. */ public function handle(NotificationSending $event): bool { return false; }

리스너 안에서는 이벤트의 notifiable, notification, channel 프로퍼티에 접근해 수신자나 알림의 세부 정보를 확인할 수 있습니다.

/** * 이벤트를 처리합니다. */ public function handle(NotificationSending $event): void { // $event->channel — 발송 채널 (예: 'mail', 'slack' 등) // $event->notifiable — 알림 수신 대상 엔티티 // $event->notification — 알림 인스턴스 }

NotificationSent 이벤트

알림이 성공적으로 발송된 직후에는 Illuminate\Notifications\Events\NotificationSent 이벤트가 디스패치됩니다. 이 이벤트 역시 notifiable 엔티티와 알림 인스턴스를 포함합니다. 애플리케이션에서 이벤트 리스너를 등록해 발송 이력 로깅 등의 후처리를 수행할 수 있습니다.

use Illuminate\Notifications\Events\NotificationSent; class LogNotification { /** * 이벤트를 처리합니다. */ public function handle(NotificationSent $event): void { // ... } }

리스너 안에서는 notifiable, notification, channel, response 프로퍼티에 접근할 수 있습니다. response는 채널 드라이버가 반환한 실제 응답 값으로, 발송 결과를 로깅하거나 추가 처리에 활용할 수 있습니다.

/** * 이벤트를 처리합니다. */ public function handle(NotificationSent $event): void { // $event->channel — 발송 채널 // $event->notifiable — 알림 수신 대상 엔티티 // $event->notification — 알림 인스턴스 // $event->response — 채널 드라이버의 발송 응답 값 }

NOTE

NotificationSending은 발송 가로채기용, NotificationSent는 발송 후처리용으로 역할이 명확히 구분됩니다. 발송 차단이 필요하면 NotificationSending 리스너를, 발송 결과 기록이 필요하면 NotificationSent 리스너를 사용하세요.

알림

커스텀 채널

Laravel은 다양한 내장 알림 채널을 제공하지만, 필요에 따라 직접 드라이버를 작성하여 원하는 채널로 알림을 전송할 수 있습니다. Laravel은 이 과정을 매우 간단하게 만들어 줍니다.

커스텀 채널을 만들려면, send 메서드를 포함한 클래스를 정의하면 됩니다. 이 메서드는 $notifiable$notification 두 개의 인수를 받습니다.

send 메서드 내에서는 알림 객체의 메서드를 호출해 채널에 맞는 메시지 객체를 가져온 뒤, $notifiable 인스턴스에 원하는 방식으로 알림을 전송하면 됩니다.

<?php namespace App\Notifications; use Illuminate\Notifications\Notification; class VoiceChannel { /** * 주어진 알림을 전송합니다. */ public function send(object $notifiable, Notification $notification): void { $message = $notification->toVoice($notifiable); // $notifiable 인스턴스에 알림을 전송합니다... } }

채널 클래스를 정의했다면, 알림 클래스의 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; /** * 알림을 전송할 채널을 반환합니다. */ public function via(object $notifiable): string { return VoiceChannel::class; } /** * 알림의 음성 표현을 반환합니다. */ public function toVoice(object $notifiable): VoiceMessage { // ... } }

NOTE

커스텀 채널을 커뮤니티와 공유하고 싶다면, 독립적인 패키지로 만들어 Packagist에 배포하는 것을 고려해 보세요. Laravel 생태계에는 이미 SMS, 푸시 알림 등 다양한 서드파티 채널 패키지가 존재하며, 이를 참고하면 구현에 도움이 됩니다.

이 문서는 Laravel 공식 문서(MIT)를 한국 개발자를 위해 번역·재구성한 것입니다.

번역일: 2026년 6월 27일