-
Notifications
You must be signed in to change notification settings - Fork 0
[채팅 스터디] 어떤 기술을 사용할까 _종호
- 작성자: @jonghopark95
- 작성일: 2022.01.10
- Description: 채팅 기능 - 어떤 기술을 사용할까
정리 안하고 막 쓰는중...
참고
HTTP 는 Stateless 한 연결이다.
=> 하나의 장치가 충돌 회피, 동기화 처리 등의 목적으로 다른 장치의 상태를 주기적으로 검사하여 일정한 조건을 만족할 때 송수신 처리를 하는 방식
- Regular Polling
- 주기적으로 Client 에서 Server 에게 계속해서 데이터 요청을 하는 것.
- 단점
- 계속해서 주기적으로 요청하기 때문에 네트워크, 서버 리소스 낭비를 가져온다.
- Long Polling
- Client 가 백엔드에게 요청을 하는데, 이 순간 서버는 두 가지 상황에 따라 대처를 다르게 한다.
- 만약 데이터가 있다면, 즉시 이를 반환한다.
- 만약 데이터가 없다면, 해당 연결을 open 상태로 유지한다. 만약, 백엔드에서 어떤 변화가 일어난다면 이 연결을 이용해 client 에게 반환한다.
- 클라이언트는 데이터를 받으면 연결을 유지하기 위해 다시 요청한다.
- 장점
- Short Polling 과는 다르게 Client 에서 Server 에게 지속적으로 데이터 요청을 하지 않아도 된다.
- 단점
- 만약, 반환되는 데이터가 매우 빠르게 발생한다면 오히려 Short Polling 보다 많은 데이터를 보내게 된다.
- Client 가 백엔드에게 요청을 하는데, 이 순간 서버는 두 가지 상황에 따라 대처를 다르게 한다.
async function subscribe() {
let response = await fetch("/subscribe");
if (response.status == 502) {
// Status 502 is a connection timeout error,
// may happen when the connection was pending for too long,
// and the remote server or a proxy closed it
// let's reconnect
await subscribe();
} else if (response.status != 200) {
// An error - let's show it
showMessage(response.statusText);
// Reconnect in one second
await new Promise(resolve => setTimeout(resolve, 1000));
await subscribe();
} else {
// Get and show the message
let message = await response.text();
showMessage(message);
// Call subscribe() again to get the next message
await subscribe();
}
}
subscribe();
WebSocket 은 Stateful 한 연결이다.
-
특징
- Client 가 서버에게 WebSocket Request 를 보내고, 서버가 accept 하면 연결이 성립된다.
- 이후, 한 쪽에서 연결을 close 할 때 까지 해당 connection 은 유지되며 양쪽 어디에서든 request 를 보낼 수 있다.
-
websocket 프로토콜은 wss:// 요청을 하더라도 일단 http 로 요청을 하고 (엄밀히는 upgrade 요청을 한다.), server 가 approve 하면 websocket 프로토콜로 바꾼다.
이는 같은 포트로 HTTP, WebSocket 프로토콜을 핸들링할 수 있게 함
// Server Response
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
// Server Response
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
참고 :
-
- ws 패키지로 websocket 프로토콜을 지원하는 메서드들을 사용할 수 있다.
- Class : WebSocketServer
- Event : close, connection, error, headers, listening
- methods : address(), clients, close, handleUpgrade, shouldHandle
- Class WebSocket
- Event : close, error, message, open, ping, pong, unexpected-response, upgrade
- methods : addEventListener (요걸로 room 만들 수 있을듯?), binaryType, bufferedAmount, close, extensions, isPaused, onclose, onerror, onmessage, onopen, ping, pong, porotocol, readyStateremoveEventLIstener, resume, send, terminate, ...
-
-
JS 에는 WebSocket API 가 있다. WebSocket constructor 로 server 와 websocket 통신을 할 수 있다.
-
Event
-
open event
- WebSocket 이 오픈되고 연결이 일어나면
open
이벤트가 발생한다.
- WebSocket 이 오픈되고 연결이 일어나면
-
message event
- WebSocket 을 통해 데이터를 받게 되면
message
이벤트가 발생한다.
- WebSocket 을 통해 데이터를 받게 되면
-
close event
- WebSocket 이 close 되면
close
이벤트가 발생한다.
- WebSocket 이 close 되면
-
error event
- WebSocket 이 에러로 인해 연결이 끊어지면 발생하는 이벤트이다. 에러가 발생하는 경우는 어떤 데이터가 보내지지 못할 때 발생한다.
-
open event
-
Method
-
WebSocket.close()
,WebSocket.send()
-
-
-
Socket.io
- 장점
- Reliable
- Socket.io 는 WebSocket 프로토콜이 이용 가능하지 않다고 판단될 때, HTTP long-polling 으로 fall back 한다. 만약 연결이 lost 된다면, client 에서 자동으로 reconnect 한다.
- 다수의 서버로 하거나 모든 연결된 client 에게 이벤트를 보내는 것이 쉽다
- ㅇㅈㅇㅈ
websocket
은 forEach 로 돌려줘야 하는데 websocket 은 emit 메서드로 쉽게 관리할 수 있어 보임.
- ㅇㅈㅇㅈ
- Reliable
- 장점
참고 : Using WebSockets with React Query
staleTime
을 Infinity 로 설정하고, websocket 을 통해 message
이벤트가 발생할 경우 invalidateQueries 를 명시적으로 호출하여 refetch 하세용
- React Query 쓰면 채팅방에서 window unfocus 시에도
refetchIntervalInBackground
등으로 요청할 수 있을듯 (다만 서비스가 커지면 너무 많은 네트워크 비용이 들지도...)
-
기획에 따라 데이터를 DB 에 저장하지 않는 경우라면 RTC 도 좋은 방법이 될 수 있을 것 같음.
-
RTCDataChannel 을 이용하면 브라우저간 text data 도 주고 받을 수 있음
- 심지어 사진도...!!!
-
socket.io 에 비해...
- 속도가 더 빠를 수 있다.
- 내장 API 이므로 번들링 사이즈가 줄어든다.
-
생각해봐야 할 점
- room 형성이 쉬운지 잘 모르겠음
- 속도 향상이 얼마나 드라마틱하게 변하는가?
- DB 에 채팅 데이터를 저장하는 시점은 언제가 될 것인가?
-
오가는 유저 데이터를 어떤 시점에 DB에 저장할 것인가...?
- rtc 를 사용하여 연결을 유지하며 주기적으로 데이터를 서버에 저장하는 방법도 있을듯
- => 속도 향상 + 이미지나 영상등을 주고받을 때도 서버를 거치는것에 비해 부담 덜 할듯
- 우리는 기획적으로 이미지, 영상을 주고받을 가능성이 매우 크다!!
- web rtc 사용한다면 화상 상담 or 피드백도 가능해진다 !!
- rtc 를 사용하여 연결을 유지하며 주기적으로 데이터를 서버에 저장하는 방법도 있을듯
-
WebRTC + WebSocket + React Query
- Room 만드는 것이 매우 번거롭지 않으면 충분히 할만한 시도인듯...?
- socket.io 에서 지원하는 연결 재시도는 react query 가 충분히 할 수 있다!
- 세 가지 도메인 모두 개발 경험이 부족해 난이도 예측이 안되긴 함... (재밌긴 할듯)