채팅은 Socket 통신을 이용한다.
- Socket 통신
소켓은 프로세스가 네트워크를 통해 데이터를 송수신할 수 있도록 하는 창구이며, 떨어져 있는 두 호스트를 연결해주는 인터페이스의 역할을 한다. 역할에 따라 서버 소켓, 클라이언트 소켓으로 구분된다.
(서버소켓, 클라이언트 소켓은 서로 다른 소켓이 아니며, 역할에 따라 구분된다)
우리 서비스 실시간 채팅 요구사항
- 채팅은 저장될 필요가 없다. 라이브스트리밍을 하는 도중에만 보이면 된다. (기본기능 출시 후 추후에는 저장이 되어야한다.)
- 유저 인증
- 방장이 강퇴, 채팅금지, 유저 차단 등의 권한을 가지고 있어야한다. (유저를 식별할 수 있어야함)
기본적인 요구사항은 이렇다
내가 사용할 수 있는 소켓
1. TCP socket
2. websocket
3. Socket.io(websocket 기반 라이브러리)
4. UDP socket
결론적으로 websocket랑 socket.io 중 하나로 하기로 했다.
따지고보면 Socket.io도 websocket에 기반을 두고 있기 때문에 사실상 websocket으로 결정했다고 봐도 무방하다.
일단 우리의 웹서버에서 다른 서버의 웹페이지 등과 통신하기위해 사용하는 프로토콜은
L4 layer protocol에 http, L3 layer protocol 에 TCP를 사용한다.
이미 http 통신이라고 불리우는 것의 다른 서버와 데이터를 주고받는 통신과정안에 tcp가 들어가 있다고 봐도 무방하다.
그러므로 또 다른 tcp 통신을 하기위해서는 새로운 포트를 열어줘야하는 것이다. (보안적인 문제 야기 가능성)
인트라넷 경계 내에서 작업하는 경우 해당 네트워크의 시스템을 제어하고 TCP 연결에 적합한 포트를 열 수 있기 때문에 TCP 소켓을 통해 통신하는 것이 더 쉽다. 하지만 이 포트(80,443)는 일반적으로 HTTP를 사용하는 웹 서버의 표준 포트이므로 HTTP 프로토콜을 준수해야한다다. 그렇지 않으면 서버가 사용자와 통신하지 않는다.
웹 소켓의 목적은 HTTP를 통해 연결을 시작한 다음 웹 소켓 프로토콜 (서버가 그렇게 할 수 있다고 가정)을 사용하여보다 “TCP 소켓”과 유사한 통신 스트림을 허용하도록 협상하는 것입니다.
websocket이 나오기 전에 웹에서 통신을 하기위해서는 기본적으로 다른 tcp 연결을 할 수 없기 때문에
polling, long looling 등 연결이 되어있는 것처럼 하는 http 기반의 연결지향형처럼 보이는 기술들이 있었다.
socket을 사용해 연결이 되어서 실시간으로 데이터를 받는 것처럼 보이는 기술들이다.
하지만 대역폭문제, 트래픽문제 등을 해결하지 못했고 이러한 필요성들에 의해 websocket이 나왔다
처음 나왔을 때는 지원하는 브라우저도 많지 않고 범용적인 사용성을 기대하긴 어려웠지만 2022년 4월 18일 기준으로 IE 말고는 모든 브라우저를 다 지원한다.
websocket의 핸드쉐이킹 과정
GET /chat HTTP/1.1
Host: localhost:8080
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13
Origin: http://localhost:9000
- Upgrade : 프로토콜을 전환하기 위해 사용하는 헤더. 웹소켓 요청 시에는 반드시 websocket이라는 값을 가지며, 이 값이 없거나 다른 값이면 cross-protocol attack이라고 간주하여 웹소켓 접속을 중지시킵니다.
- Connection : 현재의 전송이 완료된 후 네트워크 접속을 유지할 것인가에 대한 정보. 웹소켓 요청 시에는 반드시 Upgrade라는 값을 가지며, Upgrade와 마찬가지로 이 값이 없거나 다른 값이면 웹소켓 접속을 중지시킵니다.
- Sec-WebSocket-Key : 유효한 요청인지 확인하기 위해 사용하는 키 값.
- Sec-WebSocket-Protocol : 사용하고자 하는 하나 이상의 웹 소켓 프로토콜 지정. 필요한 경우에만 사용.
- Sec-WebSocket-Version : 클라이언트가 사용하고자 하는 웹소켓 프로토콜 버전. 현재 최신 버전 13
- Origin : 모든 브라우저는 보안을 위해 이 헤더를 보냅니다(Cross-Site WebSocket Hijacking와 같은 공격을 피하기 위해서). 대부분 어플리케이션은 이 헤더가 없는 요청을 거부하며, 이러한 이유로 CORS정책이 만들어진 것입니다.
websocket 연결 수, 연결하는데 걸린 시간 벤치마크
테스트 환경 : 8core 16 gib ram
분산서버로 2core 4gib ram 4개 ( docker)
10,000명을 연결하고 누적 550만개의 요청에 응답하는 시간
각 서버가 전체 벤치마크를 완료하는데 걸린 시간
websocket vs socket.io
socket.io를 사용하기로 결정했다.
우리에게 필요한 서비스는 라이브 스트리밍마다 방을 나누고, 그 방에만 message가 전송되도록 해야하는데, socket.io에는 room이란 개념으로 방을 나누는 기능이 구현되어있다. 하지만 websocket은 직접 다 구현해줘야하고, 혹시나 websocket이 연결되지 않는 상황이 생기면 socket.io는 websocket 기반이지만 다른 프로토콜로 재연결해주게 되는데 websocket만을 사용하게 되면 연결이 안되는 상황에 따른 예외처리를 모두 해줘야한다.
가장 걱정되는건 갑자기 라이브 채팅의 사용자가 늘어났을 때 확장성이 websocket보다 socket.io가 안좋게 나타났는데, 해당부분은 라이브스트리밍을 저장할 때 사용할 redis pub/sub 기술을 사용해서 채팅서버를 확장하면 될 것 같아서 문제가 없다고 판단했다.
최종 결정
채팅 서버 -> socket.io
채팅 저장 및 확장 -> redis pub/sub
최초 서비스 출시에는 채팅서버만 구현해서 라이브스트리밍을 보는 도중에만 채팅이 가능하도록 출시하고, 업데이트할 때 채팅을 저장 및 클라이언트가 늘어났을 때 확장하는 기능까지 추가할 계획이다.
'node.js' 카테고리의 다른 글
nodejs - redis Sorted SET - ZADD (0) | 2022.08.25 |
---|---|
nodejs- 현재시간 숫자만 구하는 법 (0) | 2022.08.25 |
[node.js] redis 연결 (0) | 2022.08.23 |
node.js OpenSSL 적용과정 - let's encrypt (0) | 2022.08.15 |
[Aws ec2] nginx + Socket.io 연동 (0) | 2022.04.19 |
댓글