본문 바로가기

Broadcasting

업데이트됨

번역일: 2026년 9월 18일

이 페이지는 원문이 업데이트되어 번역이 갱신되었습니다.

원문 수정
2026년 9월 18일
번역 갱신
2026년 9월 18일

Broadcasting

브로드캐스팅

빠른 시작

기본적으로 새로운 Laravel 애플리케이션에는 브로드캐스팅 기능이 활성화되어 있지 않습니다. install:broadcasting Artisan 명령어를 사용하면 브로드캐스팅 기능을 손쉽게 활성화할 수 있습니다.

php artisan install:broadcasting

install:broadcasting 명령어는 애플리케이션의 브로드캐스팅 설정 파일인 config/broadcasting.php를 생성합니다. 또한 이 명령어는 애플리케이션의 브로드캐스팅 인가 라우트와 콜백을 등록하는 데 필요한 라우트 파일 routes/channels.php도 생성해 줍니다.

빠른 시작 다음 단계

애플리케이션의 브로드캐스팅 기능을 설정한 뒤에는, Laravel 이벤트를 브로드캐스트하는 방법과 이를 수신하는 방법을 자세히 학습해 보시기 바랍니다. 이 문서에서는 다음 두 가지를 자세히 다룹니다:

서버 사이드 설치

Laravel의 이벤트 브로드캐스팅 기능을 사용하려면 Laravel 애플리케이션 내부에서 약간의 설정을 진행하고, 몇 가지 패키지를 설치해야 합니다.

이벤트 브로드캐스팅은 서버 사이드 브로드캐스팅 드라이버가 Laravel 이벤트를 브로드캐스트하면, 브라우저의 Laravel Echo(자바스크립트 라이브러리)가 이를 WebSocket 연결을 통해 수신하는 방식으로 동작합니다. 걱정하지 않으셔도 됩니다. 아래에서 각 단계를 하나씩 자세히 살펴보겠습니다.

설정

애플리케이션의 이벤트 브로드캐스팅 설정은 모두 config/broadcasting.php 설정 파일에 저장됩니다. 만약 이 디렉터리가 애플리케이션에 존재하지 않더라도 걱정할 필요는 없습니다. install:broadcasting Artisan 명령어를 실행할 때 자동으로 생성됩니다.

Laravel은 기본적으로 여러 브로드캐스트 드라이버를 지원합니다: Laravel Reverb, Pusher Channels, Ably, Mercure, 그리고 로컬 개발과 디버깅을 위한 log 드라이버입니다. 또한 테스트 중에 브로드캐스팅을 완전히 비활성화할 수 있는 null 드라이버도 포함되어 있습니다. 각 드라이버에 대한 설정 예시는 config/broadcasting.php 설정 파일에 포함되어 있습니다.

설치

기본적으로 새로운 Laravel 애플리케이션에는 브로드캐스팅이 활성화되어 있지 않습니다. install:broadcasting Artisan 명령어를 통해 브로드캐스팅을 활성화할 수 있습니다.

php artisan install:broadcasting

install:broadcasting 명령어를 실행하면 브로드캐스팅 설정 파일인 config/broadcasting.php가 생성됩니다. 또한 이 명령어는 애플리케이션의 브로드캐스팅 인가 라우트 및 콜백을 등록할 수 있는 routes/channels.php 파일도 함께 생성해 줍니다.

큐 설정

이벤트를 브로드캐스팅하기 전에, 먼저 큐 워커를 설정하고 실행해야 합니다. 모든 이벤트 브로드캐스팅은 큐에 등록된 작업(Job)을 통해 처리되므로, 애플리케이션의 응답 시간이 이벤트 브로드캐스팅으로 인해 크게 지연되지 않습니다.

Reverb

install:broadcasting 명령어를 실행할 때 Laravel Reverb를 브로드캐스트 드라이버로 선택하면, Composer 패키지 매니저를 통해 Reverb 패키지가 자동으로 설치되며, 애플리케이션의 .env 파일에 필요한 Reverb 환경 변수들이 추가됩니다. 또한 Reverb를 시작하는 데 필요한 설정도 자동으로 실행됩니다.

Reverb 설정에 관한 모든 내용은 Laravel Reverb 문서에서 확인하실 수 있습니다.

Pusher Channels

Pusher Channels를 사용해 이벤트를 브로드캐스팅하려면, Composer 패키지 매니저를 통해 Pusher Channels PHP SDK를 설치해야 합니다.

composer require pusher/pusher-php-server

다음으로, config/broadcasting.php 설정 파일에서 Pusher Channels 설정을 구성해야 합니다. 이 파일에는 이미 Pusher Channels 설정 예시가 포함되어 있어, Pusher Channels의 키, 시크릿, 애플리케이션 ID를 빠르게 지정할 수 있습니다. 일반적으로 이 값들은 PUSHER_APP_KEY, PUSHER_APP_SECRET, PUSHER_APP_ID 환경 변수를 통해 설정해야 합니다.

PUSHER_APP_ID=your-pusher-app-id PUSHER_APP_KEY=your-pusher-key PUSHER_APP_SECRET=your-pusher-secret PUSHER_APP_CLUSTER=mt1 BROADCAST_CONNECTION=pusher

config/broadcasting.php 파일의 pusher 설정을 통해 클러스터와 같은 추가 옵션들도 지정할 수 있으며, TLS 암호화를 사용할지 여부 등도 설정할 수 있습니다.

'options' => [ 'cluster' => env('PUSHER_APP_CLUSTER'), 'useTLS' => true, ],

설정이 완료되면, Laravel Echo 자바스크립트 라이브러리를 사용해 클라이언트 사이드에서 브로드캐스트 이벤트를 수신할 준비를 시작할 수 있습니다.

오픈 소스 Pusher 호환 대안

laravel-websocketssoketi는 Pusher Channels PHP SDK와 호환되는 WebSocket 서버 패키지로, Laravel 브로드캐스팅 기능을 Pusher 없이도 완전히 활용할 수 있게 해줍니다. 이 패키지들을 사용하면 상용 WebSocket 제공업체와 계약하지 않고도 브로드캐스팅 기능의 전체 이점을 누릴 수 있습니다.

Pusher 호환 오픈 소스 대안 항목에서 이러한 패키지들을 사용하는 방법에 대한 자세한 내용을 확인할 수 있습니다.

Ably

NOTE

아래 문서에서는 Ably를 "Pusher 호환" 모드로 사용하는 방법을 설명합니다. 그러나 Ably 팀은 Ably가 지원하는 고유한 기능들을 훨씬 더 잘 활용할 수 있는 자체 브로드캐스터 및 Echo 클라이언트 사용을 권장합니다. Ably 고유의 드라이버를 사용하는 방법에 대해 더 알고 싶다면 Ably의 Laravel 브로드캐스터 문서를 참고하시기 바랍니다.

Ably를 사용해 이벤트를 브로드캐스팅하려면, Composer 패키지 매니저를 통해 Ably PHP SDK를 설치해야 합니다.

composer require ably/ably-php

먼저, config/broadcasting.php 설정 파일에 Ably 설정을 추가해야 합니다. 다행히 이 파일에는 이미 Ably 설정 예시가 포함되어 있어, Ably의 키를 빠르게 지정할 수 있습니다. 일반적으로 이 값은 ABLY_KEY 환경 변수를 통해 설정합니다.

ABLY_KEY=your-ably-key BROADCAST_CONNECTION=ably

설정을 마쳤다면, Laravel Echo 자바스크립트 라이브러리를 사용해 클라이언트 사이드에서 브로드캐스트 이벤트를 수신할 준비를 시작할 수 있습니다.

Ably를 "Pusher 호환" 모드로 사용하려면, 애플리케이션의 Ably 애플리케이션 설정 내 "Protocol Adapter Settings" 부분에서 Pusher 프로토콜 지원을 활성화해야 합니다.

클라이언트 사이드 설치

Reverb

Laravel Echo는 채널과 이벤트를 구독하는 과정을 매끄럽게 처리해주는 자바스크립트 라이브러리입니다. install:broadcasting Artisan 명령어를 실행하면 laravel-echopusher-js 패키지가 함께 설치됩니다. 하지만 애플리케이션을 직접 설정하고자 한다면, NPM 패키지 매니저를 통해 두 패키지를 수동으로 설치할 수도 있습니다.

npm install --save-dev laravel-echo pusher-js

Echo 인스턴스를 생성하기 전에, Laravel Reverb를 서버로 사용한다는 사실을 Echo가 알 수 있도록 애플리케이션의 resources/js/echo.js 파일에서 broadcaster 설정을 reverb로 지정해야 합니다. install:broadcasting Artisan 명령어를 실행하면 이 설정이 이미 완료되어 있으므로, 애플리케이션의 .env 파일에 필요한 Reverb 환경 변수만 추가하면 됩니다. 그러면 Echo 인스턴스를 생성할 준비가 완료됩니다.

