[토스 SLASH24] N개의 탭, 단 하나의 웹소켓: SharedWorker
https://www.youtube.com/watch?v=SVt1-Opp3Wo
실시간으로 데이터를 가져오는 방법
1. WebSocket
2. 폴링
3. Server Sent Event (SSE)
웹 소켓
브라우저 <-> 서버
웹소켓 연결 방식
- 웹 소켓 연결시도
- 연결이 되면 서버에서 데이터를 송수신할 수 있음
토스 증권은 올해 초까지만 했어도 유저가 한개의 폰에서만 접속이 가능했었음 즉 여러개의 폰으로 접속이 불가능했음
유저 하나당 토스 증권은 한개의 서버만 열렸다
문제가 될 건 없었음 하지만 PC버전의 토스 증권을 출시하게 되어 문제가 발생함
PC환경에서는 여러개의 탭을 쓰면서 차트를 보는 것이 일반적이고 이로 인해 탭의 개수만큼 웹소켓의 연결이 늘어나게 되어 문제가 생기게 됨
이렇게 웹 소켓의 개수가 많아진다면 서버의 리소스가 필요하게 되므로 프론트엔드 단에서 연결을 줄이기로 함
Focus된 화면만 실행 && Visibility Change -> 유저 경험 악화
유저당 웹 소켓을 한개만 만들고 가져온 데이터를 공유하면 안될까?
탭 외부에 웹소켓 객체를 두는 방법?
Web Worker API를 사용하면 가능하다
Web Worker API 에는 2가지가 있다.
1. Dedicated Worker
worker.js 라는 파일을 가져와 객체로 생성한 뒤 이벤트 리스너를 통해 메시지를 가져올 수 있음
메인 스레드와 워커 스레드 둘은 통신이 가능
생성하면 해당 탭에서 스레드가 생성됨 즉, 여러 탭 -> 여러 워커 생성
-> 문제를 해결하는데 도움이 되는 게 아님
2. Shared Worker
Shared Worker의 Worker 스레드는 여러 탭에서 서로 공유가 가능하다.
생성은 Dedicated워커랑 같이 가능하나
얘는 싱글톤 패턴처럼 만들게 되면 새로 메인 스레드가 생기는것이 아니라 이전에 생겼던 애를 호출함
Shared Worker의 공유 기준
1. 같은 Origin
2. 불러온 JS 파일이 같은지
제약조건
Shared Worker를 지원해주지 않는 브라우저 (safari) 가 있다.
-> Dedicated Worker를 fall back으로 사용
실제 구현시 난관
1. 번들링
로컬파일의 경로 -> 실행시의 파일 경로가 되어서
JS 번들러가 파일 경로를 바꿀 수 있음
웹팩에서는 url 인자를 받을 수 있어서 실제 실행 환경에서의 경로로 적절히 바꿔준다.
번들러의 힘을 빌려 해결 가능
2. 메모리 누수
탭이 닫히게 되면 리소스 정리가 필요
Shared Worker에서 어떤 탭이 닫혔는지 알아야 함
-> 탭이 닫힐 때 이벤트? Before Unload -> 신뢰성이 다소 부족함 실행이 안 될 수도 있음
-> Message Port의 가비지 컬렉션으로 해결
MessagePort의 스레드 객체는 한쪽이 닫히게 되면 다른쪽도 쓸모 없는 것으로 판단되어 가비지 컬렉션이 일어남
메세지 포트 객체를 배열에 가지고 있으므로 가비지 컬렉션이 일어나지 않음
WeakRef를 사용해 가비지 컬렉션이 일어나도록 한다.
weakPort .deref()가 undefined라면 탭이 닫혔다고 판단