Skip to content

[채팅 스터디] 어떤 기술을 사용할까 _종호

Jongho Park edited this page Jan 10, 2022 · 2 revisions
  • 작성자: @jonghopark95
  • 작성일: 2022.01.10
  • Description: 채팅 기능 - 어떤 기술을 사용할까

정리 안하고 막 쓰는중...

다양한 Data Retrieve 기술 분석

참고

HTTP

HTTP 는 Stateless 한 연결이다.

Polling 이란

=> 하나의 장치가 충돌 회피, 동기화 처리 등의 목적으로 다른 장치의 상태를 주기적으로 검사하여 일정한 조건을 만족할 때 송수신 처리를 하는 방식

  • Regular Polling
    • 주기적으로 Client 에서 Server 에게 계속해서 데이터 요청을 하는 것.
    • 단점
      • 계속해서 주기적으로 요청하기 때문에 네트워크, 서버 리소스 낭비를 가져온다.
  • Long Polling
    • Client 가 백엔드에게 요청을 하는데, 이 순간 서버는 두 가지 상황에 따라 대처를 다르게 한다.
      • 만약 데이터가 있다면, 즉시 이를 반환한다.
      • 만약 데이터가 없다면, 해당 연결을 open 상태로 유지한다. 만약, 백엔드에서 어떤 변화가 일어난다면 이 연결을 이용해 client 에게 반환한다.
      • 클라이언트는 데이터를 받으면 연결을 유지하기 위해 다시 요청한다.
    • 장점
      • Short Polling 과는 다르게 Client 에서 Server 에게 지속적으로 데이터 요청을 하지 않아도 된다.
    • 단점
      • 만약, 반환되는 데이터가 매우 빠르게 발생한다면 오히려 Short Polling 보다 많은 데이터를 보내게 된다.
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

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

WebSocket 을 사용하기 위한 방법들

참고 :

  • npm - ws

    • 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, ...
  • MDN - WebSocket API

    • JS 에는 WebSocket API 가 있다. WebSocket constructor 로 server 와 websocket 통신을 할 수 있다.

    • Event

      • open event
        • WebSocket 이 오픈되고 연결이 일어나면 open 이벤트가 발생한다.
      • message event
        • WebSocket 을 통해 데이터를 받게 되면 message 이벤트가 발생한다.
      • close event
        • WebSocket 이 close 되면 close 이벤트가 발생한다.
      • error event
        • WebSocket 이 에러로 인해 연결이 끊어지면 발생하는 이벤트이다. 에러가 발생하는 경우는 어떤 데이터가 보내지지 못할 때 발생한다.
    • Method

      • WebSocket.close(), WebSocket.send()
  • Socket.io

    • 장점
      • Reliable
        • Socket.io 는 WebSocket 프로토콜이 이용 가능하지 않다고 판단될 때, HTTP long-polling 으로 fall back 한다. 만약 연결이 lost 된다면, client 에서 자동으로 reconnect 한다.
      • 다수의 서버로 하거나 모든 연결된 client 에게 이벤트를 보내는 것이 쉽다
        • ㅇㅈㅇㅈ websocket 은 forEach 로 돌려줘야 하는데 websocket 은 emit 메서드로 쉽게 관리할 수 있어 보임.

WebSocket + React Query

참고 : Using WebSockets with React Query

staleTime 을 Infinity 로 설정하고, websocket 을 통해 message 이벤트가 발생할 경우 invalidateQueries 를 명시적으로 호출하여 refetch 하세용

  • React Query 쓰면 채팅방에서 window unfocus 시에도 refetchIntervalInBackground 등으로 요청할 수 있을듯 (다만 서비스가 커지면 너무 많은 네트워크 비용이 들지도...)

WebRTC...?

  • 기획에 따라 데이터를 DB 에 저장하지 않는 경우라면 RTC 도 좋은 방법이 될 수 있을 것 같음.

  • RTCDataChannel 을 이용하면 브라우저간 text data 도 주고 받을 수 있음

    • 심지어 사진도...!!!
  • socket.io 에 비해...

    • 속도가 더 빠를 수 있다.
    • 내장 API 이므로 번들링 사이즈가 줄어든다.
  • 생각해봐야 할 점

    • room 형성이 쉬운지 잘 모르겠음
    • 속도 향상이 얼마나 드라마틱하게 변하는가?

생각해봐야 할 점

  • DB 에 채팅 데이터를 저장하는 시점은 언제가 될 것인가?
  • 오가는 유저 데이터를 어떤 시점에 DB에 저장할 것인가...?

    • rtc 를 사용하여 연결을 유지하며 주기적으로 데이터를 서버에 저장하는 방법도 있을듯
      • => 속도 향상 + 이미지나 영상등을 주고받을 때도 서버를 거치는것에 비해 부담 덜 할듯
      • 우리는 기획적으로 이미지, 영상을 주고받을 가능성이 매우 크다!!
      • web rtc 사용한다면 화상 상담 or 피드백도 가능해진다 !!
  • WebRTC + WebSocket + React Query

    • Room 만드는 것이 매우 번거롭지 않으면 충분히 할만한 시도인듯...?
    • socket.io 에서 지원하는 연결 재시도는 react query 가 충분히 할 수 있다!
    • 세 가지 도메인 모두 개발 경험이 부족해 난이도 예측이 안되긴 함... (재밌긴 할듯)
Clone this wiki locally