Realtime broadcasting with Laravel and NuxtJS (1/5)

Prologue

Laravel 은 웹소켓을 사용한 실시간 브로드캐스트 기능을 “out of the box” 로 지원한다. 이를 위해 Laravel Echo (https://github.com/laravel/echo) 라 하는 클라이언트 라이브러리가 프론트앤드 패키지의 일부로 제공되는데, 이를 Nuxt 프로젝트에서 사용할 수 있도록 만든 wrapper 모듈인 @nuxtjs/laravel-echo (https://github.com/nuxt-community/laravel-echo) 를 이용하면 Nuxt 프로젝트에서도 쉽게 리얼타임 기능을 사용할 수 있다.

공식 문서에 언급되어 있듯, Laravel 에서 기본으로 제공하는 브로드캐스트 드라이버는 Pusher Channel 과 Redis 가 있는데, Pusher Channel 의 경우 트래픽이 많은 프로덕션 환경에서 사용하기는 비용적인 문제가 있어 가성비를 경쟁력으로 삼아야 하는 스타트업 인 경우, 썩 좋은 옵션으로 보이지 않았다. 더우기 채팅기능을 위해 Pusher Chatkit 까지 사용해야 한다면, 가격 부담이 더욱 커지게 느껴질 것이다.

Pusher (https://pusher.com) 의 다른 대안으로는 Pusher API 를 PHP Ratchet (http://socketo.me) 을 이용하여 개발한 Laravel WebSockets (https://docs.beyondco.de/laravel-websockets) 을 사용하는 방법이 있다. 이 패키지를 사용하여 웹소켓 서버 박스를 만든 다음, Laravel 의 Pusher 브로드캐스트 드라이버가, Pusher 서버가 아닌, 커스텀 짝퉁 pusher 박스를 이용하도록 만드는 방법이다. (step by step 설명은 아래 유튜브 강의 참고.)

하지만, 이 또한 트래픽이 많아져서 해당 서비스의 horizontal 스케일이 필요할 때까지 고려한다면, 프로덕션용으로 viable path 가 될 지 걱정스런 부분이 있다. horizontal 스케일을 위해, ELB 아래에 여러 서비스 인스턴스를 연결하게 된다면, 결국 peer 인스턴스들 간에 데이터 동기화를 위한 로직이 필요할텐데, 이러한 커스터마이징을 위하여, PHP Ratchet 을 사용하는 방법이 Node.js Express 를 사용하는 방법 보다 더 나은 path 인지 여러 이유에서 확신이 서지 않았다.

또 다른 대안으로는 firebase 를 사용하는 방법인데, 옆 사무실에서는 잘 사용하고 있다지만, 이 역시 트래픽 증가를 고민할 단계 쯤 되면 viable 한 솔루션이 되지 않는다는 부정적인 견해가 팽배하여, 기술적인 부분을 깊게 알아보지 않고 쉽게 포기해 버렸다. 물론, 어떠한 문제들도 영리한 work around 방법들이 존재하겠지만, 현재 내가 갖고 있는 리소스들을 고려해봤을때 Laravel Echo Server (https://github.com/tlaverdure/laravel-echo-server) 라는 오픈소스 프로젝트를 근간으로 개발하는 것이 가장 현명한 방법이 되리라 판단했다.

서두가 길었는데, 결국 위에서 언급한 이유들로 인하여, AWS 환경에서 ALB 와 AutoScaling 기능을 이용하여 horizontal 스케일이 가능한 Redis 와 NoSQL (MongoDB 나 DynamoDB 중 하나) 을 사용하는 Laravel Echo 호환 node.js 서버의 개발하려고 한다. 다만, 이를 위한 아래에 열거된 pre-requisite 들이 Laravel/Nuxt 개발자인 나에게 만만치 않아 보이지만 말이다.

  • node.js Express 학습
  • TypeScript 학습
  • Laravel Echo Server 프로젝트 소스 분석
  • Chat 용 인증 메카니즘
  • Redis pub/sub 용 데이터 분석/설계
  • RDB/MongoDB 용 스키마 설계
  • horizontal 스케일 가능하도록 부분 변경
  • 테스트/배포

다행인 것은 비슷한 주제의 다양한 레퍼런스 자료들은 즐비하다는 것.

Learning new things

Node.js 학습은 일단 Udemy 강좌 중 Node.js, Express, MongoDB & more: The Complete Bootcamp 를 선택해서 들었는데, 내용이 42시간이 넘는 정도의 분량이라, 짧은 시간내에 모두 듣기엔 좀 인내심이 필요하다. 하루 8시간 씩 듣는다 쳐도 6일 분량. 모노토너스한 목소리 톤 때문에 깜박 졸았다면, 어흑… 섹션 9까지 듣고, 아래 섹션들은 일단 패스한다. 시간있을 때 다시!

https://www.udemy.com/course/nodejs-express-mongodb-bootcamp

  • 섹션 10. 인증
  • 섹션 11. 몽구스 모델링
  • 섹션 12. pug 템플릿 엔진
  • 섹션 13. 고급 기능
  • 섹션 14. 디플로이먼트

TypeScript 는 Frontend Masters 의 강좌인 TypeScript 3 Fundamentals, v2 를 선택해서 들었다.

https://frontendmasters.com/courses/typescript-v2/

이 강의는 4시간 분량으로 오전 작업 후 남은 하루 일정에 도전해 볼 만한 분량이다. TS 의 주된 특징들을 설명하면서 넘어가는 것까지는 좋았는데, 강의 내용을 기초로 실제 프로젝트를 시작하기 부족함이 느껴져서 다른 강의를 하나 더 듣게 되었다. 아래의 Pluralsight 기초 TypeScript 강좌. 이러다가 조낸 강의만 듣다가 에너지를 소진하고 끝내버릴 분위기…

https://www.pluralsight.com/courses/typescript-projects-configuring-compiling-debugging

Time to get my hands dirty

늘어진 스케쥴로 인해 제대로 된 path 를 가고 있는지 확신이 줄어들긴 했지만, 일단 VueJS 를 위한 JS 코딩 스타일에 맞춰진 나의 Visual Studio Code 의 ESLint 와 Prettier 옵션부터 TypeScript 를 위해 수정했다. .ts 파일 저장도 제대로 안되면 안되므로. 어쨌든, Visual Studio Code 의 settings.json 은 아래와 같이 변경하여, TypeScript 를 대응하도록 했다.

{
  "": {
    "editor.formatOnSave": false
  },
  "": {
    "editor.formatOnSave": false
  },
  "[javascriptreact]": {
    "editor.formatOnSave": false
  },
  "[typescript]": {
    "editor.formatOnSave": false
  },
  "[typescriptreact]": {
    "editor.formatOnSave": false
  },
  "": {
    "editor.formatOnSave": false
  },
  "diffEditor.renderSideBySide": false,
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },
  "editor.formatOnSave": true,
  "editor.formatOnPaste": true,
  "editor.largeFileOptimizations": false,
  "editor.minimap.enabled": false,
  "editor.tabSize": 2,
  "eslint.alwaysShowStatus": true,
  "eslint.validate": [
    "vue",
    "html",
    "javascript",
    "typescript",
    "typescriptreact"
  ],
  "explorer.confirmDelete": false,
  "explorer.openEditors.visible": 0,
  "files.associations": {
    "*.module": "php"
  },
  "files.maxMemoryForLargeFilesMB": 20480,
  "php.suggest.basic": false,
  "phpcs.enable": false,
  "prettier.vueIndentScriptAndStyle": true,
  "sync.gist": "e38a9bd8b19391bb6ce89814e8e621f1",
  "terminal.integrated.fontFamily": "D2Coding",
  "terminal.integrated.fontSize": 13,
  "terminal.integrated.shell.osx": "/bin/zsh",
  "vetur.completion.useScaffoldSnippets": false,
  "vetur.validation.template": false,
  "window.zoomLevel": 0,
  "workbench.colorTheme": "Monokai",
  "workbench.iconTheme": "vscode-icons",
  "editor.detectIndentation": false,
  "html.format.preserveNewLines": false,
  "eslint.probe": [
    "javascript",
    "javascriptreact",
    "typescript",
    "typescriptreact",
    "vue"
  ]
}

Laradock to the rescue

다음 편에서는 로컬환경에서 Laradock 을 사용하여, 프로덕션과 비슷한 환경으로Frontend, Backend 및 Laravel Echo Server 를 설정해 보겠다.

Leave a Reply