너굴 개발 일지

[socket.io] 옵션별 동작 방식 본문

기타

[socket.io] 옵션별 동작 방식

너굴냥 2024. 10. 21. 14:23

실무에서 socket.io를 통해 콘텐츠 업로드시 트랜스코딩 진행률 데이터를 전달 받습니다. 관련해서 socket.io를 공부하며 정리한 글입니다.

정의

양방향 통신을 하기 위해 웹 소켓 기술을 활용한 Node.js 라이브러리로 JS를 이용해 브라우저 종류에 상관없이 실시간 웹 구현이 가능하다.

Websocket이라는 HTML5 표준 기술을 이용할 수도 있으나 일부 구형 브라우저나 OS에 따라 지원되지 않을 수도 있다는 단점이 있다.

(브라우저 호환성을 보면 거의 다 지원하는 수준인 것 같다.)

https://developer.mozilla.org/ko/docs/Web/API/WebSocket

 

 

동작 방식

  1. HTTP long-polling 방식으로 서버와 연결 시도 (HTTP 프로토콜 사용)
  2. WebSocket으로 업그레이드가 가능한 경우 업그레이드 진행

Polling

  • 클라이언트가 n초 간격으로 request를 서버로 보내서 response를 전달받는 방식
  • 가장 간단한 방법이지만 언제 통신이 발생할지 예측이 불가능하다는 점에서 클라이언트가 계속적으로 요청을 하기때문에 클라이언트가 많아지면 서버의 부담이 급증한다.
  • http 오버헤드 발생 가능성도 있다. (정보의 신뢰성 판단을 위한, 보내지는 헤더 같은 정보 때문에 오히려 데이터량이나 처리시간이 증가)

Long Polling

  • Polling과 비슷한 기법이나 실시간으로 데이터를 처리할 수 있는 방식이다.
  • Long Polling은 클라이언트에서 서버로 일단 http request를 보내고 이 상태로 계속 기다리다가 서버에서 해당 클라이언트로 전달할 이벤트가 있다면 그 순간 response 메세지를 전달하며 연결이 종료된다.
  • 해당 작업이 완료된 이후에는 클라이언트에서 곧바로 다시 http request를 보내 서버의 다음 이벤트를 기다리게 되는 작업 방식이다.
  • Polling보다는 서버의 부담이 줄어든다는 장점이 있지만 클라이언트에게 동시에 많은 양의 메세지가 올 경우 Polling과 별 차이가 없게되며, 다수의 클라이언트에게 동시에 이벤트가 발생될 경우에는 곧바로 다수의 클라이언트가 서버로 접속을 시도하게 되면서 서버의 부담이 급증하게 된다.

WebSocket

  • 양방향 통신이 가능하며 프로토콜을 통해 웹소켓 포트에 접속해 있는 모든 클라이언트에게 이벤트 방식으로 응답한다.
  • 최초 접속이 일반 http request를 통해 handshaking과정을 통해 이루어 지기 떄문에, 기존의 80, 443 포트로 접속을 하므로 추가로 방화벽을 열지 않고도 양방향 통신이 가능하고, http 규격인 CORS적용이나 인증등의 과정을 기존과 동일하게 가저갈 수 있는것이 장점이다.

 

특징

Packet buffering

  • 클라이언트 연결이 끊어졌을 때 패킷은 자동으로 버퍼링되며 다시 연결 되었을 때 전송된다.

 

회사에서 사용되는 socket.io 설정

0.9.16 버전으로 엄청 오래된 버전이다. 아래는 관련 docs 같은데 자세하지는 않다... 아래 옵션값은 ms 기준인 것 같지만 자세한 확인 필요

https://www.npmjs.com/package/socket.io/v/0.9.1

https://github.com/socketio/socket.io-client/tree/0.9.16

  • heartbeatTimeout: 60000 (ms)
    • 클라이언트와 서버가 연결된 후, 서버가 클라이언트로부터 정기적인 heartbeat 신호(ping/pong 메시지)를 받지 못했을 때 연결이 끊겼다고 판단하는 시간
    • heartbeat timeout이 30초로 설정되어 있다면 서버는 클라이언트로부터 30초 동안 아무 신호도 받지 못하면 연결이 끊겼다고 판단
  • heartbeatTimeoutTimer : 25 (?)
  • closeTimeout: 60000 (ms)
    • 연결이 끊긴 후에 재연결을 허용할 때까지 기다리는 시간
    • closeTimeout이 60초로 설정되어 있다면, 연결이 끊긴 후 60초 동안 클라이언트가 다시 연결할 기회를 준다. 이 시간이 지나면 클라이언트는 새로운 연결을 시도해야 한다.
  • connectTimeoutTimer : 18 (?)
  • connect timeout: 10000 (ms)
    • 클라이언트가 서버에 연결을 시도할 때, 특정 시간 안에 연결이 완료되지 않으면 연결 시도를 포기하는 시간 제한
    • connect timeout이 5000ms(5초)로 설정되어 있다면 클라이언트가 서버에 5초 동안 연결되지 않으면 연결 시도를 포기하고 에러로 처리한다.
  • reconnection delay: 500 (ms)
    • 서버에 다시 연결을 시도하기 전의 delay 시간이다. 다음 재연결에 대해 지수 백오프 알고리즘을 사용하며, 재연결 시도할 때마다 값이 더해진다. (500 > 1000 > 2000 > 4000 > 8000)
  • max reconnection attempts: 10
    • 연결이 끊긴 경우, 최대 재연결 시도 횟수로 마지막 시도 후 실패시 모든 활성화된 전송 방법으로 다시 시도한다.

Event 관련

  • connect
  • connect_failed
    • 마지막 연결 시도 후 연결 시간 초과 발생시 실행 (connectTimeout이 설정된 경우에만 실행)
  • disconnect
  • reconnect
  • reconnect_failed
    • 모든 재연결 시도가 실패하고 서버에 다시 연결할 수 없을 때 발생
  • error

 

테스트

현재 push 서버는 버전이 오래되어 문서가 자세하지 않음… 따라서 직접 테스트 진행

  polling websocket
네트워크 offline시 socket 연결 바로 끊김 여부 일정 시간 이후 disconnect (connect timeout이 적용되는 것 같음…) 일정 시간 이후 disconnect (heartbeatTimeout이 적용되는 것 같음…)
TR push 알림 받는 중 네트워크 offline 한 경우 네트워크 offline시 push 알림 못받음
disconnect 후 reconnect되어도 이전 push 알림 못받음
네트워크 offline시 push 알림 못받음
disconnect 되기 전 네트워크 online 전환하면 이전 push 알림 받게됨
disconnect 후 reconnect된 경우 이전 push 알림 못받음
disconnect 알림 O O
reconnect 알림e O O