Laravel Broadcast — pusher(X), Laravel websocket(O) 편

Jeongkuk Seo
sjk5766
Published in
9 min readOct 26, 2019

지난번 포스팅에서는 Laravel Broadcast redis를 다뤘습니다. Laravel 에서는 Broadcasting을 redis, pusher 두 가지 방식으로 지원하는데 이번 포스팅에서는 pusher 기반의 broadcasting에 대한 내용을 다루겠습니다.

단, Laravel 공식 홈페이지에서 소개하는 pusher가 아닌(pusher의 Limitation 때문에) pusher 프로토콜을 구현한 Laravel Websocket으로 Broadcasting 하는 내용을 다룹니다.

Pusher limitation

Laravel 공식 Document에서 Broadcasting을 살펴보면 아래와 같은 화면을 볼 수 있습니다.

여기서 Pusher Channels 링크를 클릭하면 여기접속하게 됩니다. Pricing을 클릭해보면 아래와 같은 화면을 확인할 수 있습니다.

즉, 무료버전을 사용하면 limitation이 존재합니다. 각 상황에 따라 선택지가 다를 수 있습니다. 개인 프로젝트라면 무료버전을 사용하면 되고, Redis를 이용해 broadcasting을 구현할 수도 있습니다.

Limitation 없이 pusher를 쓰려면?

“아, pusher는 limitation이 존재하니 Redis로 Broadcasting을 구현해야지” 라고 생각했으나 추후에 Laravel websocket 프로젝트를 발견했습니다.

Laravel websocket은 웹 소켓을 위한 Laravel 패키지로 Laravel의 Broadcasting 지원, pusher 프로토콜 구현, 그리고 Limitation이 없습니다.

따라서 이 포스팅은 pusher 프로토콜을 구현한 Laravel Websocket을 사용하여 Broadcasting 하는 내용을 다룹니다.

Pusher 정보 생성

Laravel Websocket은 내부적으로 pusher 프로토콜을 구현하기 때문에 운영에 필요한 Key나 ID를 발급받아야 합니다.

이 링크에 접속 후 회원가입을 하면 아래 화면이 보입니다. 여기서 Create new app 버튼을 클릭합니다.

사용할 Channel 명을 아래 화면에서 입력 후 Create my app 버튼을 클릭합니다.

그 후에 아래와 같이 pusher 프로토콜 운영에 필요한 app_id 및 key 정보들을 받을 수 있습니다. 이 정보는 추후 설정부분에 사용하게 됩니다.

Laravel Websocket 설치 및 Laravel 설정

config/app.php 파일에서 아래 코드가 주석처리 되어있습니다. 주석 해제합니다.

App\Providers\BroadcastServiceProvider::class,

laravel-websockets 설치 및 config 파일을 publish 합니다.

composer require beyondcode/laravel-websocketsphp artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="config"

config/app.php 파일에서 providers 배열 아래에 아래 구문을 추가해 줍니다.

\Nuwave\Lighthouse\Subscriptions\SubscriptionServiceProvider::class,

pusher를 설치합니다.

composer require pusher/pusher-php-server

.env 파일에서 BROADCAST_DRIVER=pusher 로 변경하고 위에서 생성한 pusher 정보들을 입력합니다.

BROADCAST_DRIVER=pusher// 위에서 생성했던 pusher 정보들을 여기에 넣어주세요
PUSHER_APP_ID=ID
PUSHER_APP_KEY=
PUSHER_APP_SECRET=xxx
PUSHER_APP_CLUSTER=xxx

config/broadcasting.php 파일에서 BROADCAST_DRIVER 변경합니다.

'default' => env('BROADCAST_DRIVER', 'pusher')

config/broadcasting.php 파일에서 options 하위에 host, port, scheme 정보를 추가합니다.

'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'useTLS' => true,
'host' => '127.0.0.1',
'port' => 6001,
'scheme' => 'http'

],
],

php artisan websockets:serve 명령어를 입력합니다.

서버측에서 broadcasting을 위해 event를 생성합니다.

php artisan make:event test

app/Events 경로의 test.php 파일을 열고 ShouldBroadcast 인터페이스를 상속받고 public channel을 열어줍니다.

routes/web.php 에서 /broadcast 로 접근할 경우 test 브로드캐스트가 발생하도록 코드를 작성합니다.

Client측 설정

Client에서는 Laravel 공식 Document에서 소개하는 Laravel-echo를 사용하여 broadcasting을 받겠습니다. 사실 이 내용의 대부분은 redis 편과 중복됩니다. 따라서 이 링크에 들어가서 클라이언트 측 작업사항을 동일하게 수행합니다.

Client 측에서 pusher를 사용하기 위해 추가적인 작업을 합니다.

npm install — save pusher-js

resources/js/bootstrap.js 파일에 아래 내용을 추가합니다.

import Echo from "laravel-echo"
window.Pusher = require('pusher-js');
window.io = require('socket.io-client');
window.Echo = new Echo({
broadcaster: 'pusher',
key: '생성한 pusher 키',
wsHost: window.location.hostname,
wsPort: 6001,
host: window.location.hostname + ':6001'
});

디폴트로 생성되는 resources/js/components/ExampleComponent.vue에 아래 코드를 추가합니다.

Echo.channel('test') // 채널 이름
.listen('test', (e) => { // 이벤트 이름
console.log(e);
});

Redis와 달라진 점은, Laravel-echo-server & Redis로 Broadcasting을 할 경우 채널의 이름에 laravel_database를 자동으로 추가하지만 Laravel Websocket은 채널 이름 그대로 test를 입력했습니다.

자바스크립트를 npm run dev 명령으로 빌드한 뒤, Client에 접속합니다. 접속하게 될 경우 Laravel Websocket이 실행되는 Console에서 접속에 성공한 로그를 확인할 수 있습니다.

테스트

브라우져에서 http://localhost/broadcast에 접속하면 web.php에서 코드대로 broadcasting이 발생할 것이고, 이 데이터는 Laravel Websocket으로 전달되어 최종적으로 Laravel-echo에게 전달될 것입니다.

http://localhost/broadcast에 접속하면 Laravel Websocket을 실행한 Console에 다음과 같은 로그가 기록됩니다.

Connection id 511109914.431779481 sending message {“channel”:”test”,”event”:”App\\Events\\test”,”data”:”{\”key\”:\”value\”}”}

localhost에서는 아래와 같이 최종적인 데이터를 수신한 것을 확인할 수 있습니다.

--

--