-
Notifications
You must be signed in to change notification settings - Fork 0
브라우저 WebSocket 관리에서 SharedWorker 도입 검토
최근 라이브 스트리밍 서비스의 채팅 시스템을 개발하면서 흥미로운 문제 상황을 마주했다. 사용자들이 하나의 채널을 여러 탭으로 열었을 때 발생하는 시청자 수 중복 집계 문제였다. 예를 들어 한 사용자가 "조이" 채널을 3개의 탭으로 열면, 시청자 수가 3명으로 집계되는 현상이 발생했다. 이 문제를 해결하기 위해 웹소켓 연결 관리 방식을 개선하고자 했고, 그 과정에서 SharedWorker라는 기술을 검토하게 되었다.
우리 서비스는 채널 페이지에 진입할 때 자동으로 웹소켓 연결이 이루어지는 구조다. 이 연결을 통해 실시간 채팅과 시청자 수 집계가 동시에 이루어진다. 문제는 이 구현이 컴포넌트 단위로 이루어져 있어, 동일 채널을 여러 탭에서 열 때마다 새로운 웹소켓 연결이 생성된다는 점이었다.
사용자A의 브라우저:
[탭1] 조이 채널 → 웹소켓 연결 1 → 시청자 +1
[탭2] 조이 채널 → 웹소켓 연결 2 → 시청자 +1
[탭3] 조이 채널 → 웹소켓 연결 3 → 시청자 +1
이는 불필요한 리소스 사용일 뿐만 아니라, 정확한 시청자 수 파악을 어렵게 만드는 요인이 되었다.
문제 해결을 위해 SharedWorker라는 웹 기술을 발견했다. SharedWorker는 브라우저의 여러 탭이 하나의 워커를 공유할 수 있게 해주는 기술이다. 이를 활용하면 다음과 같은 구조를 만들 수 있었다:
[탭1] 채팅/시청
[탭2] 팝업 채팅창 → [SharedWorker] → 단일 웹소켓 연결 → 서버
[탭3] 스트리머 대시보드
이 방식은 여러 가지 장점을 제공했다:
- 브라우저당 하나의 웹소켓 연결로 최적화
- 실시간 데이터의 일관된 동기화
- 정확한 시청자 수 집계 가능성
위 과정들을 클라이언트 측에서 최대한 정확한 시청자 수 집계를 위한 해법이었다. 하지만 서버에서도 시청자수 집계를 위해 IP 기반 필터링을 적용했다.
시청자 집계 로직 (서버):
1. 웹소켓 연결 시 클라이언트 IP 해시화
2. 채널별로 유니크한 IP 해시 카운트
3. 실시간 시청자 수 = 유니크 IP 수
이는 클라이언트 단의 복잡한 처리 없이도 정확한 시청자 수 집계가 가능함을 의미했다.
더 깊이 고민하면서 우리 서비스의 특성도 다시 살펴보았다. 사용자들의 일반적인 시청 패턴은 다음과 같았다:
[탭1] 게임이좋아 채널 → 채널A 전용 웹소켓
[탭2] 요리왕 채널 → 채널B 전용 웹소켓
[탭3] 음악다방 채널 → 채널C 전용 웹소켓
각 채널이 독립적인 컨텐츠와 채팅방을 가지고 있어, 채널 간 웹소켓 연결 공유의 실익이 크지 않았다.
게다가 SharedWorker는 브라우저 지원 범위가 제한적이었다:
- Chrome, Edge, Firefox: 안정적 지원
- Safari: 최신 버전에서만 부분 지원
- IE: 미지원
이를 위한 폴리필과 대체 로직 구현은 새로운 복잡성을 가져올 것이 분명했다.
긴 고민 끝에 웹소켓 연결을 현재의 컴포넌트 기반 구조를 유지하기로 결정했다. 그 이유는 다음과 같다:
- 단순성과 명확성
[채널 페이지]
├─ 스트리밍 영역
└─ 채팅 컴포넌트
└─ 웹소켓 연결
이 구조는 직관적이고 유지보수가 용이하다.
- 강한 결합의 정당성 채팅은 해당 채널에 종속적인 기능이므로, 컴포넌트와의 강한 결합이 오히려 자연스럽다.
- 실제 필요성 부족
- 서버 측에서 이미 시청자 수 정확성 보장
- 채널별 독립적 운영으로 인한 공유 이점 제한
이번 검토 과정을 통해 몇 가지 중요한 교훈을 얻었다:
- 문제 해결의 관점
- 클라이언트/서버 전체를 고려한 접근 필요
- 기존 시스템의 기능 파악 중요성
- 기술 도입의 기준
- 실제 문제 해결 기여도
- 구현/유지보수 비용
- 서비스 특성과의 부합성
- 단순함의 가치
- 불필요한 추상화 지양
- 명확한 책임 범위의 중요성
때로는 새로운 기술의 도입이 아닌, 현재 시스템의 가치를 재발견하는 것이 더 중요할 수 있다. 이번 검토 과정은 기술 도입을 고려할 때 서비스의 실제 요구사항과 제약사항을 종합적으로 고려해야 한다는 것을 다시 한번 일깨워주었다.
복잡한 문제라고 해서 반드시 복잡한 해결책이 필요한 것은 아니다. 때로는 현재의 단순한 구조가 가장 좋은 해결책일 수 있다는 점을 배웠다. 이는 향후 기술 검토 과정에서도 중요한 판단 기준이 될 것이다.