실시간 통신 기술 비교: WebSocket, WebRTC, Supabase Realtime

붕붕·2025년 3월 31일
post-thumbnail

이번 프로젝트에서 만들어야 하는 양방향 통신 기능에서 쓸 수 있는 기술들인 WebSocket, WebRTC, Yjs, Supabase Realtime에 대해 간단히 정리해보았다.

WebSocket

기본 개념

WebSocket은 웹 브라우저와 서버 간에 지속적인 연결을 유지하면서 실시간으로 양방향 통신이 가능한 프로토콜이다.

초기 연결 시에는 HTTP를 사용하지만 연결이 성립된 이후에는 WebSocket 프로토콜로 전환되어 지속적인 데이터 송수신이 가능해진다.

등장 배경

기존의 HTTP 통신 방식에서는 클라이언트가 요청을 보내야만 서버가 응답을 줄 수 있는 구조였다.

따라서, 서버에서 실시간으로 정보를 전달해야 하는 경우 클라이언트가 주기적으로 서버에 요청을 보내야 했고 이러한 방식은 불필요한 트래픽 증가와 서버 부하를 초래했다.

이를 해결하기 위해 등장한 것이 WebSocket이다.

웹소켓이란?

WebSocket은 TCP 기반의 통신 프로토콜이다.

TCP란?
송신자와 수신자가 데이터를 전송하기 전에 통신 가능 여부를 확인하고, 데이터가 순서대로 전달되도록 보장하는 신뢰성 있는 프로토콜이다.

WebSocket은 한 번 연결이 성립되면 지속적인 연결을 유지하기 때문에 클라이언트와 서버 간에 실시간으로 자유롭게 데이터를 주고받을 수 있다.

웹소켓 사용법

WebSocket 초기 연결은 다음과 같은 과정을 통해 이뤄진다.

  1. 클라이언트는 HTTP 요청을 통해 서버에 연결 요청을 보낸다.

  2. 서버가 이를 수락하면, HTTP 프로토콜에서 WebSocket 프로토콜로 업그레이드된다.

-> 이 과정을 핸드셰이킹이라고 부른다.

프로토콜로 wss:// 사용이 권장된다.
이는 TLS(SSL) 보안 계층을 통해 송신할 때 암호화가 되고 수신할 때 복호화가 된다.

대부분의 최신 브라우저는 WebSocket API를 기본적으로 지원하므로 별도의 패키지 설치 없이 다음과 같이 사용할 수 있다.

const socket = new WebSocket("wss://example.com/chat");

단점

브라우저 호환성: WebSocket은 HTML5를 지원하지 않는 구형 브라우저에서는 사용할 수 없다.

서버 리소스 부담: 연결이 지속되기 때문에 다수의 클라이언트와 WebSocket 연결을 유지하려면 서버 자원이 많이 소모된다.

에러 처리의 어려움: 연결이 끊어졌을 때, 정확한 종료 사유를 파악하기 어렵기 때문에 안정적인 에러 처리가 쉽지 않다.

WebRTC

기본 개념

WebRTC는 웹 애플리케이션과 사이트가 중간자 없이 브라우저 간에 오디오나 영상 미디어, 임의의 데이터를 교환할 수 있도록 하는 기술이다.
주로 화상 회의, 파일 교환 등에 사용되며 P2P 방식으로 동작한다.

P2P 방식이란?
중앙 서버를 거치지 않고 클라이언트 컴퓨터끼리 직접 통신하는 방식이다.

중개 서버를 거치지 않기 때문에 빠른 속도가 보장되며 HTTPS를 통해 보안도 강화된다. 그러나, 크로스 브라우징 이슈를 해결하기 위해서는 adapter.js 라이브러리 사용이 필수이다. 또한, 초기 연결을 위해 시그널링 서버가 필요하며 이 서버는 실제 데이터를 전달하지 않고 연결을 도와주는 역할을 한다.

단점

  • 크로스 브라우징 이슈: 다양한 브라우저 호환을 위해 adapter.js가 필수
  • 시그널링 서버 필요: 직접 구현해야 하므로 초기 설정이 번거롭다

Yjs

Yjs는 실시간 동시 편집 기능을 제공하는 라이브러리로, 충돌 없이 데이터를 병합하기 위해 CRDT 알고리즘을 사용한다.

서버 측에서는 WebSocket 서버를 구현하고, 이를 y-websocket과 연결하여 사용한다.

병합 방식 비교

  1. OT (Operational Transformation)
  • 시간 순서대로 병합하며 서버가 중간 개입자로 병합 처리를 담당한다.
  1. CRDT (Conflict-free Replicated Data Type)
  • P2P 방식으로 병합하며 중앙 서버 없이 각 클라이언트가 유니크한 값을 기반으로 병합한다.

Supabase Realtime

Broadcast

Broadcast는 발행-구독(Pub/Sub) 패턴을 따른다. 이벤트, 메시지와 같은 정보를 한 번만 전송하여 데이터 보존이 일시적이고 서버 부담이 적다.

roomOne.send({
  type: 'broadcast',
  event: 'test',
  payload: { message: 'hello, world' },
})

Presence

Channel 내에서 개별 사용자의 상태를 공유할 때 사용한다.

사용자의 상태를 지속적으로 공유하고 추적한다.

const presenceTrackStatus = await roomOne.track({
  user: 'user-1',
  online_at: new Date().toISOString(),
})

피그마처럼 유저의 마우스 커서 위치를 실시간으로 공유할 때 사용할 수 있다.

Postgres Changes

Postgres Changes는 Supabase 테이블의 변경사항을 실시간으로 감지하고 클라이언트에 전달한다. JWT가 유효하면 누구나 데이터베이스 변경 사항을 수신할 수 있다.

const allChanges = supabase
  .channel('schema-db-changes')
  .on(
    'postgres_changes',
    {
      event: '*',
      schema: 'public',
    },
    (payload) => console.log(payload)
  )
  .subscribe()

Broadcast vs Presence 선택 기준

기본적으로는 Broadcast를 사용하고, 특별히 필요한 경우에만 Presence를 사용하는 것을 권장한다.

Presence는 CRDT(Conflict-free Replicated Data Type) 라는 메모리 기반 구조를 활용해 공유 상태를 관리한다. 상태 변경 시 기존 상태와의 차이를 계산하여 Broadcast를 통해 필요한 변경만 전송하는 구조이기 때문에, 계산 부하가 크다.

따라서 Presence를 사용할 경우에는 변경 빈도를 줄이기(throttling) 를 권장한다.

참고 자료
https://ko.javascript.info/websocket
https://aws-hyoh.tistory.com/57
https://wormwlrm.github.io/2021/01/24/Introducing-WebRTC.html
https://supabase.com/docs/guides/realtime/concepts

profile
프론트엔드 개발자(가 되고 싶은 대학생)

0개의 댓글