Blade로 Chirper 구축 - 알림 및 이벤트

1 개요[ | ]

07. Notifications & Events
07. 알림 및 이벤트

https://bootcamp.laravel.com/blade/notifications-and-events

이메일 발송 지원 외에도, Laravel은 이메일, SMS, Slack 등 다양한 전달 채널을 통한 알림 전송을 지원합니다. 또한, 커뮤니티에서 구축한 다양한 알림 채널을 통해 수십 가지 다른 채널로 알림을 보낼 수 있습니다! 알림은 데이터베이스에 저장되어 웹 인터페이스에서 표시될 수도 있습니다.

2 알림 생성하기[ | ]

Artisan이 또 한 번, 아래 명령어로 모든 어려운 작업을 대신해 줄 수 있습니다:

php artisan make:notification NewChirp

이 명령어는 app/Notifications/NewChirp.php에 커스터마이징할 준비가 된 새로운 알림을 생성합니다.

이제 NewChirp 클래스를 열어 새로 작성된 Chirp를 수락하고, 메시지에 작성자의 이름과 메시지 일부를 포함하도록 커스터마이징해 보겠습니다:

app/Notifications/NewChirp.php
<?php
namespace App\Notifications;
 
use App\Models\Chirp;
use Illuminate\Bus\Queueable;
use Illuminate\Support\Str;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
 
class NewChirp extends Notification
{
    use Queueable;
 
    /**
     * Create a new notification instance.
     */
    public function __construct(public Chirp $chirp)
    {
        //
    }
 
    /**
     * Get the mail representation of the notification.
     */
    public function toMail(object $notifiable): MailMessage
    {
        return (new MailMessage)
                    ->subject("New Chirp from {$this->chirp->user->name}")
                    ->greeting("New Chirp from {$this->chirp->user->name}")
                    ->line(Str::limit($this->chirp->message, 50))
                    ->action('Go to Chirper', url('/'))
                    ->line('Thank you for using our application!');
    }
    ...
}

ChirpController 클래스의 store 메소드에서 직접 알림을 보낼 수 있지만, 그렇게 하면 컨트롤러의 작업이 많아져 요청이 느려질 수 있습니다. 특히 데이터베이스를 쿼리하고 이메일을 보내는 작업이 추가되기 때문입니다.

대신, 이벤트를 디스패치하여 이를 백그라운드 큐에서 처리하도록 만들어 애플리케이션이 빠르게 반응할 수 있도록 합시다.

3 이벤트 생성하기[ | ]

이벤트는 애플리케이션의 다양한 측면을 분리하는 데 매우 유용합니다. 하나의 이벤트에 여러 리스너가 있을 수 있으며, 이들은 서로 의존하지 않습니다.

다음 명령어를 사용하여 새 이벤트를 생성해 봅시다:

php artisan make:event ChirpCreated

이 명령어는 app/Events/ChirpCreated.php에 새 이벤트 클래스를 생성합니다.

각 새로운 Chirp가 생성될 때마다 이벤트를 디스패치할 것이므로, 새로 생성된 Chirp를 받아 알림으로 전달할 수 있도록 ChirpCreated 이벤트를 업데이트합시다:

app/Events/ChirpCreated.php
<?php

namespace App\Events;

use App\Models\Chirp;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class ChirpCreated
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    /**
     * Create a new event instance.
     */
    public function __construct(public Chirp $chirp)
    {
        //
    }
    ...
}

4 이벤트 디스패치하기[ | ]

이제 이벤트 클래스를 가지고 있으니 Chirp가 생성될 때마다 이벤트를 디스패치할 준비가 되었습니다. 애플리케이션의 라이프사이클 어디에서나 이벤트를 디스패치할 수 있지만, 우리의 이벤트는 Eloquent 모델의 생성과 관련이 있으므로 Chirp 모델이 이벤트를 디스패치하도록 설정할 수 있습니다.

app/Models/Chirp.php
<?php

namespace App\Models;

