[django] webRTC, websocket, django-channel (1)

EMMA·2022년 5월 10일
1

🖥 화상 채팅을 구현해보자.

화상 채팅을 위한 초기 셋팅을 첫 날 하고,
오늘은 coturn 서버를 구축하면서 굉장히 많은 에러를 마주했다.
그래서 정리할 겸 webRTC와 관련 내용에 대해 정리해보고자 한다.


webRTC를 사용하려면 websocket이 필요하다

webRTC는, P2P 간 (브라우저 간)에 데이터, 오디오, 영상 등을 자유롭게 교환하고 스트리밍할 수 있게 하는 기술이자 API이다.

그래서 실시간 채팅/영상 채팅 등에 사용되는데, webRTC를 사용하려면 아래 열거한 서버 및 개념들에 대한 이해가 필요하다.

  • Signaling server (websocket)
  • STUN/TURN server (for ICE)

이미지 출처: https://medium.com/monday-9-pm/%EC%B4%88%EB%B3%B4-%EA%B0%9C%EB%B0%9C%EC%9E%90-webrtc-%EC%8B%9C%EB%8F%99%EA%B1%B8%EA%B8%B0-ebefe6feadf7

Peer to Peer communication

P2P communication이라는 것은 한 마디로 서버를 거치지 않고 브라우저끼리 바로 통신하는 것을 말한다. 이 때 서로의 IP주소가 필요한데, IP주소를 알려면 각 컴퓨터가 어떻게 IP 주소를 할당 받는지 알아야 한다.

일반적으로 우리는 ISP(SK, KT 등)에게 공인 IP를 제공받고(NAT), 라우터를 통해 각 기기 별로 사설 IP를 할당(DHCP) 받는다.

그런데 어떤 라우터는 사설 IP/port 넘버와의 연결을 차단하는 방화벽이 설정되어 있어, 이를 통과하는 방법이 필요한데 이 때 STUN 서버가 필요한 것이다.

  • STUN: 외부 네트워크 주소, 즉 공인 IP로 바로 연결
  • TURN: 트래픽을 중계해주는 서버, 즉 내 정보를 상대에게 전달하는 역할을 위임받은 서버로 STUN이 실패했을 때 대안으로 사용됨

STUN 서버(Session Traversal Utilities for NAT)는 한 마디로 외부 네트워크를 알아내기 위한 서버다. 공인 IP 정보를 주고 받고 바로 P2P 통신을 가능하게 해 편리하지만, 위에서 언급한 방화벽 문제 등으로 인해 통신이 불가능할 수 있다.

반면 TURN (Traversal Using Relay NAT) 서버는 STUN서버보다 더 안전한 방법으로, 내 정보를 위임받아 대신 전달해준다. STUN 서버를 통해 정보를 알아내지 못했을 경우 대안으로 사용되는 방법이다.


통신을 성공시키기 위한 ICE

이러한 관계에서 call_offer하는 사람을 caller, call_answer 하는 사람을 callee 라고 한다.

caller가 callee에게 offer를 보내면, 통신을 위한 최적의 경로를 탐색하기 시작하는데 이 때 위에 설명했던 과정을 통해 수집된 IP 주소 및 경로가 collect된다. (ICE, Interactice Connectivity Establishment)

이미지 출처: https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Signaling_and_video_calling#the_signaling_server

STUN, TURN 서버 등을 통해서 수집된 경로들 중 최적의 경로가 선택되면,
데이터/미디어를 교환하기 위한 과정이 남게된다.

데이터/미디어 교환은 SDP 프로토콜을 통해 이뤄진다. SDP는 Session Description Protocol로, 송신/수신 여부, 멀티미디어 코덱, 해상도, 형식 등의 정보를 담아서 전송하는 프로토콜이다.

이 모든 과정을 signaling 이라고 한다. signaling은 webRTC에서 지원하지 않는 기능이기 때문에 websocket을 통해 이를 구현해야 한다.


결국, 필요한 것은 무엇?

  • Signaling server (by websocket)
  • STUN/TURN server (by coturn)
  • Channel layer (by django-channel, redis)

결국 webRTC을 사용하려면,
signaling을 진행하게 해줄 서버(websocket 사용), ICE 후보들을 모두 모아줄 STUN/TURN 서버가 필요하다.

그리고 django에서 websocket을 연동해 signaling을 구현하려면 django-channels 라는 라이브러리를 사용해야 한다.
redis는 django-channels에서 추천하는 backend로 key-value 구조의 데이터를 저장하는 저장소다.

Overall flow

그래서 flow를 정리하면 아래와 같다
1 클라이언트 - 서버 간 http 통신이 이뤄지면, websocket 연결
2 handshake 후에 http -> websocket 프로토콜로 switching
3 websocket을 통한 caller - callee 통신 시도
4 ICE candidates 중에서 최적 경로 선택, 통신 연결



참고 자료
https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Signaling_and_video_calling#the_signaling_server
https://wormwlrm.github.io/2021/01/24/Introducing-WebRTC.html

profile
예비 개발자의 기술 블로그 | explore, explore and explore

1개의 댓글

comment-user-thumbnail
2023년 3월 16일

감사합니다!

답글 달기