import Echo from 'laravel-echo'; import Pusher from 'pusher-js'; window.Pusher = Pusher; window.Echo = new Echo({ broadcaster: 'reverb', key: import.meta.env.VITE_REVERB_APP_KEY, wsHost: import.meta.env.VITE_REVERB_HOST, wsPort: import.meta.env.VITE_REVERB_PORT, wssPort: import.meta.env.VITE_REVERB_PORT, forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https', enabledTransports: ['ws', 'wss'], });

다음으로, 애플리케이션의 애셋을 컴파일해야 합니다.

npm run build

WARNING

Laravel Echo의 reverb 브로드캐스터는 laravel-echo v1.16.0 이상 버전이 필요합니다.

Pusher Channels

Laravel Echo는 채널과 이벤트를 구독하는 과정을 매끄럽게 처리해주는 자바스크립트 라이브러리입니다. Echo는 NPM 패키지 매니저를 통해 설치할 수 있습니다. 이 예제에서는 Pusher Channels 브로드캐스터를 사용하므로 pusher-js 패키지도 함께 설치하겠습니다.

npm install --save-dev laravel-echo pusher-js

Echo가 설치되면, 애플리케이션 자바스크립트에서 새로운 Echo 인스턴스를 생성할 준비가 된 것입니다. install:broadcasting Artisan 명령어를 실행하면 애플리케이션의 resources/js/bootstrap.js 파일 하단에 좋은 시작점이 되는 예제 코드가 이미 추가되어 있습니다. 다만, 이 파일에 있는 기본 설정은 Reverb용이므로, 아래 설정을 그대로 복사해 Pusher용으로 전환할 수 있습니다.

import Echo from 'laravel-echo'; import Pusher from 'pusher-js'; window.Pusher = Pusher; window.Echo = new Echo({ broadcaster: 'pusher', key: import.meta.env.VITE_PUSHER_APP_KEY, cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER, forceTLS: true });

다음으로, 애플리케이션의 .env 파일에 Pusher 환경 변수들을 적절히 정의해야 합니다. 만약 .env 파일에 해당 변수들이 아직 없다면 추가해야 합니다.

PUSHER_APP_KEY="${PUSHER_APP_KEY}" PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}" VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

환경 변수와 Echo 설정을 애플리케이션의 필요에 맞게 조정했다면, 이제 애플리케이션의 애셋을 컴파일할 수 있습니다.

npm run build

NOTE

자바스크립트 애셋 컴파일에 대해 더 알고 싶다면 Vite 문서를 참고하세요.

기존 클라이언트 인스턴스 사용하기

이미 사전 설정된 Pusher Channels 또는 Ably 클라이언트 인스턴스를 Echo와 함께 사용하고 싶다면, client 설정 옵션을 통해 Echo에 전달할 수 있습니다.

import Echo from 'laravel-echo'; import Pusher from 'pusher-js'; const options = { broadcaster: 'pusher', key: 'your-pusher-channels-key' }; window.Echo = new Echo({ ...options, client: new Pusher(options.key, options) });

오픈 소스 대안

PHP WebSocket

laravel-websockets 패키지는 Pusher Channels 호환 WebSocket 패키지로, Laravel과 함께 사용할 수 있습니다. 이 패키지를 사용하면 상용 WebSocket 제공업체와 계약하지 않고도 브로드캐스팅 기능의 모든 이점을 누릴 수 있습니다. 설치 및 사용 방법에 대한 자세한 내용은 패키지의 공식 문서를 참고하세요.

Soketi

Soketi는 Node 기반의 빠르고 확장 가능한 오픈 소스 WebSocket 서버입니다. 내부적으로 μWebSockets.js를 사용해 뛰어난 확장성과 속도를 제공합니다. 이 패키지는 Pusher 프로토콜과 호환되므로 Laravel Echo와 함께 사용할 수 있습니다.

개념 개요

Laravel의 이벤트 브로드캐스팅을 사용하면 서버 사이드 Laravel 이벤트를 WebSocket 기반 드라이버를 통해 클라이언트 사이드 자바스크립트 애플리케이션으로 브로드캐스트할 수 있습니다. 현재 Laravel은 기본적으로 Pusher ChannelsAbly 드라이버를 제공합니다. 클라이언트 사이드에서는 Laravel Echo 자바스크립트 패키지를 사용해 이벤트를 손쉽게 수신할 수 있습니다.

이벤트는 "채널"을 통해 브로드캐스트되며, 채널은 공개 또는 비공개로 지정할 수 있습니다. 애플리케이션의 방문자라면 누구나 인증이나 인가 절차 없이 공개 채널을 구독할 수 있습니다. 반면, 비공개 채널을 구독하려면 클라이언트가 해당 채널을 수신할 수 있는 권한이 있는지 인증 및 인가 과정을 거쳐야 합니다.

NOTE

Pusher의 오픈 소스 대안을 살펴보고 싶다면, 오픈 소스 대안 절을 참고하세요.

예제 애플리케이션 사용해 보기

이벤트 브로드캐스팅 각 요소를 자세히 알아보기 전에, 전자상거래 스토어를 예로 들어 전체적인 개요를 살펴보겠습니다.

이 예제에서는 사용자가 자신의 주문 배송 상태를 확인할 수 있는 페이지를 가지고 있다고 가정하겠습니다. 그리고 주문 배송 상태가 갱신될 때마다 OrderShipmentStatusUpdated 이벤트가 발생한다고 가정해 보겠습니다.

use App\Events\OrderShipmentStatusUpdated; OrderShipmentStatusUpdated::dispatch($order);

`ShouldBroadcast` 인터페이스

사용자가 주문 중 하나를 보고 있을 때, 배송 상태가 갱신될 때마다 사용자가 페이지를 새로고침하지 않고도 상태 갱신 내용을 확인할 수 있게 하고 싶습니다. 이를 위해 OrderShipmentStatusUpdated 이벤트가 ShouldBroadcast 인터페이스를 구현하도록 만들어야 합니다. 그러면 이벤트가 발생(dispatch)될 때 Laravel이 자동으로 해당 이벤트를 브로드캐스트합니다.

<?php namespace App\Events; use App\Models\Order; use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Broadcasting\PresenceChannel; use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Queue\SerializesModels; class OrderShipmentStatusUpdated implements ShouldBroadcast { /** * 새로운 이벤트 인스턴스를 생성합니다. */ public function __construct( public Order $order, ) {} }

ShouldBroadcast 인터페이스는 이벤트에 broadcastOn 메서드를 정의하도록 요구합니다. 이 메서드는 해당 이벤트가 브로드캐스트되어야 할 채널을 반환하는 역할을 담당합니다. 이 메서드의 기본 뼈대는 이미 이벤트 클래스를 생성할 때 자동으로 만들어지므로, 남은 작업은 이 메서드의 세부 내용을 채우는 것뿐입니다. 여기서는 주문을 생성한 사용자만 상태 갱신 내용을 볼 수 있어야 하므로, 주문과 관련된 비공개 채널에 이벤트를 브로드캐스트하도록 작성합니다.

use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\PrivateChannel; /** * 이 이벤트가 브로드캐스트될 채널을 반환합니다. * * @return array<int, \Illuminate\Broadcasting\Channel> */ public function broadcastOn(): array { return [ new PrivateChannel('orders.'.$this->order->id), ]; }

이벤트를 브로드캐스트할 때 여러 채널로 동시에 브로드캐스트하고 싶다면, array를 반환하면 됩니다. 채널, 프레즌스 채널, 비공개 채널 인스턴스를 자유롭게 조합해서 생성할 수 있습니다. 채널 인스턴스에 대해서는 이후에 더 자세히 다루겠습니다.

채널 인가하기

사용자가 비공개 채널을 청취(listen)하려면, 반드시 인가를 받아야 한다는 점을 기억해야 합니다. 애플리케이션의 routes/channels.php 파일에서 사용자가 특정 채널을 청취할 수 있는 권한이 있는지 검사하는 채널 인가 규칙을 정의할 수 있습니다. 이 예제에서는 orders.1 이라는 비공개 채널을 청취하려는 사용자가 해당 주문의 실제 생성자인지 검증해야 합니다.

use App\Models\Order; use App\Models\User; Broadcast::channel('orders.{orderId}', function (User $user, int $orderId) { return $user->id === Order::findOrNew($orderId)->user_id; });

channel 메서드는 두 개의 인자를 받습니다. 첫 번째는 채널의 이름이고, 두 번째는 사용자가 해당 채널을 청취할 권한이 있는지를 true 또는 false로 반환하는 콜백입니다.

모든 인가 콜백은 현재 인증된 사용자를 첫 번째 인자로 받고, 이후에 와일드카드 파라미터들을 받게 됩니다. 이 예제에서는 {orderId} 플레이스홀더를 사용해 채널 이름의 "ID" 부분이 와일드카드임을 나타냈습니다.

이벤트 브로드캐스트 청취하기

다음으로 남은 작업은 자바스크립트 애플리케이션에서 이벤트를 청취하는 것입니다. 이는 Laravel Echo를 사용해 처리할 수 있습니다. 먼저 private 메서드를 사용해 비공개 채널을 구독합니다. 그런 다음 listen 메서드를 사용해 OrderShipmentStatusUpdated 이벤트를 청취할 수 있습니다. 기본적으로 비공개 채널 이벤트의 모든 공개 속성은 브로드캐스트 이벤트에 포함됩니다.

Echo.private(`orders.${orderId}`) .listen('OrderShipmentStatusUpdated', (e) => { console.log(e.order); });

브로드캐스트 이벤트 정의하기

특정 이벤트가 브로드캐스트되어야 함을 Laravel에 알리려면, 해당 이벤트 클래스에 Illuminate\Contracts\Broadcasting\ShouldBroadcast 인터페이스를 구현해야 합니다. 이 인터페이스는 프레임워크에서 생성되는 모든 이벤트 클래스에 이미 임포트되어 있으므로, 원하는 이벤트에 손쉽게 추가할 수 있습니다.

ShouldBroadcast 인터페이스는 단일 메서드인 broadcastOn을 구현하도록 요구합니다. broadcastOn 메서드는 이벤트가 브로드캐스트되어야 할 채널 또는 채널들의 배열을 반환해야 합니다. 채널은 Channel, PrivateChannel, PresenceChannel의 인스턴스여야 합니다. Channel 인스턴스는 누구나 구독할 수 있는 공개 채널을 나타내며, PrivateChannelPresenceChannel채널 인가가 필요한 비공개 채널을 나타냅니다.

<?php namespace App\Events; use App\Models\User; use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Broadcasting\PresenceChannel; use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Queue\SerializesModels; class ServerCreated implements ShouldBroadcast { /** * 새로운 이벤트 인스턴스를 생성합니다. */ public function __construct( public User $user, ) {} /** * 이 이벤트가 브로드캐스트될 채널을 반환합니다. * * @return array<int, \Illuminate\Broadcasting\Channel> */ public function broadcastOn(): array { return [ new PrivateChannel('user.'.$this->user->id), ]; } }

ShouldBroadcast 인터페이스를 구현한 후에는, 평소처럼 이벤트를 발생시키기만 하면 됩니다. 이벤트가 발생하면, 큐에 등록된 작업이 지정된 브로드캐스트 드라이버를 이용해 이벤트를 자동으로 브로드캐스트합니다.

브로드캐스트 이름

기본적으로 Laravel은 이벤트의 클래스 이름을 사용해 이벤트를 브로드캐스트합니다. 하지만 이벤트 클래스에 broadcastAs 메서드를 정의하여 브로드캐스트 이름을 원하는 대로 커스터마이징할 수 있습니다.

/** * 이벤트의 브로드캐스트 이름입니다. */ public function broadcastAs(): string { return 'server.created'; }

broadcastAs 메서드를 사용해 브로드캐스트 이름을 커스터마이징하는 경우, 리스너를 등록할 때 이름 앞에 반드시 . 문자를 붙여야 합니다. 이렇게 하면 Echo가 이벤트에 애플리케이션의 네임스페이스를 자동으로 붙이지 않도록 지시할 수 있습니다.

.listen('.server.created', function (e) { .... });

브로드캐스트 데이터

이벤트가 브로드캐스트될 때, 해당 이벤트의 모든 public 속성이 자동으로 직렬화되어 이벤트의 페이로드로 브로드캐스트됩니다. 즉, 자바스크립트 애플리케이션에서 이벤트의 모든 공개 데이터에 접근할 수 있습니다. 예를 들어, 이벤트에 단일 public $user 속성이 있고 이 속성이 Eloquent 모델을 담고 있다면, 이벤트의 브로드캐스트 페이로드는 다음과 같습니다.

{ "user": { "id": 1, "name": "Patrick Stewart" ... } }

하지만 브로드캐스트 페이로드를 더 세밀하게 제어하고 싶다면, 이벤트에 broadcastWith 메서드를 추가할 수 있습니다. 이 메서드는 이벤트 페이로드로 브로드캐스트하고자 하는 데이터 배열을 반환해야 합니다.

/** * 브로드캐스트할 데이터를 반환합니다. * * @return array<string, mixed> */ public function broadcastWith(): array { return ['id' => $this->user->id]; }

브로드캐스트 큐

기본적으로 각 브로드캐스트 이벤트는 애플리케이션의 queue.php 설정 파일에 지정된 기본 큐 연결의 기본 큐에 등록됩니다. 브로드캐스터가 사용하는 큐 연결과 큐 이름은 이벤트 클래스에 connectionqueue 속성을 정의하여 커스터마이징할 수 있습니다.

/** * 이벤트 브로드캐스트 시 사용할 큐 연결의 이름입니다. * * @var string */ public $connection = 'redis'; /** * 브로드캐스트 작업이 위치할 큐의 이름입니다. * * @var string */ public $queue = 'default';

또는, 이벤트 클래스에 broadcastQueue 메서드를 정의하여 큐 이름을 커스터마이징할 수도 있습니다.

/** * 브로드캐스트 작업이 위치할 큐의 이름입니다. */ public function broadcastQueue(): string { return 'default'; }

기본 큐 드라이버 대신 sync 큐를 사용하여 이벤트를 브로드캐스트하고 싶다면, ShouldBroadcast 대신 ShouldBroadcastNow 인터페이스를 구현할 수 있습니다.

<?php use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow; class OrderShipmentStatusUpdated implements ShouldBroadcastNow { // ... }

브로드캐스트 조건

때로는 특정 조건이 참일 때만 이벤트를 브로드캐스트하고 싶은 경우가 있습니다. 이런 경우, 이벤트 클래스에 broadcastWhen 메서드를 추가해 조건을 정의할 수 있습니다.

/** * 이 이벤트를 브로드캐스트할지 여부를 결정합니다. */ public function broadcastWhen(): bool { return $this->order->value > 100; }

브로드캐스팅과 데이터베이스 트랜잭션

브로드캐스트 이벤트가 데이터베이스 트랜잭션 내부에서 디스패치될 경우, 트랜잭션이 커밋되기 전에 큐가 해당 이벤트를 처리해버릴 수 있습니다. 이런 상황이 발생하면, 트랜잭션 중에 모델이나 데이터베이스 레코드에 가한 변경 사항이 아직 데이터베이스에 반영되지 않은 상태일 수 있습니다. 또한 트랜잭션 내에서 생성된 모델이나 데이터베이스 레코드가 데이터베이스에 존재하지 않을 수도 있습니다. 만약 이벤트가 이러한 모델에 의존하고 있다면, 브로드캐스트 이벤트를 처리하는 작업이 실행될 때 예기치 않은 오류가 발생할 수 있습니다.

만약 애플리케이션의 큐 연결에 대해 after_commit 설정 옵션이 false로 지정되어 있다면, 특정 브로드캐스트 이벤트가 열려있는 모든 데이터베이스 트랜잭션이 커밋된 이후에 디스패치되도록 지정할 수 있습니다. 이를 위해 이벤트 클래스의 생성자에서 ShouldDispatchAfterCommit 인터페이스를 구현하면 됩니다.

<?php namespace App\Events; use App\Models\User; use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Broadcasting\PresenceChannel; use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Contracts\Events\ShouldDispatchAfterCommit; use Illuminate\Queue\SerializesModels; class ServerCreated implements ShouldBroadcast, ShouldDispatchAfterCommit { use SerializesModels; /** * 새로운 이벤트 인스턴스를 생성합니다. */ public function __construct( public User $user, ) {} }

NOTE

이러한 문제를 우회하는 방법에 대해 더 자세히 알고 싶다면 큐에 등록된 작업과 데이터베이스 트랜잭션에 대한 문서를 참고하세요.

브로드캐스팅

빠른 시작

Laravel 신규 애플리케이션에서는 기본적으로 브로드캐스팅 기능이 활성화되어 있지 않습니다. install:broadcasting Artisan 명령어를 실행하면 브로드캐스팅 기능을 활성화할 수 있습니다.

php artisan install:broadcasting

install:broadcasting 명령어를 실행하면 어떤 이벤트 브로드캐스팅 서비스를 사용할지 묻는 프롬프트가 나타납니다. 이 과정을 마치면 config/broadcasting.php 설정 파일과, 브로드캐스트 인가 라우트 및 콜백을 등록하는 routes/channels.php 파일이 생성됩니다.

Laravel은 기본적으로 여러 브로드캐스트 드라이버를 지원합니다: Laravel Reverb, Pusher Channels, Ably, Mercure, 그리고 로컬 개발과 디버깅을 위한 log 드라이버가 있습니다. 또한 테스트 중에 브로드캐스팅을 비활성화할 수 있는 null 드라이버도 포함되어 있습니다. config/broadcasting.php 설정 파일에는 이 드라이버들 각각에 대한 설정 예시가 포함되어 있습니다.

애플리케이션의 모든 이벤트 브로드캐스팅 설정은 config/broadcasting.php 설정 파일에 저장됩니다. 애플리케이션에 아직 이 파일이 없더라도 걱정할 필요는 없습니다. install:broadcasting Artisan 명령어를 실행하면 자동으로 생성됩니다.

다음 단계

이벤트 브로드캐스팅을 활성화했다면, 이제 브로드캐스트 이벤트 정의하기이벤트 리스닝하기에 대해 더 자세히 알아볼 차례입니다. React, Vue, Svelte용 Laravel 스타터 키트를 사용 중이라면, Echo의 useEcho 훅을 사용해 이벤트를 손쉽게 수신할 수 있습니다.

NOTE

이벤트를 브로드캐스팅하기 전에 먼저 큐 워커를 설정하고 실행해두어야 합니다. 모든 이벤트 브로드캐스팅은 큐에 등록된 Job을 통해 처리되므로, 이벤트를 브로드캐스팅하더라도 애플리케이션의 응답 속도에 큰 영향을 주지 않습니다.

서버 사이드 설치

Laravel의 이벤트 브로드캐스팅 기능을 사용하려면 애플리케이션 내에서 몇 가지 설정 작업과 패키지 설치가 필요합니다.

이벤트 브로드캐스팅은 서버 측 브로드캐스팅 드라이버가 Laravel 이벤트를 외부로 전송하고, 브라우저 클라이언트에서는 Laravel Echo(자바스크립트 라이브러리)가 이를 수신하는 방식으로 동작합니다. 다소 복잡해 보일 수 있지만, 설치 과정을 단계별로 하나씩 살펴보겠습니다.

Reverb

Reverb를 이벤트 브로드캐스터로 사용하면서 Laravel의 브로드캐스팅 기능을 빠르게 활성화하려면, install:broadcasting Artisan 명령어를 --reverb 옵션과 함께 실행하세요. 이 명령어는 Reverb에 필요한 Composer 및 NPM 패키지를 설치하고, 애플리케이션의 .env 파일에 필요한 환경 변수를 자동으로 추가해줍니다:

php artisan install:broadcasting --reverb

수동 설치

install:broadcasting 명령어를 실행하면 Laravel Reverb 설치 여부를 묻는 프롬프트가 표시됩니다. 물론 Composer 패키지 매니저를 이용해 Reverb를 직접 수동으로 설치할 수도 있습니다:

composer require laravel/reverb

패키지 설치가 끝나면 Reverb의 설치 명령어를 실행해 설정 파일을 배포하고, 필요한 환경 변수를 추가하고, 애플리케이션에서 이벤트 브로드캐스팅을 활성화할 수 있습니다:

php artisan reverb:install

Reverb 설치 및 사용에 관한 자세한 내용은 Reverb 문서를 참고하세요.

Pusher Channels

Pusher를 이벤트 브로드캐스터로 사용하면서 Laravel의 브로드캐스팅 기능을 빠르게 활성화하려면, install:broadcasting Artisan 명령어를 --pusher 옵션과 함께 실행하세요. 이 명령어는 Pusher 자격 증명을 입력하도록 안내하고, Pusher PHP 및 자바스크립트 SDK를 설치한 뒤, 애플리케이션의 .env 파일에 필요한 환경 변수를 자동으로 추가해줍니다:

php artisan install:broadcasting --pusher

수동 설치

Pusher를 수동으로 설치하려면 Composer 패키지 매니저를 이용해 Pusher Channels PHP SDK를 설치해야 합니다:

composer require pusher/pusher-php-server

그다음, config/broadcasting.php 설정 파일에서 Pusher Channels 자격 증명을 설정해야 합니다. 이 파일에는 이미 Pusher Channels 설정 예시가 포함되어 있어, key, secret, application ID를 손쉽게 지정할 수 있습니다. 일반적으로 Pusher Channels 자격 증명은 애플리케이션의 .env 파일에서 설정합니다:

PUSHER_APP_ID="your-pusher-app-id" PUSHER_APP_KEY="your-pusher-key" PUSHER_APP_SECRET="your-pusher-secret" PUSHER_HOST= PUSHER_PORT=443 PUSHER_SCHEME="https" PUSHER_APP_CLUSTER="mt1"

config/broadcasting.php 파일의 pusher 설정에서는 클러스터(cluster) 등 Channels가 지원하는 추가 options도 지정할 수 있습니다.

이어서 애플리케이션의 .env 파일에서 BROADCAST_CONNECTION 환경 변수를 pusher로 설정합니다:

BROADCAST_CONNECTION=pusher

마지막으로 클라이언트 측에서 브로드캐스트 이벤트를 수신할 Laravel Echo를 설치하고 설정하면 됩니다.

Ably

NOTE

아래 문서는 Ably를 "Pusher 호환" 모드로 사용하는 방법을 다룹니다. 다만 Ably 팀은 Ably만의 고유한 기능을 온전히 활용할 수 있는 별도의 브로드캐스터와 Echo 클라이언트를 자체적으로 개발하고 유지 관리하고 있으니, 이를 사용하고 싶다면 Ably의 Laravel 브로드캐스터 문서를 참고하시기 바랍니다.

Ably를 이벤트 브로드캐스터로 사용하면서 Laravel의 브로드캐스팅 기능을 빠르게 활성화하려면, install:broadcasting Artisan 명령어를 --ably 옵션과 함께 실행하세요. 이 명령어는 Ably 자격 증명을 입력하도록 안내하고, Ably PHP 및 자바스크립트 SDK를 설치한 뒤, 애플리케이션의 .env 파일에 필요한 환경 변수를 자동으로 추가해줍니다:

php artisan install:broadcasting --ably

계속 진행하기 전에, Ably 애플리케이션 설정에서 Pusher 프로토콜 지원 기능을 반드시 활성화해야 합니다. 이 옵션은 Ably 애플리케이션 설정 대시보드의 "Protocol Adapter Settings" 항목에서 활성화할 수 있습니다.

수동 설치

Ably를 수동으로 설치하려면 Composer 패키지 매니저를 이용해 Ably PHP SDK를 설치해야 합니다:

composer require ably/ably-php

그다음, config/broadcasting.php 설정 파일에서 Ably 자격 증명을 설정해야 합니다. 이 파일에는 이미 Ably 설정 예시가 포함되어 있어 key 값을 손쉽게 지정할 수 있습니다. 일반적으로 이 값은 ABLY_KEY 환경 변수를 통해 설정합니다:

ABLY_KEY=your-ably-key

이어서 애플리케이션의 .env 파일에서 BROADCAST_CONNECTION 환경 변수를 ably로 설정합니다:

BROADCAST_CONNECTION=ably

마지막으로 클라이언트 측에서 브로드캐스트 이벤트를 수신할 Laravel Echo를 설치하고 설정하면 됩니다.

Mercure

Mercure는 서버 전송 이벤트(Server-Sent Events)를 활용하는 실시간 프로토콜입니다. Mercure 허브를 통해 이벤트를 브로드캐스트하려면, 애플리케이션의 .env 파일에서 mercure 커넥션을 설정하세요:

BROADCAST_CONNECTION=mercure MERCURE_URL=https://mercure.example.com/.well-known/mercure MERCURE_PUBLIC_URL=https://mercure.example.com/.well-known/mercure MERCURE_JWT_SECRET=<your-mercure-jwt-secret>

MERCURE_URL 값은 Laravel이 업데이트를 게시(publish)할 때 사용하는 URL이며, MERCURE_PUBLIC_URL은 브라우저 클라이언트가 구독(subscribe)할 때 사용하는 URL입니다. Mercure 허브도 동일한 JWT secret으로 설정되어 있어야 합니다.

종단 간 암호화(end-to-end encryption)가 적용된 프라이빗 채널을 사용하려면, 32바이트 길이의 MERCURE_ENCRYPTION_KEY 환경 변수를 설정하세요:

MERCURE_ENCRYPTION_KEY=<your-32-byte-encryption-key>

NOTE

Reverb, Pusher, Ably, Mercure 중 어떤 드라이버를 선택하든 핵심 개념은 동일합니다. 서버가 이벤트를 특정 채널로 브로드캐스트하면, 클라이언트는 Echo를 통해 해당 채널을 구독해 실시간으로 데이터를 받습니다. 드라이버는 이 "배달" 방식의 차이일 뿐이므로, 프로젝트 규모나 인프라 환경(자체 호스팅 여부, 관리형 서비스 선호 여부 등)에 맞춰 선택하면 됩니다.

클라이언트 사이드 설치

Reverb

Laravel Echo는 서버 측 브로드캐스팅 드라이버가 전송하는 이벤트를 채널을 통해 손쉽게 구독하고 수신할 수 있게 해주는 자바스크립트 라이브러리입니다.

install:broadcasting Artisan 명령어로 Laravel Reverb를 설치하면 Reverb와 Echo에 필요한 스캐폴딩 및 설정이 애플리케이션에 자동으로 반영됩니다. 하지만 Laravel Echo를 직접 수동으로 설정하고 싶다면 아래 안내를 따르면 됩니다.

수동 설치

애플리케이션 프런트엔드에 Laravel Echo를 수동으로 설정하려면, 먼저 pusher-js 패키지를 설치해야 합니다. Reverb는 WebSocket 구독, 채널, 메시지 전송에 Pusher 프로토콜을 사용하기 때문입니다.

npm install --save-dev laravel-echo pusher-js

Echo 설치가 끝나면 애플리케이션의 자바스크립트 코드 안에서 새로운 Echo 인스턴스를 생성할 준비가 된 것입니다. Laravel 프레임워크에 기본 포함된 resources/js/app.js 파일 하단에 아래 코드를 추가하면 좋습니다.

JavaScript

import Echo from 'laravel-echo'; import Pusher from 'pusher-js'; window.Pusher = Pusher; window.Echo = new Echo({ broadcaster: 'reverb', key: import.meta.env.VITE_REVERB_APP_KEY, wsHost: import.meta.env.VITE_REVERB_HOST, wsPort: import.meta.env.VITE_REVERB_PORT ?? 80, wssPort: import.meta.env.VITE_REVERB_PORT ?? 443, forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https', enabledTransports: ['ws', 'wss'], });

React

import { configureEcho } from "@laravel/echo-react"; configureEcho({ broadcaster: "reverb", // key: import.meta.env.VITE_REVERB_APP_KEY, // wsHost: import.meta.env.VITE_REVERB_HOST, // wsPort: import.meta.env.VITE_REVERB_PORT, // wssPort: import.meta.env.VITE_REVERB_PORT, // forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https', // enabledTransports: ['ws', 'wss'], });

Vue

import { configureEcho } from "@laravel/echo-vue"; configureEcho({ broadcaster: "reverb", // key: import.meta.env.VITE_REVERB_APP_KEY, // wsHost: import.meta.env.VITE_REVERB_HOST, // wsPort: import.meta.env.VITE_REVERB_PORT, // wssPort: import.meta.env.VITE_REVERB_PORT, // forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https', // enabledTransports: ['ws', 'wss'], });

Svelte

import { configureEcho } from "@laravel/echo-svelte"; configureEcho({ broadcaster: "reverb", // key: import.meta.env.VITE_REVERB_APP_KEY, // wsHost: import.meta.env.VITE_REVERB_HOST, // wsPort: import.meta.env.VITE_REVERB_PORT, // wssPort: import.meta.env.VITE_REVERB_PORT, // forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https', // enabledTransports: ['ws', 'wss'], });

이제 애플리케이션의 에셋을 컴파일합니다.

npm run build

WARNING

Laravel Echo의 reverb 브로드캐스터를 사용하려면 laravel-echo v1.16.0 이상이 필요합니다.

Pusher Channels

Laravel Echo는 서버 측 브로드캐스팅 드라이버가 전송하는 이벤트를 채널을 통해 손쉽게 구독하고 수신할 수 있게 해주는 자바스크립트 라이브러리입니다.

install:broadcasting --pusher Artisan 명령어로 브로드캐스팅 기능을 설치하면 Pusher와 Echo에 필요한 스캐폴딩 및 설정이 애플리케이션에 자동으로 반영됩니다. 하지만 Laravel Echo를 직접 수동으로 설정하고 싶다면 아래 안내를 따르면 됩니다.

수동 설치

애플리케이션 프런트엔드에 Laravel Echo를 수동으로 설정하려면, 먼저 WebSocket 구독·채널·메시지 전송에 Pusher 프로토콜을 사용하는 laravel-echopusher-js 패키지를 설치해야 합니다.

npm install --save-dev laravel-echo pusher-js

Echo 설치가 끝나면 애플리케이션의 resources/js/app.js 파일 안에서 새로운 Echo 인스턴스를 생성할 준비가 된 것입니다.

JavaScript

import Echo from 'laravel-echo'; import Pusher from 'pusher-js'; window.Pusher = Pusher; window.Echo = new Echo({ broadcaster: 'pusher', key: import.meta.env.VITE_PUSHER_APP_KEY, cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER, forceTLS: true });

React

import { configureEcho } from "@laravel/echo-react"; configureEcho({ broadcaster: "pusher", // key: import.meta.env.VITE_PUSHER_APP_KEY, // cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER, // forceTLS: true, // wsHost: import.meta.env.VITE_PUSHER_HOST, // wsPort: import.meta.env.VITE_PUSHER_PORT, // wssPort: import.meta.env.VITE_PUSHER_PORT, // enabledTransports: ["ws", "wss"], });

Vue

import { configureEcho } from "@laravel/echo-vue"; configureEcho({ broadcaster: "pusher", // key: import.meta.env.VITE_PUSHER_APP_KEY, // cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER, // forceTLS: true, // wsHost: import.meta.env.VITE_PUSHER_HOST, // wsPort: import.meta.env.VITE_PUSHER_PORT, // wssPort: import.meta.env.VITE_PUSHER_PORT, // enabledTransports: ["ws", "wss"], });

Svelte

import { configureEcho } from "@laravel/echo-svelte"; configureEcho({ broadcaster: "pusher", // key: import.meta.env.VITE_PUSHER_APP_KEY, // cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER, // forceTLS: true, // wsHost: import.meta.env.VITE_PUSHER_HOST, // wsPort: import.meta.env.VITE_PUSHER_PORT, // wssPort: import.meta.env.VITE_PUSHER_PORT, // enabledTransports: ["ws", "wss"], });

다음으로, 애플리케이션의 .env 파일에 Pusher 관련 환경 변수 값을 적절히 설정합니다. 만약 아래 변수들이 .env 파일에 없다면 새로 추가해야 합니다.

PUSHER_APP_ID="your-pusher-app-id" PUSHER_APP_KEY="your-pusher-key" PUSHER_APP_SECRET="your-pusher-secret" PUSHER_HOST= PUSHER_PORT=443 PUSHER_SCHEME="https" PUSHER_APP_CLUSTER="mt1" VITE_APP_NAME="${APP_NAME}" VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}" VITE_PUSHER_HOST="${PUSHER_HOST}" VITE_PUSHER_PORT="${PUSHER_PORT}" VITE_PUSHER_SCHEME="${PUSHER_SCHEME}" VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

애플리케이션에 맞게 Echo 설정을 조정했다면, 에셋을 컴파일합니다.

npm run build

NOTE

자바스크립트 에셋 컴파일에 대해 더 알고 싶다면 Vite 문서를 참고하세요.

기존 클라이언트 인스턴스 사용하기

이미 미리 구성해둔 Pusher Channels 클라이언트 인스턴스가 있고 이를 Echo에서 그대로 사용하고 싶다면, client 설정 옵션을 통해 전달할 수 있습니다.

import Echo from 'laravel-echo'; import Pusher from 'pusher-js'; const options = { broadcaster: 'pusher', key: import.meta.env.VITE_PUSHER_APP_KEY } window.Echo = new Echo({ ...options, client: new Pusher(options.key, options) });

Ably

NOTE

아래 문서는 Ably를 "Pusher 호환" 모드로 사용하는 방법을 설명합니다. 다만 Ably 팀은 Ably 고유 기능을 최대한 활용할 수 있는 자체 브로드캐스터와 Echo 클라이언트를 별도로 권장 및 관리하고 있습니다. Ably가 직접 관리하는 드라이버에 대해 더 알고 싶다면 Ably의 Laravel 브로드캐스터 문서를 참고하세요.

Laravel Echo는 서버 측 브로드캐스팅 드라이버가 전송하는 이벤트를 채널을 통해 손쉽게 구독하고 수신할 수 있게 해주는 자바스크립트 라이브러리입니다.

install:broadcasting --ably Artisan 명령어로 브로드캐스팅 기능을 설치하면 Ably와 Echo에 필요한 스캐폴딩 및 설정이 애플리케이션에 자동으로 반영됩니다. 하지만 Laravel Echo를 직접 수동으로 설정하고 싶다면 아래 안내를 따르면 됩니다.

수동 설치

애플리케이션 프런트엔드에 Laravel Echo를 수동으로 설정하려면, 먼저 WebSocket 구독·채널·메시지 전송에 Pusher 프로토콜을 사용하는 laravel-echopusher-js 패키지를 설치해야 합니다.

npm install --save-dev laravel-echo pusher-js

계속 진행하기 전에, Ably 애플리케이션 설정에서 Pusher 프로토콜 지원 기능을 활성화해야 합니다. 이 기능은 Ably 애플리케이션 설정 대시보드의 "Protocol Adapter Settings" 항목에서 활성화할 수 있습니다.

Echo 설치가 끝나면 애플리케이션의 resources/js/app.js 파일 안에서 새로운 Echo 인스턴스를 생성할 준비가 된 것입니다.

JavaScript

import Echo from 'laravel-echo'; import Pusher from 'pusher-js'; window.Pusher = Pusher; window.Echo = new Echo({ broadcaster: 'pusher', key: import.meta.env.VITE_ABLY_PUBLIC_KEY, wsHost: 'realtime-pusher.ably.io', wsPort: 443, disableStats: true, encrypted: true, });

React

import { configureEcho } from "@laravel/echo-react"; configureEcho({ broadcaster: "ably", // key: import.meta.env.VITE_ABLY_PUBLIC_KEY, // wsHost: "realtime-pusher.ably.io", // wsPort: 443, // disableStats: true, // encrypted: true, });

Vue

import { configureEcho } from "@laravel/echo-vue"; configureEcho({ broadcaster: "ably", // key: import.meta.env.VITE_ABLY_PUBLIC_KEY, // wsHost: "realtime-pusher.ably.io", // wsPort: 443, // disableStats: true, // encrypted: true, });

Svelte

import { configureEcho } from "@laravel/echo-svelte"; configureEcho({ broadcaster: "ably", // key: import.meta.env.VITE_ABLY_PUBLIC_KEY, // wsHost: "realtime-pusher.ably.io", // wsPort: 443, // disableStats: true, // encrypted: true, });

위 예시의 Ably Echo 설정에서 VITE_ABLY_PUBLIC_KEY라는 환경 변수를 참조하고 있는 것을 확인할 수 있습니다. 이 변수의 값은 Ably의 퍼블릭 키(public key)여야 합니다. 퍼블릭 키는 Ably 키 값에서 : 문자 앞부분에 해당하는 부분입니다.

필요에 맞게 Echo 설정을 조정했다면, 에셋을 컴파일합니다.

npm run dev

NOTE

자바스크립트 에셋 컴파일에 대해 더 알고 싶다면 Vite 문서를 참고하세요.

Mercure

Laravel Echo와 함께 Mercure를 사용하려면 laravel-echo 패키지를 설치합니다.

npm install --save-dev laravel-echo

그다음 mercure 브로드캐스터를 사용하는 Echo 인스턴스를 생성합니다. host 옵션의 기본값은 현재 origin의 /.well-known/mercure 경로입니다.

JavaScript

import Echo from 'laravel-echo'; window.Echo = new Echo({ broadcaster: 'mercure', host: import.meta.env.VITE_MERCURE_HUB_URL, });

React

import { configureEcho } from "@laravel/echo-react"; configureEcho({ broadcaster: "mercure", });

Vue

import { configureEcho } from "@laravel/echo-vue"; configureEcho({ broadcaster: "mercure", });

Svelte

import { configureEcho } from "@laravel/echo-svelte"; configureEcho({ broadcaster: "mercure", });

.env 파일에 허브 URL을 정의합니다.

VITE_MERCURE_HUB_URL="${MERCURE_PUBLIC_URL}"

브로드캐스팅

개념 개요

Laravel의 이벤트 브로드캐스팅 기능을 사용하면 서버 사이드에서 발생한 Laravel 이벤트를 클라이언트 사이드 자바스크립트 애플리케이션으로 실시간 전송할 수 있습니다. 여러 드라이버 중 선택할 수 있는 구조이며, 현재 Laravel은 Laravel Reverb, Pusher Channels, Ably, Mercure 드라이버를 기본으로 제공합니다. 클라이언트 측에서는 Laravel Echo 자바스크립트 패키지를 사용해 이러한 이벤트를 손쉽게 수신할 수 있습니다.

이벤트는 "채널"을 통해 브로드캐스트되며, 채널은 공개(public) 또는 비공개(private)로 지정할 수 있습니다. 공개 채널은 인증이나 인가 없이 누구나 구독할 수 있지만, 비공개 채널을 구독하려면 사용자가 인증되어 있어야 하고 해당 채널을 청취할 권한이 있어야 합니다.

NOTE

예를 들어 실시간 채팅, 알림, 주문 배송 현황처럼 "새로고침 없이 화면이 즉시 갱신되어야 하는 기능"을 만들 때 브로드캐스팅이 유용합니다. 폴링(polling)으로 서버에 반복 요청을 보내는 대신, 서버가 변경 사항을 능동적으로 밀어주는(push) 방식이라고 이해하면 됩니다.

예제 애플리케이션으로 살펴보기

이벤트 브로드캐스팅을 구성하는 각 요소를 하나씩 살펴보기 전에, 쇼핑몰 애플리케이션을 예로 들어 전체 흐름을 먼저 훑어보겠습니다.

애플리케이션에 사용자가 자신의 주문 배송 상태를 확인할 수 있는 페이지가 있다고 가정해봅시다. 그리고 애플리케이션이 배송 상태 업데이트를 처리할 때 OrderShipmentStatusUpdated 이벤트가 발생한다고 해봅시다.

use App\Events\OrderShipmentStatusUpdated; OrderShipmentStatusUpdated::dispatch($order);

`ShouldBroadcast` 인터페이스

사용자가 자신의 주문 페이지를 보고 있을 때, 상태 업데이트를 확인하기 위해 매번 페이지를 새로고침하게 만들고 싶지는 않을 것입니다. 대신 상태가 갱신되는 즉시 이를 애플리케이션으로 브로드캐스트하고자 합니다. 이를 위해서는 OrderShipmentStatusUpdated 이벤트에 ShouldBroadcast 인터페이스를 구현해야 합니다. 이렇게 하면 이벤트가 발생(dispatch)될 때 Laravel이 자동으로 해당 이벤트를 브로드캐스트합니다.

<?php namespace App\Events; use App\Models\Order; use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Broadcasting\PresenceChannel; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Queue\SerializesModels; class OrderShipmentStatusUpdated implements ShouldBroadcast { /** * 주문 인스턴스. * * @var \App\Models\Order */ public $order; }

ShouldBroadcast 인터페이스를 구현하려면 이벤트 클래스에 broadcastOn 메서드를 정의해야 합니다. 이 메서드는 이벤트가 브로드캐스트될 채널을 반환하는 역할을 합니다. Artisan으로 이벤트 클래스를 생성하면 이 메서드의 빈 틀이 이미 만들어져 있으므로, 세부 내용만 채우면 됩니다. 이 예제에서는 주문을 생성한 당사자만 상태 업데이트를 볼 수 있어야 하므로, 해당 주문에 연결된 비공개 채널로 이벤트를 브로드캐스트합니다.

use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\PrivateChannel; /** * 이벤트가 브로드캐스트될 채널을 반환합니다. */ public function broadcastOn(): Channel { return new PrivateChannel('orders.'.$this->order->id); }

여러 채널에 이벤트를 브로드캐스트하고 싶다면 배열(array)을 반환하면 됩니다.

use Illuminate\Broadcasting\PrivateChannel; /** * 이벤트가 브로드캐스트될 채널 목록을 반환합니다. * * @return array<int, \Illuminate\Broadcasting\Channel> */ public function broadcastOn(): array { return [ new PrivateChannel('orders.'.$this->order->id), // ... ]; }

채널 인가(authorization) 처리하기

앞서 언급했듯이, 사용자는 비공개 채널을 청취하려면 반드시 인가를 받아야 합니다. 채널 인가 규칙은 애플리케이션의 routes/channels.php 파일에 정의합니다. 이 예제에서는 비공개 채널 orders.1을 구독하려는 사용자가 실제로 해당 주문을 생성한 본인인지 검증해야 합니다.

use App\Models\Order; use App\Models\User; Broadcast::channel('orders.{orderId}', function (User $user, int $orderId) { return $user->id === Order::findOrNew($orderId)->user_id; });

channel 메서드는 두 개의 인자를 받습니다. 첫 번째는 채널 이름이고, 두 번째는 사용자가 해당 채널을 청취할 권한이 있는지를 true 또는 false로 반환하는 콜백입니다.

모든 인가 콜백은 첫 번째 인자로 현재 인증된 사용자를 받고, 그 뒤로 채널 이름에 포함된 와일드카드 파라미터들을 순서대로 전달받습니다. 위 예제에서는 {orderId} 플레이스홀더를 사용해 채널 이름의 "ID" 부분이 와일드카드임을 나타내고 있습니다.

브로드캐스트된 이벤트 수신하기

이제 남은 작업은 자바스크립트 애플리케이션에서 이 이벤트를 수신하는 것뿐입니다. Laravel Echo를 사용하면 됩니다. Laravel Echo가 기본 제공하는 React, Vue, Svelte용 훅(hook)을 사용하면 손쉽게 시작할 수 있으며, 기본적으로 이벤트의 모든 public 속성이 브로드캐스트되는 이벤트 데이터에 포함됩니다.

React

import { useEcho } from "@laravel/echo-react"; useEcho( `orders.${orderId}`, "OrderShipmentStatusUpdated", (e) => { console.log(e.order); }, );

Vue

<script setup lang="ts"> import { useEcho } from "@laravel/echo-vue"; useEcho( `orders.${orderId}`, "OrderShipmentStatusUpdated", (e) => { console.log(e.order); }, ); </script>

Svelte

<script> import { useEcho } from "@laravel/echo-svelte"; useEcho( `orders.${orderId}`, "OrderShipmentStatusUpdated", (e) => { console.log(e.order); }, ); </script>

전체 흐름을 정리하면 다음과 같습니다.

브로드캐스팅

이벤트를 브로드캐스트 대상으로 정의하기

특정 이벤트를 브로드캐스트하도록 Laravel에 알리려면, 해당 이벤트 클래스에 Illuminate\Contracts\Broadcasting\ShouldBroadcast 인터페이스를 구현해야 합니다. 이 인터페이스는 프레임워크가 생성하는 모든 이벤트 클래스에 이미 임포트되어 있으므로, 원하는 이벤트에 손쉽게 추가할 수 있습니다.

ShouldBroadcast 인터페이스를 구현하려면 broadcastOn 메서드 하나만 정의하면 됩니다. broadcastOn 메서드는 이벤트가 브로드캐스트될 채널(또는 채널 배열)을 반환해야 합니다. 여기서 채널은 Channel, PrivateChannel, PresenceChannel 인스턴스여야 합니다. Channel은 누구나 구독할 수 있는 공개 채널을 나타내며, PrivateChannelPresenceChannel채널 인가가 필요한 비공개 채널을 나타냅니다:

<?php namespace App\Events; use App\Models\User; use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Broadcasting\PresenceChannel; use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Queue\SerializesModels; class ServerCreated implements ShouldBroadcast { use SerializesModels; /** * 새 이벤트 인스턴스를 생성합니다. */ public function __construct( public User $user, ) {} /** * 이벤트가 브로드캐스트될 채널을 반환합니다. * * @return array<int, \Illuminate\Broadcasting\Channel> */ public function broadcastOn(): array { return [ new PrivateChannel('user.'.$this->user->id), ]; } }

ShouldBroadcast 인터페이스를 구현했다면, 이제 평소처럼 이벤트를 발생시키기만 하면 됩니다. 이벤트가 발생하면 큐에 등록된 Job이 자동으로 지정된 브로드캐스트 드라이버를 사용해 이벤트를 브로드캐스트합니다.

NOTE

이벤트 브로드캐스트는 큐 Job으로 처리되므로, 채널 이름에 오타가 있거나 인가 로직에 문제가 있어도 즉시 에러가 발생하지 않고 조용히 실패할 수 있습니다. 프론트엔드에서 이벤트가 수신되지 않는다면 먼저 큐 워커 로그와 채널 인가 설정을 확인해 보세요.

브로드캐스트 이름

기본적으로 Laravel은 이벤트 클래스명을 브로드캐스트 이름으로 사용합니다. 하지만 이벤트에 broadcastAs 메서드를 정의하면 브로드캐스트 이름을 원하는 대로 지정할 수 있습니다:

/** * 이벤트의 브로드캐스트 이름을 반환합니다. */ public function broadcastAs(): string { return 'server.created'; }

broadcastAs 메서드로 브로드캐스트 이름을 커스터마이징했다면, 리스너를 등록할 때 이름 앞에 .을 반드시 붙여야 합니다. 이렇게 하면 Echo가 애플리케이션 네임스페이스를 이벤트 이름 앞에 붙이지 않도록 지시할 수 있습니다:

.listen('.server.created', function (e) { // ... });

브로드캐스트 데이터

이벤트가 브로드캐스트되면, 해당 이벤트의 모든 public 프로퍼티가 자동으로 직렬화되어 이벤트 페이로드로 브로드캐스트됩니다. 이를 통해 JavaScript 애플리케이션에서 공개된 데이터에 자유롭게 접근할 수 있습니다. 예를 들어, 이벤트에 Eloquent 모델을 담은 $user라는 public 프로퍼티가 하나 있다면, 브로드캐스트 페이로드는 다음과 같습니다:

{ "user": { "id": 1, "name": "홍길동" ... } }

다만 브로드캐스트 페이로드를 좀 더 세밀하게 제어하고 싶다면, 이벤트에 broadcastWith 메서드를 추가하면 됩니다. 이 메서드는 이벤트 페이로드로 브로드캐스트할 데이터 배열을 반환해야 합니다:

/** * 브로드캐스트할 데이터를 반환합니다. * * @return array<string, mixed> */ public function broadcastWith(): array { return ['id' => $this->user->id]; }

브로드캐스트 큐

기본적으로 각 브로드캐스트 이벤트는 queue.php 설정 파일에 지정된 기본 큐 커넥션의 기본 큐에 등록됩니다. 이벤트 클래스에 ConnectionQueue 어트리뷰트를 사용하면 브로드캐스터가 사용할 큐 커넥션과 큐 이름을 커스터마이징할 수 있습니다:

use Illuminate\Queue\Attributes\Connection; use Illuminate\Queue\Attributes\Queue; #[Connection('redis')] #[Queue('default')] class ServerCreated implements ShouldBroadcast { // ... }

또는 이벤트에 broadcastQueue 메서드를 정의해서 큐 이름을 지정할 수도 있습니다:

/** * 브로드캐스트 Job을 등록할 큐 이름을 반환합니다. */ public function broadcastQueue(): string { return 'default'; }

각 이벤트 클래스를 일일이 커스터마이징하지 않고 모든 브로드캐스트 이벤트가 동일한 큐를 사용하도록 하고 싶다면, ShouldBroadcast 컨트랙트를 특정 큐로 라우팅하는 방법도 있습니다.

이벤트를 기본 큐 드라이버 대신 sync 큐를 통해 즉시 브로드캐스트하고 싶다면, ShouldBroadcast 대신 ShouldBroadcastNow 인터페이스를 구현하면 됩니다:

<?php namespace App\Events; use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow; class OrderShipmentStatusUpdated implements ShouldBroadcastNow { // ... }

브로드캐스트 조건

특정 조건이 참일 때만 이벤트를 브로드캐스트하고 싶은 경우가 있습니다. 이벤트 클래스에 broadcastWhen 메서드를 추가하여 이러한 조건을 정의할 수 있습니다:

/** * 이벤트를 브로드캐스트할지 여부를 결정합니다. */ public function broadcastWhen(): bool { return $this->order->value > 100; }

브로드캐스팅과 데이터베이스 트랜잭션

데이터베이스 트랜잭션 내부에서 브로드캐스트 이벤트를 디스패치하면, 트랜잭션이 커밋되기 전에 큐가 해당 이벤트를 먼저 처리해버릴 수 있습니다. 이 경우 트랜잭션 안에서 모델이나 데이터베이스 레코드에 가한 변경 사항이 아직 데이터베이스에 반영되지 않았을 수 있습니다. 또한 트랜잭션 내에서 새로 생성한 모델이나 레코드가 데이터베이스에 아직 존재하지 않을 수도 있습니다. 만약 이벤트가 이러한 모델에 의존한다면, 브로드캐스트 Job이 처리되는 시점에 예기치 않은 오류가 발생할 수 있습니다.

큐 커넥션의 after_commit 설정 옵션이 false로 되어 있더라도, 특정 브로드캐스트 이벤트만큼은 열려 있는 모든 데이터베이스 트랜잭션이 커밋된 이후에 디스패치되도록 지정하고 싶다면, 이벤트 클래스에 ShouldDispatchAfterCommit 인터페이스를 구현하면 됩니다:

<?php namespace App\Events; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Contracts\Events\ShouldDispatchAfterCommit; use Illuminate\Queue\SerializesModels; class ServerCreated implements ShouldBroadcast, ShouldDispatchAfterCommit { use SerializesModels; }

NOTE

이러한 문제를 해결하는 방법에 대해 더 자세히 알고 싶다면 큐 작업과 데이터베이스 트랜잭션 문서를 참고하세요.

채널 인가

프라이빗 채널은 현재 인증된 사용자가 해당 채널을 실제로 구독(수신)할 권한이 있는지 인가받는 과정이 필요합니다. 이 과정은 채널 이름을 담아 Laravel 애플리케이션에 HTTP 요청을 보내고, 애플리케이션이 해당 사용자가 그 채널을 구독할 수 있는지 판단하는 방식으로 이루어집니다. Laravel Echo를 사용한다면 프라이빗 채널 구독을 인가받기 위한 HTTP 요청은 자동으로 이루어집니다.

브로드캐스팅을 설치하면 Laravel은 인가 요청을 처리하기 위해 /broadcasting/auth 라우트를 자동으로 등록하려고 시도합니다. 만약 이 라우트가 자동으로 등록되지 않았다면, 애플리케이션의 /bootstrap/app.php 파일에서 직접 등록할 수 있습니다:

->withRouting( web: __DIR__.'/../routes/web.php', channels: __DIR__.'/../routes/channels.php', health: '/up', )

인가 콜백 정의하기

다음으로, 현재 인증된 사용자가 특정 채널을 구독할 수 있는지 실제로 판단하는 로직을 정의해야 합니다. 이 작업은 install:broadcasting Artisan 명령어로 생성된 routes/channels.php 파일에서 이루어집니다. 이 파일에서 Broadcast::channel 메서드를 사용해 채널 인가 콜백을 등록할 수 있습니다:

use App\Models\User; Broadcast::channel('orders.{orderId}', function (User $user, int $orderId) { return $user->id === Order::findOrNew($orderId)->user_id; });

channel 메서드는 두 개의 인자를 받습니다: 채널 이름과, 사용자가 해당 채널을 구독할 권한이 있는지를 true 또는 false로 반환하는 콜백입니다.

모든 인가 콜백은 첫 번째 인자로 현재 인증된 사용자를 받고, 그 이후 인자로 와일드카드 파라미터들을 전달받습니다. 위 예제에서는 {orderId} 플레이스홀더를 사용해서 채널 이름 중 "ID" 부분이 와일드카드임을 나타내고 있습니다.

애플리케이션에 등록된 브로드캐스트 인가 콜백 목록은 channel:list Artisan 명령어로 확인할 수 있습니다:

php artisan channel:list

인가 콜백에서의 모델 바인딩

HTTP 라우트와 마찬가지로, 채널 라우트에서도 암시적/명시적 라우트 모델 바인딩을 활용할 수 있습니다. 예를 들어, 문자열이나 숫자 형태의 주문 ID를 받는 대신, 실제 Order 모델 인스턴스를 요청받도록 만들 수 있습니다:

use App\Models\Order; use App\Models\User; Broadcast::channel('orders.{order}', function (User $user, Order $order) { return $user->id === $order->user_id; });

WARNING

HTTP 라우트 모델 바인딩과 달리, 채널 모델 바인딩은 자동 암시적 모델 바인딩 스코핑을 지원하지 않습니다. 다만 대부분의 채널은 단일 모델의 고유한 기본 키를 기준으로 스코프를 지정할 수 있기 때문에, 이로 인해 문제가 발생하는 경우는 거의 없습니다.

인가 콜백의 인증 방식

프라이빗 채널과 presence 채널은 애플리케이션의 기본 인증 가드를 통해 현재 사용자를 인증합니다. 사용자가 인증되지 않은 상태라면 채널 인가는 자동으로 거부되며, 인가 콜백 자체가 실행되지 않습니다. 필요하다면 요청을 인증할 여러 개의 커스텀 가드를 지정할 수도 있습니다:

Broadcast::channel('channel', function () { // ... }, ['guards' => ['web', 'admin']]);

채널 클래스 정의하기

애플리케이션에서 다루는 채널 종류가 많아지면 routes/channels.php 파일이 금방 복잡해질 수 있습니다. 이럴 때는 클로저로 채널을 인가하는 대신 채널 클래스를 사용할 수 있습니다. 채널 클래스는 make:channel Artisan 명령어로 생성하며, 새로 생성된 클래스는 App/Broadcasting 디렉터리에 위치합니다.

php artisan make:channel OrderChannel

그다음 routes/channels.php 파일에 채널을 등록합니다:

use App\Broadcasting\OrderChannel; Broadcast::channel('orders.{order}', OrderChannel::class);

마지막으로, 해당 채널의 인가 로직을 채널 클래스의 join 메서드 안에 작성하면 됩니다. 이 join 메서드에는 원래 채널 인가 클로저에 작성했을 법한 로직을 그대로 담으면 됩니다. 물론 채널 모델 바인딩도 그대로 활용할 수 있습니다:

<?php namespace App\Broadcasting; use App\Models\Order; use App\Models\User; class OrderChannel { /** * 새 채널 인스턴스를 생성합니다. */ public function __construct() {} /** * 사용자의 채널 접근 권한을 인증합니다. */ public function join(User $user, Order $order): array|bool { return $user->id === $order->user_id; } }

NOTE

Laravel의 다른 여러 클래스와 마찬가지로, 채널 클래스 역시 서비스 컨테이너를 통해 자동으로 해석(resolve)됩니다. 따라서 생성자에 필요한 의존성을 타입힌트로 선언해 주입받을 수 있습니다.

브로드캐스팅

이벤트 브로드캐스트하기

이벤트에 ShouldBroadcast 인터페이스를 붙여 정의했다면, 이제 남은 일은 그 이벤트를 dispatch 메서드로 발생시키는 것뿐입니다. 이벤트 디스패처는 해당 이벤트가 ShouldBroadcast 인터페이스를 구현하고 있음을 감지하고, 브로드캐스트를 위해 큐에 등록합니다:

use App\Events\OrderShipmentStatusUpdated; OrderShipmentStatusUpdated::dispatch($order);

나를 제외한 다른 사용자에게만 브로드캐스트하기

이벤트 브로드캐스팅을 활용하는 애플리케이션을 만들다 보면, 특정 채널을 구독 중인 모든 사용자에게 이벤트를 보내되 현재 사용자만은 제외하고 싶을 때가 있습니다. 이런 경우에는 broadcast 헬퍼와 toOthers 메서드를 함께 사용하면 됩니다:

use App\Events\OrderShipmentStatusUpdated; broadcast(new OrderShipmentStatusUpdated($update))->toOthers();

toOthers 메서드가 언제 필요한지 감이 잘 안 온다면, 할 일 목록(Todo List) 애플리케이션을 예로 들어보겠습니다. 사용자가 작업 이름을 입력해서 새 작업(Task)을 만드는 상황을 가정해봅시다. 작업을 생성할 때 애플리케이션은 /task 엔드포인트로 요청을 보내고, 이 요청은 작업 생성 이벤트를 브로드캐스트한 뒤 새로 생성된 작업의 JSON 데이터를 응답으로 반환합니다. 그리고 JavaScript 애플리케이션은 이 응답을 받아 곧바로 작업 목록에 추가합니다:

axios.post('/task', task) .then((response) => { this.tasks.push(response.data); });

그런데 여기서 문제가 발생합니다. 우리는 작업 생성 시 이벤트도 함께 브로드캐스트했다는 사실을 기억해야 합니다. 만약 JavaScript 애플리케이션이 작업 목록에 항목을 추가하기 위해 이 이벤트도 함께 리스닝하고 있다면, 목록에 동일한 작업이 두 번 표시되는 문제가 생깁니다. 하나는 엔드포인트 응답으로 추가된 것이고, 다른 하나는 브로드캐스트 이벤트로 추가된 것이기 때문입니다. 이런 상황에서는 toOthers 메서드를 사용해 현재 사용자에게는 이벤트를 브로드캐스트하지 않도록 지시하면 문제를 해결할 수 있습니다.

WARNING

toOthers 메서드를 호출하려면 이벤트 클래스가 반드시 Illuminate\Broadcasting\InteractsWithSockets 트레이트를 사용해야 합니다.

설정 방법

Laravel Echo 인스턴스를 초기화하면 해당 커넥션에 소켓 ID가 할당됩니다. JavaScript 애플리케이션에서 HTTP 요청을 보낼 때 전역 Axios 인스턴스를 사용하고 있다면, 이 소켓 ID는 모든 요청의 X-Socket-ID 헤더에 자동으로 포함됩니다. 이후 toOthers 메서드를 호출하면, Laravel은 이 헤더에서 소켓 ID를 추출해서 해당 소켓 ID를 가진 커넥션에는 이벤트를 브로드캐스트하지 않도록 처리합니다.

전역 Axios 인스턴스를 사용하지 않는 경우에는, 모든 요청에 X-Socket-ID 헤더를 직접 추가하도록 JavaScript 애플리케이션을 설정해야 합니다. 소켓 ID는 Echo.socketId 메서드로 가져올 수 있습니다:

var socketId = Echo.socketId();

브로드캐스트 커넥션 지정하기

애플리케이션이 여러 개의 브로드캐스트 커넥션을 사용하고 있고, 기본 브로드캐스터가 아닌 다른 브로드캐스터로 이벤트를 전송하고 싶다면 via 메서드로 사용할 커넥션을 지정할 수 있습니다:

use App\Events\OrderShipmentStatusUpdated; broadcast(new OrderShipmentStatusUpdated($update))->via('pusher');

또는 이벤트 생성자 안에서 broadcastVia 메서드를 호출해 브로드캐스트 커넥션을 지정할 수도 있습니다. 다만 이 방법을 사용하려면 먼저 이벤트 클래스가 InteractsWithBroadcasting 트레이트를 사용하고 있어야 합니다:

<?php namespace App\Events; use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\InteractsWithBroadcasting; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Broadcasting\PresenceChannel; use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Queue\SerializesModels; class OrderShipmentStatusUpdated implements ShouldBroadcast { use InteractsWithBroadcasting; /** * 새로운 이벤트 인스턴스를 생성합니다. */ public function __construct() { $this->broadcastVia('pusher'); } }

익명 이벤트 (Anonymous Events)

경우에 따라, 별도의 이벤트 클래스를 만들지 않고 단순한 이벤트를 프론트엔드로 브로드캐스트하고 싶을 때가 있습니다. 이런 상황을 위해 Broadcast 파사드는 "익명 이벤트(anonymous event)"를 브로드캐스트하는 기능을 제공합니다:

Broadcast::on('orders.'.$order->id)->send();

위 예제 코드는 다음과 같은 이벤트를 브로드캐스트합니다:

{ "event": "AnonymousEvent", "data": "[]", "channel": "orders.1" }

aswith 메서드를 사용하면 이벤트 이름과 데이터를 원하는 대로 지정할 수 있습니다:

Broadcast::on('orders.'.$order->id) ->as('OrderPlaced') ->with($order) ->send();

위 예제는 다음과 같은 형태의 이벤트를 브로드캐스트합니다:

{ "event": "OrderPlaced", "data": "{ id: 1, total: 100 }", "channel": "orders.1" }

익명 이벤트를 프라이빗 채널이나 프레즌스 채널로 브로드캐스트하고 싶다면 private, presence 메서드를 사용하면 됩니다:

Broadcast::private('orders.'.$order->id)->send(); Broadcast::presence('channels.'.$channel->id)->send();

send 메서드로 익명 이벤트를 브로드캐스트하면, 해당 작업은 애플리케이션의 에 등록되어 처리됩니다. 만약 큐를 거치지 않고 즉시 브로드캐스트하고 싶다면 sendNow 메서드를 사용하세요:

Broadcast::on('orders.'.$order->id)->sendNow();

현재 인증된 사용자를 제외한 나머지 채널 구독자에게만 이벤트를 브로드캐스트하고 싶다면 toOthers 메서드를 호출하면 됩니다:

Broadcast::on('orders.'.$order->id) ->toOthers() ->send();

브로드캐스트 오류로부터 안전하게 처리하기 (Rescuing Broadcasts)

애플리케이션의 큐 서버를 사용할 수 없거나 Laravel이 이벤트를 브로드캐스트하는 도중 오류가 발생하면, 예외가 발생하면서 최종 사용자에게 애플리케이션 오류 화면이 노출될 수 있습니다. 하지만 이벤트 브로드캐스팅은 대부분 애플리케이션의 핵심 기능을 보조하는 부가적인 역할을 하는 경우가 많습니다. 따라서 이벤트에 ShouldRescue 인터페이스를 구현해두면, 이런 예외가 사용자 경험을 방해하지 않도록 막을 수 있습니다.

ShouldRescue 인터페이스를 구현한 이벤트는 브로드캐스트를 시도할 때 Laravel의 rescue 헬퍼 함수를 자동으로 활용합니다. 이 헬퍼는 발생한 예외를 잡아서(catch) 애플리케이션의 예외 핸들러에 기록(로깅)한 뒤, 사용자의 작업 흐름을 방해하지 않고 애플리케이션이 정상적으로 계속 실행되도록 해줍니다:

<?php namespace App\Events; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Contracts\Broadcasting\ShouldRescue; class ServerCreated implements ShouldBroadcast, ShouldRescue { // ... }

브로드캐스트 수신하기

이벤트 리스닝하기

Laravel Echo를 설치하고 인스턴스를 생성했다면, 이제 Laravel 애플리케이션에서 브로드캐스트되는 이벤트를 수신할 준비가 끝났습니다. 먼저 channel 메서드로 채널 인스턴스를 가져온 다음, listen 메서드를 호출해서 원하는 이벤트를 구독합니다.

Echo.channel(`orders.${this.order.id}`) .listen('OrderShipmentStatusUpdated', (e) => { console.log(e.order.name); });

프라이빗 채널에서 이벤트를 수신하려면 channel 대신 private 메서드를 사용하면 됩니다. 하나의 채널에서 여러 이벤트를 수신하고 싶다면 listen 메서드를 연속으로 체이닝할 수 있습니다.

Echo.private(`orders.${this.order.id}`) .listen(/* ... */) .listen(/* ... */) .listen(/* ... */);

이벤트 리스닝 중지하기

채널을 완전히 떠나지 않고 특정 이벤트에 대한 리스닝만 멈추고 싶다면 stopListening 메서드를 사용할 수 있습니다.

Echo.private(`orders.${this.order.id}`) .stopListening('OrderShipmentStatusUpdated');

채널 떠나기

Echo 인스턴스에서 leaveChannel 메서드를 호출하면 특정 채널을 떠날 수 있습니다.

Echo.leaveChannel(`orders.${this.order.id}`);

해당 채널뿐 아니라 연관된 프라이빗 채널과 프레즌스 채널까지 함께 떠나고 싶다면 leave 메서드를 호출하세요.

Echo.leave(`orders.${this.order.id}`);

네임스페이스

앞서 살펴본 예제에서 이벤트 클래스에 App\Events 네임스페이스 전체 경로를 명시하지 않았다는 점을 눈치채셨을 겁니다. Echo는 기본적으로 모든 이벤트가 App\Events 네임스페이스 안에 있다고 가정하기 때문입니다. 하지만 Echo 인스턴스를 생성할 때 namespace 설정 옵션을 전달하면 루트 네임스페이스를 원하는 대로 바꿀 수 있습니다.

window.Echo = new Echo({ broadcaster: 'pusher', // ... namespace: 'App.Other.Namespace' });

또는 Echo로 이벤트를 구독할 때 클래스 이름 앞에 .을 붙이는 방법도 있습니다. 이렇게 하면 매번 완전히 정규화된(fully-qualified) 클래스 이름을 직접 지정할 수 있습니다.

Echo.channel('orders') .listen('.Namespace\\Event\\Class', (e) => { // ... });

React, Vue, Svelte에서 사용하기

Laravel Echo는 React, Vue, Svelte용 훅(hook)을 제공해서 이벤트 리스닝을 간편하게 만들어줍니다. 시작하려면 프라이빗 이벤트를 수신하는 useEcho 훅을 호출하면 됩니다. useEcho 훅은 이를 사용하는 컴포넌트가 언마운트될 때 채널을 자동으로 떠나줍니다.

React

import { useEcho } from "@laravel/echo-react"; useEcho( `orders.${orderId}`, "OrderShipmentStatusUpdated", (e) => { console.log(e.order); }, );

Vue

<script setup lang="ts"> import { useEcho } from "@laravel/echo-vue"; useEcho( `orders.${orderId}`, "OrderShipmentStatusUpdated", (e) => { console.log(e.order); }, ); </script>

Svelte

<script> import { useEcho } from "@laravel/echo-svelte"; useEcho( `orders.${orderId}`, "OrderShipmentStatusUpdated", (e) => { console.log(e.order); }, ); </script>

useEcho에 이벤트 배열을 전달하면 여러 이벤트를 한 번에 수신할 수도 있습니다.

useEcho( `orders.${orderId}`, ["OrderShipmentStatusUpdated", "OrderShipped"], (e) => { console.log(e.order); }, );

브로드캐스트 이벤트 페이로드의 타입을 직접 지정할 수도 있습니다. 이렇게 하면 타입 안전성이 높아지고 에디터에서 자동완성 등의 편의 기능을 제대로 활용할 수 있습니다.

type OrderData = { order: { id: number; user: { id: number; name: string; }; created_at: string; }; }; useEcho<OrderData>(`orders.${orderId}`, "OrderShipmentStatusUpdated", (e) => { console.log(e.order.id); console.log(e.order.user.id); });

useEcho 훅은 컴포넌트가 언마운트되면 채널을 자동으로 떠나지만, 필요하다면 반환된 함수들을 이용해 리스닝을 수동으로 멈추거나 다시 시작할 수도 있습니다.

React

import { useEcho } from "@laravel/echo-react"; const { leaveChannel, leave, stopListening, listen } = useEcho( `orders.${orderId}`, "OrderShipmentStatusUpdated", (e) => { console.log(e.order); }, ); // 채널을 떠나지 않고 리스닝만 중지... stopListening(); // 다시 리스닝 시작... listen(); // 채널 떠나기... leaveChannel(); // 채널과 연관된 프라이빗/프레즌스 채널까지 모두 떠나기... leave();

Vue

<script setup lang="ts"> import { useEcho } from "@laravel/echo-vue"; const { leaveChannel, leave, stopListening, listen } = useEcho( `orders.${orderId}`, "OrderShipmentStatusUpdated", (e) => { console.log(e.order); }, ); // 채널을 떠나지 않고 리스닝만 중지... stopListening(); // 다시 리스닝 시작... listen(); // 채널 떠나기... leaveChannel(); // 채널과 연관된 프라이빗/프레즌스 채널까지 모두 떠나기... leave(); </script>

Svelte

<script> import { useEcho } from "@laravel/echo-svelte"; const { leaveChannel, leave, stopListening, listen } = useEcho( `orders.${orderId}`, "OrderShipmentStatusUpdated", (e) => { console.log(e.order); }, ); // 채널을 떠나지 않고 리스닝만 중지... stopListening(); // 다시 리스닝 시작... listen(); // 채널 떠나기... leaveChannel(); // 채널과 연관된 프라이빗/프레즌스 채널까지 모두 떠나기... leave(); </script>

퍼블릭 채널에 연결하기

퍼블릭 채널에 연결하려면 useEchoPublic 훅을 사용하세요.

React

import { useEchoPublic } from "@laravel/echo-react"; useEchoPublic("posts", "PostPublished", (e) => { console.log(e.post); });

Vue

<script setup lang="ts"> import { useEchoPublic } from "@laravel/echo-vue"; useEchoPublic("posts", "PostPublished", (e) => { console.log(e.post); }); </script>

Svelte

<script> import { useEchoPublic } from "@laravel/echo-svelte"; useEchoPublic("posts", "PostPublished", (e) => { console.log(e.post); }); </script>

프레즌스 채널에 연결하기

프레즌스 채널에 연결하려면 useEchoPresence 훅을 사용하세요.

React

import { useEchoPresence } from "@laravel/echo-react"; useEchoPresence("posts", "PostPublished", (e) => { console.log(e.post); });

Vue

<script setup lang="ts"> import { useEchoPresence } from "@laravel/echo-vue"; useEchoPresence("posts", "PostPublished", (e) => { console.log(e.post); }); </script>

Svelte

<script> import { useEchoPresence } from "@laravel/echo-svelte"; useEchoPresence("posts", "PostPublished", (e) => { console.log(e.post); }); </script>

연결 상태 확인하기

useConnectionStatus 훅을 사용하면 현재 WebSocket 연결 상태를 확인할 수 있습니다. 이 값은 리액티브(reactive)하게 동작하므로 연결 상태가 바뀌면 자동으로 갱신됩니다.

React

import { useConnectionStatus } from "@laravel/echo-react"; function ConnectionIndicator() { const status = useConnectionStatus(); return <div>Connection: {status}</div>; }

Vue

<script setup lang="ts"> import { useConnectionStatus } from "@laravel/echo-vue"; const status = useConnectionStatus(); </script> <template> <div>Connection: {{ status }}</div> </template>

Svelte

<script> import { useConnectionStatus } from "@laravel/echo-svelte"; const status = useConnectionStatus(); </script> <div>Connection: {status()}</div>

가능한 상태 값은 다음과 같습니다.

  • connected - WebSocket 서버에 성공적으로 연결된 상태
  • connecting - 초기 연결을 시도하는 중
  • reconnecting - 연결이 끊긴 뒤 재연결을 시도하는 중
  • disconnected - 연결되어 있지 않고, 재연결도 시도하지 않는 상태
  • failed - 연결에 실패했으며 재시도하지 않는 상태

소켓 ID

useSocketId 훅을 사용하면 현재 WebSocket 소켓 ID를 가져올 수 있습니다. 이 값도 리액티브하므로 재연결되어 새로운 소켓 ID가 발급되면 자동으로 갱신됩니다.

React

import { useSocketId } from "@laravel/echo-react"; function SocketIndicator() { const socketId = useSocketId(); return <div>Socket ID: {socketId}</div>; }

Vue

<script setup lang="ts"> import { useSocketId } from "@laravel/echo-vue"; const socketId = useSocketId(); </script> <template> <div>Socket ID: {{ socketId }}</div> </template>

Svelte

<script> import { useSocketId } from "@laravel/echo-svelte"; const socketId = useSocketId(); </script> <div>Socket ID: {socketId()}</div>

Presence 채널

Presence 채널은 private 채널의 보안 기능을 그대로 가져오면서, 여기에 더해 현재 채널을 구독 중인 사용자가 누구인지 알 수 있는 기능을 추가로 제공합니다. 이 기능을 활용하면 "같은 페이지를 보고 있는 다른 사용자에게 알림 보내기"나 "채팅방에 접속해 있는 사용자 목록 표시하기"처럼, 협업 기능이 필요한 애플리케이션을 쉽게 구현할 수 있습니다.

Presence 채널 인가하기

Presence 채널은 본질적으로 private 채널이기도 하므로, 사용자는 해당 채널에 접근할 권한을 인가받아야 합니다. 다만 presence 채널의 인가 콜백을 작성할 때는 private 채널과 다르게, 사용자가 채널에 참여할 권한이 있다고 해서 단순히 true를 반환하지 않습니다. 대신 해당 사용자에 대한 정보를 담은 배열을 반환해야 합니다.

인가 콜백이 반환한 데이터는 자바스크립트 애플리케이션의 presence 채널 이벤트 리스너에서 사용할 수 있게 됩니다. 만약 사용자가 presence 채널에 참여할 권한이 없다면 false 또는 null을 반환하면 됩니다.

use App\Models\User; Broadcast::channel('chat.{roomId}', function (User $user, int $roomId) { if ($user->canJoinRoom($roomId)) { return ['id' => $user->id, 'name' => $user->name]; } });

Presence 채널 참여하기

Presence 채널에 참여하려면 Echo의 join 메서드를 사용하면 됩니다. join 메서드는 PresenceChannel 구현체를 반환하는데, 이 객체는 listen 메서드뿐만 아니라 here, joining, leaving 이벤트도 구독할 수 있게 해줍니다.

Echo.join(`chat.${roomId}`) .here((users) => { // ... }) .joining((user) => { console.log(user.name); }) .leaving((user) => { console.log(user.name); }) .error((error) => { console.error(error); });

here 콜백은 채널 참여에 성공하는 즉시 실행되며, 현재 채널을 구독 중인 다른 모든 사용자의 정보를 담은 배열을 인자로 받습니다. joining 메서드는 새로운 사용자가 채널에 참여할 때 실행되고, leaving 메서드는 사용자가 채널을 떠날 때 실행됩니다. error 메서드는 인증 엔드포인트가 200이 아닌 HTTP 상태 코드를 반환하거나, 반환된 JSON을 파싱하는 과정에서 문제가 발생했을 때 실행됩니다.

NOTE

here, joining, leaving은 채팅방 인원 목록처럼 "지금 누가 접속해 있는가"를 UI에 반영할 때 유용합니다. 예를 들어 온라인 사용자 아바타 목록을 실시간으로 업데이트하는 기능을 구현할 때 이 세 콜백을 조합해서 사용하면 됩니다.

Presence 채널로 브로드캐스팅하기

Presence 채널도 public 채널이나 private 채널과 마찬가지로 이벤트를 수신할 수 있습니다. 채팅방 예시를 다시 살펴보면, NewMessage 이벤트를 해당 채팅방의 presence 채널로 브로드캐스팅하고 싶을 수 있습니다. 이때는 이벤트의 broadcastOn 메서드에서 PresenceChannel 인스턴스를 반환하면 됩니다.

/** * 이 이벤트가 브로드캐스팅될 채널을 반환합니다. * * @return array<int, \Illuminate\Broadcasting\Channel> */ public function broadcastOn(): array { return [ new PresenceChannel('chat.'.$this->message->room_id), ]; }

다른 이벤트와 마찬가지로 broadcast 헬퍼와 toOthers 메서드를 사용해서 현재 사용자를 브로드캐스트 수신 대상에서 제외할 수 있습니다.

broadcast(new NewMessage($message)); broadcast(new NewMessage($message))->toOthers();

다른 유형의 이벤트를 처리할 때와 마찬가지로, Echo의 listen 메서드를 사용해서 presence 채널로 전송된 이벤트를 수신할 수 있습니다.

Echo.join(`chat.${roomId}`) .here(/* ... */) .joining(/* ... */) .leaving(/* ... */) .listen('NewMessage', (e) => { // ... });

모델 브로드캐스팅

WARNING

아래 모델 브로드캐스팅 문서를 읽기 전에, Laravel 브로드캐스팅 서비스의 전반적인 개념과 브로드캐스트 이벤트를 직접 생성하고 리스닝하는 방법을 먼저 익혀두시길 권장합니다.

애플리케이션에서 Eloquent 모델이 생성, 수정, 삭제될 때 이벤트를 브로드캐스트해야 하는 경우가 흔히 있습니다. 물론 이는 Eloquent 모델 상태 변화에 대한 커스텀 이벤트를 직접 정의하고 ShouldBroadcast 인터페이스를 적용해서 구현할 수도 있습니다.

하지만 이런 이벤트를 오직 브로드캐스트 목적으로만 사용한다면, 매번 이벤트 클래스를 새로 만드는 작업이 번거로울 수 있습니다. 이를 해결하기 위해 Laravel은 Eloquent 모델이 상태 변화를 자동으로 브로드캐스트하도록 지정할 수 있는 기능을 제공합니다.

시작하려면 Eloquent 모델에 Illuminate\Database\Eloquent\BroadcastsEvents 트레이트를 적용합니다. 그리고 모델 이벤트가 브로드캐스트될 채널 목록을 반환하는 broadcastOn 메서드를 정의해야 합니다.

<?php namespace App\Models; use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Database\Eloquent\BroadcastsEvents; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; class Post extends Model { use BroadcastsEvents, HasFactory; /** * 이 게시글이 속한 사용자를 반환합니다. */ public function user(): BelongsTo { return $this->belongsTo(User::class); } /** * 모델 이벤트가 브로드캐스트될 채널을 반환합니다. * * @return array<int, \Illuminate\Broadcasting\Channel|\Illuminate\Database\Eloquent\Model> */ public function broadcastOn(string $event): array { return [$this, $this->user]; } }

이렇게 트레이트를 적용하고 브로드캐스트 채널을 정의하면, 해당 모델 인스턴스가 생성(created), 수정(updated), 삭제(deleted), 소프트 삭제(trashed), 복원(restored)될 때마다 자동으로 이벤트가 브로드캐스트됩니다.

여기서 눈여겨볼 부분은 broadcastOn 메서드가 문자열 $event 인자를 받는다는 점입니다. 이 인자는 모델에서 발생한 이벤트 종류를 담고 있으며 created, updated, deleted, trashed, restored 중 하나의 값을 가집니다. 이 값을 확인해서 특정 이벤트에 대해 어떤 채널로 브로드캐스트할지(혹은 아예 브로드캐스트하지 않을지) 결정할 수 있습니다.

/** * 모델 이벤트가 브로드캐스트될 채널을 반환합니다. * * @return array<string, array<int, \Illuminate\Broadcasting\Channel|\Illuminate\Database\Eloquent\Model>> */ public function broadcastOn(string $event): array { return match ($event) { 'deleted' => [], default => [$this, $this->user], }; }

모델 브로드캐스팅 이벤트 생성 커스터마이징

경우에 따라 Laravel이 내부적으로 모델 브로드캐스팅 이벤트를 생성하는 방식 자체를 커스터마이징하고 싶을 수 있습니다. 이때는 Eloquent 모델에 newBroadcastableEvent 메서드를 정의하면 됩니다. 이 메서드는 Illuminate\Database\Eloquent\BroadcastableModelEventOccurred 인스턴스를 반환해야 합니다.

use Illuminate\Database\Eloquent\BroadcastableModelEventOccurred; /** * 모델에 대한 새로운 브로드캐스트 가능 이벤트를 생성합니다. */ protected function newBroadcastableEvent(string $event): BroadcastableModelEventOccurred { return (new BroadcastableModelEventOccurred( $this, $event ))->dontBroadcastToCurrentUser(); }

모델 브로드캐스팅 규칙

채널 규칙

위 예제의 broadcastOn 메서드는 Channel 인스턴스가 아니라 Eloquent 모델 인스턴스를 그대로 반환하고 있다는 점을 눈치채셨을 겁니다. broadcastOn 메서드가 Eloquent 모델 인스턴스를 반환하거나(또는 반환하는 배열 안에 모델 인스턴스가 포함되어 있으면), Laravel은 해당 모델의 클래스명과 기본 키(primary key) 값을 조합해 자동으로 프라이빗 채널 인스턴스를 만들어줍니다.

예를 들어 id1App\Models\User 모델은 App.Models.User.1이라는 이름을 가진 Illuminate\Broadcasting\PrivateChannel 인스턴스로 변환됩니다. 물론 Eloquent 모델 인스턴스를 그대로 반환하는 대신, 채널 이름을 완전히 직접 제어하고 싶다면 Channel 인스턴스를 직접 반환할 수도 있습니다.

use Illuminate\Broadcasting\PrivateChannel; /** * 모델 이벤트가 브로드캐스트될 채널을 반환합니다. * * @return array<int, \Illuminate\Broadcasting\Channel> */ public function broadcastOn(string $event): array { return [ new PrivateChannel('user.'.$this->id) ]; }

broadcastOn 메서드에서 채널 인스턴스를 직접 반환할 계획이라면, 채널 생성자에 Eloquent 모델 인스턴스를 전달할 수도 있습니다. 이렇게 하면 Laravel이 앞서 설명한 모델 채널 규칙을 적용해서 해당 모델을 채널 이름 문자열로 자동 변환합니다.

return [new Channel($this->user)];

특정 모델의 채널 이름이 무엇인지 알고 싶다면, 모델 인스턴스에서 broadcastChannel 메서드를 호출하면 됩니다. 예를 들어 id1App\Models\User 모델에서 이 메서드를 호출하면 App.Models.User.1이라는 문자열이 반환됩니다.

$user->broadcastChannel();

이벤트 규칙

모델 브로드캐스트 이벤트는 애플리케이션의 App\Events 디렉터리에 있는 "실제" 이벤트 클래스와 연결되어 있지 않기 때문에, 정해진 규칙에 따라 이벤트 이름과 페이로드가 자동으로 결정됩니다. Laravel의 기본 규칙은 모델의 클래스명(네임스페이스 제외)과 브로드캐스트를 유발한 모델 이벤트 이름을 조합해서 이벤트 이름을 만드는 것입니다.

예를 들어 App\Models\Post 모델이 수정되면, 클라이언트 애플리케이션으로는 다음과 같은 페이로드와 함께 PostUpdated라는 이름으로 이벤트가 브로드캐스트됩니다.

{ "model": { "id": 1, "title": "첫 번째 게시글입니다" ... }, ... "socket": "someSocketId" }

App\Models\User 모델이 삭제되면 UserDeleted라는 이름의 이벤트가 브로드캐스트됩니다.

원한다면 모델에 broadcastAsbroadcastWith 메서드를 추가해서 브로드캐스트 이름과 페이로드를 직접 커스터마이징할 수도 있습니다. 이 두 메서드는 현재 발생한 모델 이벤트/동작의 이름을 인자로 받으므로, 각 모델 동작(operation)마다 이벤트 이름과 페이로드를 다르게 지정할 수 있습니다. broadcastAs 메서드에서 null을 반환하면 Laravel은 앞서 설명한 기본 이벤트 이름 규칙을 그대로 사용합니다.

/** * 모델 이벤트의 브로드캐스트 이름을 반환합니다. */ public function broadcastAs(string $event): string|null { return match ($event) { 'created' => 'post.created', default => null, }; } /** * 모델에 대해 브로드캐스트할 데이터를 반환합니다. * * @return array<string, mixed> */ public function broadcastWith(string $event): array { return match ($event) { 'created' => ['title' => $this->title], default => ['model' => $this], }; }

모델 브로드캐스트 리스닝하기

모델에 BroadcastsEvents 트레이트를 추가하고 broadcastOn 메서드까지 정의했다면, 이제 클라이언트 애플리케이션에서 브로드캐스트된 모델 이벤트를 리스닝할 준비가 된 것입니다. 시작하기 전에 이벤트 리스닝 관련 문서를 먼저 참고하시길 권장합니다.

먼저 private 메서드로 채널 인스턴스를 가져온 다음, listen 메서드를 호출해서 지정한 이벤트를 리스닝합니다. 이때 private 메서드에 전달하는 채널 이름은 Laravel의 모델 브로드캐스팅 규칙을 따라야 합니다.

채널 인스턴스를 가져온 뒤에는 listen 메서드로 특정 이벤트를 리스닝할 수 있습니다. 모델 브로드캐스트 이벤트는 App\Events 디렉터리에 있는 "실제" 이벤트와 연결되어 있지 않으므로, 이벤트 이름 앞에 .을 붙여서 특정 네임스페이스에 속하지 않음을 나타내야 합니다. 각 모델 브로드캐스트 이벤트에는 모델의 브로드캐스트 가능한 속성을 모두 담고 있는 model 속성이 포함되어 있습니다.

Echo.private(`App.Models.User.${this.user.id}`) .listen('.UserUpdated', (e) => { console.log(e.model); });

React, Vue, Svelte 사용하기

React, Vue, Svelte를 사용하고 있다면, Laravel Echo에서 제공하는 useEchoModel 훅을 이용해 모델 브로드캐스트를 쉽게 리스닝할 수 있습니다.

React

import { useEchoModel } from "@laravel/echo-react"; useEchoModel("App.Models.User", userId, ["UserUpdated"], (e) => { console.log(e.model); });

Vue

<script setup lang="ts"> import { useEchoModel } from "@laravel/echo-vue"; useEchoModel("App.Models.User", userId, ["UserUpdated"], (e) => { console.log(e.model); }); </script>

Svelte

<script> import { useEchoModel } from "@laravel/echo-svelte"; useEchoModel("App.Models.User", userId, ["UserUpdated"], (e) => { console.log(e.model); }); </script>

모델 이벤트 페이로드 데이터의 타입을 명시적으로 지정할 수도 있는데, 이렇게 하면 타입 안전성이 높아지고 편집기 자동완성도 더 편리해집니다.

type User = { id: number; name: string; email: string; }; useEchoModel<User, "App.Models.User">("App.Models.User", userId, ["UserUpdated"], (e) => { console.log(e.model.id); console.log(e.model.name); });

클라이언트 이벤트

NOTE

Pusher Channels를 사용하는 경우, 클라이언트 이벤트를 전송하려면 애플리케이션 대시보드의 "App Settings" 섹션에서 "Client Events" 옵션을 활성화해야 합니다.

경우에 따라서는 Laravel 애플리케이션 서버를 거치지 않고, 연결된 다른 클라이언트에게 곧바로 이벤트를 브로드캐스트하고 싶을 수 있습니다. 이런 방식은 특정 화면에서 다른 사용자가 메시지를 입력 중이라는 사실을 실시간으로 알려주는 "타이핑 중" 알림 같은 기능을 구현할 때 특히 유용합니다.

클라이언트 이벤트를 브로드캐스트하려면 Echo의 whisper 메서드를 사용하면 됩니다:

JavaScript

Echo.private(`chat.${roomId}`) .whisper('typing', { name: this.user.name });

React

import { useEcho } from "@laravel/echo-react"; const { channel } = useEcho(`chat.${roomId}`, ['update'], (e) => { console.log('Chat event received:', e); }); channel().whisper('typing', { name: user.name });

Vue

<script setup lang="ts"> import { useEcho } from "@laravel/echo-vue"; const { channel } = useEcho(`chat.${roomId}`, ['update'], (e) => { console.log('Chat event received:', e); }); channel().whisper('typing', { name: user.name }); </script>

Svelte

<script> import { useEcho } from "@laravel/echo-svelte"; const { channel } = useEcho(`chat.${roomId}`, ['update'], (e) => { console.log('Chat event received:', e); }); channel().whisper('typing', { name: user.name }); </script>

클라이언트 이벤트를 수신하려면 listenForWhisper 메서드를 사용합니다:

JavaScript

Echo.private(`chat.${roomId}`) .listenForWhisper('typing', (e) => { console.log(e.name); });

React

import { useEcho } from "@laravel/echo-react"; const { channel } = useEcho(`chat.${roomId}`, ['update'], (e) => { console.log('Chat event received:', e); }); channel().listenForWhisper('typing', (e) => { console.log(e.name); });

Vue

<script setup lang="ts"> import { useEcho } from "@laravel/echo-vue"; const { channel } = useEcho(`chat.${roomId}`, ['update'], (e) => { console.log('Chat event received:', e); }); channel().listenForWhisper('typing', (e) => { console.log(e.name); }); </script>

Svelte

<script> import { useEcho } from "@laravel/echo-svelte"; const { channel } = useEcho(`chat.${roomId}`, ['update'], (e) => { console.log('Chat event received:', e); }); channel().listenForWhisper('typing', (e) => { console.log(e.name); }); </script>

NOTE

클라이언트 이벤트는 서버를 거치지 않으므로 Laravel의 이벤트 시스템이나 큐, 리스너와는 무관하게 동작합니다. 인증되지 않은 임의의 데이터가 전달될 수 있으므로, 화면 표시용 정보(타이핑 상태 등) 이상의 민감한 로직 처리에는 사용하지 않는 것이 좋습니다.

알림

이벤트 브로드캐스팅알림 기능을 함께 사용하면, JavaScript 애플리케이션이 페이지를 새로고침하지 않고도 새로운 알림을 실시간으로 받을 수 있습니다. 시작하기 전에 브로드캐스트 알림 채널 문서를 먼저 읽어보시기 바랍니다.

알림이 브로드캐스트 채널을 사용하도록 설정했다면, Echo의 notification 메서드를 통해 브로드캐스트 이벤트를 수신할 수 있습니다. 이때 채널 이름은 알림을 받는 엔티티(모델)의 클래스 이름과 일치해야 한다는 점을 기억하세요:

JavaScript

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

React

import { useEchoModel } from "@laravel/echo-react"; const { channel } = useEchoModel('App.Models.User', userId); channel().notification((notification) => { console.log(notification.type); });

Vue

<script setup lang="ts"> import { useEchoModel } from "@laravel/echo-vue"; const { channel } = useEchoModel('App.Models.User', userId); channel().notification((notification) => { console.log(notification.type); }); </script>

Svelte

<script> import { useEchoModel } from "@laravel/echo-svelte"; const { channel } = useEchoModel('App.Models.User', userId); channel().notification((notification) => { console.log(notification.type); }); </script>

위 예제에서는 broadcast 채널을 통해 App\Models\User 인스턴스로 전송된 모든 알림이 콜백으로 전달됩니다. App.Models.User.{id} 채널에 대한 채널 인가(authorization) 콜백은 애플리케이션의 routes/channels.php 파일에 이미 기본으로 포함되어 있습니다.

NOTE

만약 아직 채널 인가 콜백이 등록되어 있지 않다면 routes/channels.php에 직접 추가해야 합니다. 관련 내용은 채널 인가 섹션을 참고하세요.

알림 수신 중지하기

채널을 완전히 떠나지 않고 알림 수신만 중지하고 싶다면, stopListeningForNotification 메서드를 사용할 수 있습니다:

const callback = (notification) => { console.log(notification.type); } // 수신 시작... Echo.private(`App.Models.User.${userId}`) .notification(callback); // 수신 중지 (동일한 콜백 함수를 전달해야 합니다)... Echo.private(`App.Models.User.${userId}`) .stopListeningForNotification(callback);

NOTE

수신을 중지할 때 전달하는 콜백은 등록할 때 사용한 콜백과 반드시 동일한 참조여야 합니다. 익명 함수를 인라인으로 두 번 작성하면 서로 다른 참조로 취급되어 정상적으로 동작하지 않으니, 위 예제처럼 콜백을 변수에 저장해 재사용하세요.

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

번역일: 2026년 9월 18일