use App\Events\ChirpCreated;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Chirp extends Model
{
    use HasFactory;

    protected $fillable = [
        'message',
    ];

    protected $dispatchesEvents = [
        'created' => ChirpCreated::class,
    ];

    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }
}

이제 새로운 Chirp가 생성될 때마다 ChirpCreated 이벤트가 디스패치될 것입니다.

5 이벤트 리스너 생성하기[ | ]

이제 이벤트를 디스패치하고 있으므로, 해당 이벤트를 청취하여 알림을 보내는 리스너를 만들어 보겠습니다.

ChirpCreated 이벤트에 구독하는 리스너를 생성합니다:

php artisan make:listener SendChirpCreatedNotifications --event=ChirpCreated

새로운 리스너는 app/Listeners/SendChirpCreatedNotifications.php에 위치하게 됩니다. 이 리스너를 업데이트하여 알림을 보내도록 하겠습니다.

app/Listeners/SendChirpCreatedNotifications.php
<?php

namespace App\Listeners;

use App\Events\ChirpCreated;
use App\Models\User;
use App\Notifications\NewChirp;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;

class SendChirpCreatedNotifications implements ShouldQueue
{
    ...
    /**
     * Handle the event.
     */
    public function handle(ChirpCreated $event): void
    {
        // 이벤트 처리
        foreach (User::whereNot('id', $event->chirp->user_id)->cursor() as $user) {
            $user->notify(new NewChirp($event->chirp));
        }
    }
}

리스너에 ShouldQueue 인터페이스를 지정하여, 리스너가 에서 실행되도록 Laravel에 알려줍니다. 기본적으로 "database" 큐가 사용되어 작업이 비동기적으로 처리됩니다. 큐에 작업을 처리하려면 터미널에서 php artisan queue:work Artisan 명령어를 실행해야 합니다.

또한, 모든 플랫폼 사용자에게 알림을 보내도록 리스너를 구성했으며, Chirp 작성자는 제외했습니다. 실제로는 이로 인해 사용자가 불편할 수 있으므로, 팔로우한 계정에 대해서만 알림을 받도록 하는 "팔로우" 기능을 구현하는 것이 좋습니다.

모든 사용자를 한 번에 메모리에 로드하지 않기 위해 데이터베이스 커서를 사용했습니다.

Note

프로덕션 애플리케이션에서는 사용자가 이러한 알림을 구독 해지할 수 있는 기능을 추가해야 합니다.

6 테스트하기[ | ]

애플리케이션에서 전송된 이메일을 확인하기 위해 MailpitHELO 같은 로컬 이메일 테스트 도구를 사용할 수 있습니다. Docker와 Laravel Sail을 사용하여 개발 중이라면 Mailpit이 포함되어 있습니다.

대안으로, 프로젝트의 .env 파일을 편집하여 MAIL_MAILER 환경변수를 log로 변경하면 Laravel이 이메일을 로그 파일에 작성하도록 설정할 수 있습니다. 기본적으로 이메일은 storage/logs/laravel.log 파일에 기록됩니다.

알림이 Chirp 작성자에게 전송되지 않도록 설정했으므로, 두 개 이상의 사용자 계정을 등록하십시오. 그런 다음 새 Chirp를 게시하여 알림을 트리거하세요.

Mailpit을 사용 중이라면 http://localhost:8025/ 로 이동하여 방금 게시한 메시지에 대한 알림을 찾을 수 있습니다!

Mailpit.png

6.1 프로덕션에서 이메일 보내기[ | ]

프로덕션 환경에서 실제 이메일을 전송하려면 SMTP 서버 또는 Mailgun, Postmark, Amazon SES와 같은 트랜잭셔널 이메일 제공자가 필요합니다. Laravel은 이러한 모든 제공자를 기본적으로 지원합니다. 자세한 내용은 Mail 문서를 참조하십시오.

문서 댓글 ({{ doc_comments.length }})
{{ comment.name }} {{ comment.created | snstime }}