최종 프로젝트 기획이 끝났습니다. 해당 기획 내부에서는 실시간 통신을 기반으로 구현해야하는 기능이 있기 때문에 그 기능을 위해 양방향 통신을 공부 해볼까 합니다.
웹소켓은 HTTP의 Polling이라는 방식의 보완을 위해 나온 방식으로 클라이언트가 서버와 동등하게 메세지를 주고 받을 수 있는 양방향 통신이 가능하게 합니다.
클라이언트가 서버에 웹소켓을 연결하자는 HTTP를 보내고 서버가 이에 응하는 HTTP를 보내는 HandShake 과정을 거쳐 HTTP가 아닌 WebSocket 프로토콜을 사용하여 통신합니다.
해당 HandShake 과정이 이러난 후엔 서버에서 클라이언트에 요청을 먼저 보낼 수 있게 됩니다.
WebSocket에서 통신은 HTTP와 다르게 헤더의 크기가 작고 오버헤드가 적기 때문에 효율적인 통신이 가능합니다.
해당 연결은 종료가 이루어지기 전까지 연결을 유지하고, 그 과정도 적은 리소스를 소모하기 때문에 Polling에 비해 서버에 주는 부담이 현저히 적습니다.
웹소켓은 OSI 7계층 중, 전송 계층에서 작동하고 TCP 소켓을 기반으로 작동하기 때문에 데이터 전송에 신뢰성이 높고 데이터 순서가 보장이 됩니다.
메세지의 크기가 제한이 되어 있고, 여러 환경마다 웹소켓 메세지의 크기에 제약이 있어 큰 메세지는 분할 전송 및 타 프로토콜을 사용해야 합니다.
웹소켓의 기본적으로 암호화가 되어 있지 않은 점도 있으니 HTTPS 처럼 암호화가 필요하다면 WS가 아닌 WSS를 사용하여야 합니다.
많은 사용자가 동시 접속해 있으면 실시간으로 연결하는 WS의 연결이 많아지고 그 만큼 서버에도 부하가 지속되니 고려해야 할 부분입니다.
실시간 통신 프로토콜 웹소켓을 배우면서 추가로 고려할 웹RTC도 간단히 찾아보았습니다.
우선 웹RTC는 P2P 방식을 통해 음성, 영상, 파일등 데이터를 주고 받는 방식입니다.
웹RTC는 MediaStream, RTCPeerConnection, RTCDataChannel을 사용하여 데이터 교환이 이루어집니다.
또, 이 객체의 교환이 가능하도록 처리해주는 과정을 Signaling이라 합니다.
연결을 요청하는 Caller, 연결을 받는 Callee가 존재하고 해당 둘을 연결하기 위해 중간에 서버가 필요합니다.
P2P 방식이라 따라올 수 있는 문제점이 크게 대두됩니다.
개인의 네트워크 주소(IP)를 바탕으로 연결하여 통신을 하여야 하는데, 개인의 환경, 방화벽등 여러 요소로 인해 연결이 쉽지 않아 보입니다.
하지만 이러한 걱정을 해결해 주는 것들이 STUN Server, TURN Server입니다.
STUN Server는 자신의 Public IP를 확인하기 위한 서버입니다. STUN 서버로 요청을 보내 자신의 Public IP를 확인한 후, 해당 IP를 통해 시그널링을 합니다.
TURN Server는 Public한 TURN Server를 경유하여 본인의 Public IP와 TURN Server의 통신으로 상대방과 연결합니다.
이러한 방법으로 직접 서로 데이터를 주고 받으며 웹RTC는 실시간 통신을 이루어냅니다.
프로젝트에서는 라이브러리를 많이 사용합니다. 복잡한 기능을 간단하게 구현하게 해주는 라이브러리는 프로젝트와 땔래야 떌 수 없는 관계로, 실시간 통신을 지원해주는 라이브러리를 알아보았습니다.
CRDT: Conflict-free Replicated Data Types 알고리즘을 기반으로 웹소켓과 웹RTC 방식을 모두 지원해주는 라이브러리입니다.
웹RTC를 사용 했을 때에 Caller와 Callee 사이에서 다리 역할을 해주는 시그널링 서버 구축을 위한 데모 서버도 제공해줍니다.
데이터 충돌을 알고리즘을 통해 자동으로 처리해주고, 데이터의 일관성, 연결된 사용자끼리 데이터의 동기화도 보장합니다.
세부적인 코드는 단시간에 확인이 어렵지만 내일 다같이 사용해볼까 합니다.
라이브러리는 아니지만 실시간 통신 서비스를 간단히 사용할 수 있어 넣었습니다.
Supabase Realtime은 웹소켓 기반으로 통신을 합니다.
덕분에 클라이언트와 데이터베이스의 변경 사항을 즉각적으로 수신할 수 있어 최신 상태를 빠르게 반영할 수 있습니다.
그렇다면 supabase realtime은 단순히 웹소켓이 연결되는 서버로 끝이 나는 걸까요?
PostgreSQL의 Logical Replication 기능을 통해 데이터베이스의 변경을 감지합니다. 그 과정에서 WAL(Write-Ahead Log)를 활용하여 모든 데이터 변경을 캡처하고 Elixir 기반의 실시간 서버로 캡처된 이벤트를 처리합니다. 해당 서버는 Pub/Sub 모델을 사용해, 변경 이벤트를 채널로 브로드캐스트 하여 데이터 변경을 알립니다.
이처럼 supabase의 realtime 서비스도 웹소켓 프로토콜을 핵심으로 하여 실시간 데이터 동기화 구현을 할 수 있게 해주고 복잡한 실시간 통신 로직을 손쉽게 사용자에게 통합할 수 있도록 지원합니다.
이번 프로젝트에서는 협업 툴과 비슷한 모습을 하고 있기에 웹RTC보다는 웹소켓이 더욱 더 잘 어울리는 실시간 통신 기술이 아닐까 생각합니다. 내일 팀원들과 해당 내용을 통해 더욱 이야기를 하고 프로젝트에서는 웹소켓 서버를 하나 새로 만들것인지, 아니면 supabase의 realtime 서비스를 활용 할 것인지 의논해보아야 하겠습니다.
양방향 통신은 예전 HTTP 통신만 사용하던 시절과 확실히 나누어주는 기준인 것 처럼 느껴집니다. 그런 느낌이 드는 만큼 더더욱 이 양방향 통신을 정복하여 최신 기술에 더욱 다가가는 프론트엔드 개발자가 되고 싶습니다.