Local Setup
일단, Laravel 6.16 와 NuxtJS 2.11 를 사용한 “out of the box” Laravel 브로드캐스트 기능이 로컬 환경에서 작동하도록 설정 후, 전반적인 구현 디테일을 분석해 본다.
사용자가 브라우저로 접속할 frontend 주소는 localhost:3000
이고, Laradock 으로 설정한 backend API 는 amuse.test
라는 주소 값을 갖고 있으며, Echo 서버는 websockets.test:6001
로 접근가능한 구성이다. 아래의 그림을 참고하기 바란다. Laradock 환경에서, Echo 서버가 amuse.test 으로, 접근할 수 있도록 설정하는 것이 tricky 할 수 있는데 이는 이전 Laradock 관련 포스팅을 참고하기 바란다. (https://whatsupkorea.com/2018/05/26/laradock-with-muliple-projects)

Laravel 브로드캐스트 기능을 NuxtJS 를 사용하는 프로젝트에서 사용하기 위해서는, Laravel Echo 의 NuxtJS 용 wrapper 모듈 @nuxtjs/laravel-echo 을 설치 후, nuxt.config.js
파일을 아래와 같이 설정한다.
: buildModules: [ '@nuxtjs/dotenv', '@nuxtjs/eslint-module', '@nuxtjs/vuetify', [ '@nuxtjs/laravel-echo', { broadcaster: 'socket.io', host: 'http://websockets.test:6001', plugins: ['~/plugins/echo.js'], // transports: ['websocket', 'polling'], authModule: true, connectOnLogin: true, disconnectOnLogout: true } ], ], :
plugins/echo.js
에는 아래와 같이 public 채널, Laravel notification 용 프라이빗 채널, 그리고 presence 채널을 위한 3개의 리스너를 추가했다. 각각의 채널은 use-case 별로 추가확장 할 수 있으므로, 가장 심플한 형태의 working example 로 보면 되겠다.
export default function({ $auth, $echo, store, app: { $toast } }) { $echo.channel('public').listen('PublicMessageSent', (event) => { console.log('data from public', event) }) if ($auth.loggedIn) { $echo .private(`App.Models.User.${$auth.user.id}`) .notification((notification) => { console.log(notification) $toast.success(notification.message) store.commit('notifications/INCREASE_UNREAD_COUNT') }) $echo .join('presence') .here((users) => { store.commit('online/SET_USERS', users) }) .joining((user) => { store.commit('online/JOIN_USER', user) }) .leaving((user) => { store.commit('online/LEAVE_USER', user) }) } }
2. Laravel Echo Server 를 위한 laravel-echo-server.json
파일의 내용은 아래와 같이 설정한다.
참고로, Laravel 의 config/database.php
Redis 옵션의 prefix 값 즉, config('database.redis.options.prefix')
의 값이 app 내 사용한 채널명과 조합하여 사용되므로, 이를 frontend 에서도 동일한 이름으로 해당 채널을 지정하려면 databaseConfig.redis.keyPrefix
옵션을 같은 값으로 셋팅해주는 것이 좋다. 그러면, Redis 에 실제 설정된 키값에 상관없이 PHP 코드에서는 new PrivateChannel('chat');
이라 사용하고, JS 코드에서는 Echo.private('chat').listen()
라고 사용하는 것이 가능하다.
{ "authHost": "http://amuse.test", "authEndpoint": "/broadcasting/auth", "clients": [ { "appId": "1111aaaa9999cccc", "key": "8888dddd2222bbbb4444ffff6666eeee" } ], "database": "redis", "databaseConfig": { "redis": { "port": "6379", "host": "redis", "keyPrefix": "laravel_database_" }, "sqlite": { "databasePath": "/database/laravel-echo-server.sqlite" } }, "devMode": true, "host": null, "port": "6001", "protocol": "http", "socketio": {}, "secureOptions": 66666666, "sslCertPath": "", "sslKeyPath": "", "sslCertChainPath": "", "sslPassphrase": "", "subscribers": { "http": true, "redis": true }, "apiOriginAllow": { "allowCors": true, "allowOrigin": "http://localhost:3000", "allowMethods": "GET, POST", "allowHeaders": "Origin, Content-Type, X-Auth-Token, X-Requested-With, Accept, Authorization, X-CSRF-TOKEN, X-Socket-Id" } }
3. Laravel 7 이 아니라면, CORS 설정을 위해 "fruitcake/laravel-cors": "^1.0"
디펜던시를 수동으로 추가하고, config/cors.php
를 아래와 같이 설정한다.
<?php return [ 'paths' => ['*'], 'allowed_methods' => ['*'], 'allowed_origins' => ['*'], 'allowed_origins_patterns' => [], 'allowed_headers' => ['*'], 'exposed_headers' => false, 'max_age' => false, 'supports_credentials' => false, ];
위의 설정으로 public, private, presence 채널 접속이 가능하며, Load balancer 를 Echo 서버 앞에 설정하는 구성이라면 HTTPS 를 통신을 위한 Echo 서버의 추가 설정 또한 필요없어진다. 이제 NuxtJS 앱에서, 동적으로 프라이빗 chat.{room id#}
채널을 listen() 하거나 leave() 하면서 웹소켓통신을 할 수 있도록 만들면, 비교적 수월하게 아래 그림과 같은 채팅서비스를 구현할 수 있다.

그럼 당장 Laravel Echo 기능을 이용한 채팅 서비스를 프로덕션에 적용해보자. 라고 할 줄 알았다면… Not so fast.