WebRTC

jiyoon·2024년 11월 15일

KG 지식그래프

목록 보기
6/6

WebRTC와 React + Socket.io + Flask 통신 구조


1. WebRTC란?

WebRTC(Web Real-Time Communication)는 브라우저 간의 실시간 P2P 통신을 지원하는 기술입니다. 이를 통해 별도의 플러그인 없이 브라우저에서 실시간 오디오, 비디오, 데이터 통신을 가능하게 합니다.


2. WebRTC의 핵심 요소

2.1 Offer, Answer, ICE Candidate

  • Offer

    • WebRTC 연결을 시작하려는 클라이언트가 생성하는 초기 요청 메시지입니다.
    • 네트워크 정보와 미디어 정보(예: 비디오/오디오 설정)가 포함됩니다.
  • Answer

    • Offer를 받은 클라이언트가 응답으로 보내는 메시지입니다.
    • 자신의 네트워크와 미디어 정보를 포함하여 연결을 수락합니다.
  • ICE Candidate

    • P2P 연결을 최적화하기 위해 네트워크 경로(IP 주소와 포트)를 제공하는 정보입니다.
    • 여러 ICE Candidate를 교환하여 최적의 경로를 설정합니다.

3. Signaling 서버

3.1 역할과 개념

  • Signaling 서버란?

    • 두 클라이언트(A와 B)가 WebRTC 연결을 시작하기 전에 서로의 연결 정보(Offer, Answer, ICE Candidate)를 교환하는 중간 다리 역할을 합니다.
    • 실제 미디어 데이터(비디오, 오디오)는 Signaling 서버를 통하지 않고 브라우저 간 직접 전송됩니다.
  • Socket.io의 활용

    • Signaling 서버 구현 시 자주 사용되는 실시간 통신 도구로, WebSocket 기반 데이터 교환을 간소화합니다.

4. WebRTC 통신 흐름

4.1 React + Socket.io + Flask의 통신 흐름

1. React 클라이언트와 Flask 서버 연결

  • 각 클라이언트(A와 B)는 React에서 socket.emit()으로 메시지를 전송.
  • Flask는 socketio.on()으로 메시지를 수신 후 상대 클라이언트에게 전달.

2. Signaling 과정

  • A 클라이언트가 Offer를 생성하여 Flask 서버에 전송.
  • Flask가 클라이언트 B로 Offer를 전달.
  • 클라이언트 B가 Answer를 생성해 Flask 서버에 전송.
  • Flask가 Answer를 클라이언트 A로 전달.
  • 양쪽 클라이언트가 ICE Candidate를 주고받아 최적의 경로를 설정.

3. P2P 연결 완료

  • Signaling 이후 클라이언트 간 P2P 연결이 성립됩니다.
  • 이후 데이터(비디오, 오디오, 메시지)는 서버를 거치지 않고 브라우저 간 직접 전송됩니다.

5. P2P 통신

5.1 RTCPeerConnection: P2P 통신의 중심

- LocalDescription과 RemoteDescription

  • LocalDescription
    : 현재 클라이언트의 WebRTC 연결 상태(Offer 또는 Answer)를 나타냄.
  • RemoteDescription
    : 상대방의 WebRTC 연결 상태(Offer 또는 Answer)를 나타냄.
// Offer 생성 및 설정
const offer = await peerConnection.createOffer();
await peerConnection.setLocalDescription(offer);

// RemoteDescription 설정
await peerConnection.setRemoteDescription(offer);

- ICE Candidate 교환

  • 네트워크 경로(IP와 포트 정보)를 제공하여 방화벽과 NAT 문제를 해결.
  • 최적의 경로 설정 후 P2P 데이터 전송 시작.

5.2 P2P 데이터 전송 흐름

  • 미디어 데이터 전송
    : WebRTC를 사용해 실시간 비디오 및 오디오 데이터를 전송.

  • 데이터 채널 전송
    : 텍스트 데이터, 파일 등 일반 데이터를 전송 가능.


6. NAT 및 방화벽 문제 해결

6.1 STUN 서버와 TURN 서버

- STUN 서버

  • 공인 IP와 포트를 확인해 클라이언트 간 P2P 연결을 돕습니다.

- TURN 서버

  • P2P 연결이 불가능할 경우 데이터를 중계.
  • 성능은 다소 저하될 수 있으나 연결이 항상 보장됩니다.
const peerConnection = new RTCPeerConnection({
    iceServers: [
        { urls: "stun:stun.l.google.com:19302" },
        { urls: "turn:turnserver.example.com", username: "user", credential: "pass" },
    ],
});

7. React + Socket.io + Flask의 장점

- React

  • WebRTC를 UI와 연동하여 사용자 경험을 개선할 수 있습니다.
  • Electron을 통해 패드에서도 동일한 화면을 출력할 수 있습니다.

- Socket.io

  • 브라우저 간 Offer/Answer/ICE Candidate 교환을 실시간으로 처리.
  • 재연결 및 브라우저 호환성을 지원하여 안정적인 통신 가능.

- Flask

  • GraphRAG 기능을 위한 백엔드 처리.
  • REST API와 Socket.io의 공존이 가능해 확장성 높은 아키텍처 구축 가능.

8. React + Socket.io + Flask 구현 예시

8.1 React 클라이언트 코드

import React, { useRef } from "react";
import io from "socket.io-client";

const socket = io("http://localhost:5000");

const WebRTCApp = () => {
  const localVideoRef = useRef(null);
  const remoteVideoRef = useRef(null);

  const startCall = async () => {
    const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
    localVideoRef.current.srcObject = stream;

    const peerConnection = new RTCPeerConnection({
      iceServers: [{ urls: "stun:stun.l.google.com:19302" }],
    });

    stream.getTracks().forEach((track) => peerConnection.addTrack(track, stream));

    const offer = await peerConnection.createOffer();
    await peerConnection.setLocalDescription(offer);
    socket.emit("offer", offer);

    socket.on("answer", async (answer) => {
      await peerConnection.setRemoteDescription(answer);
    });

    peerConnection.onicecandidate = (event) => {
      if (event.candidate) socket.emit("candidate", event.candidate);
    };

    socket.on("candidate", async (candidate) => {
      await peerConnection.addIceCandidate(candidate);
    });

    peerConnection.ontrack = (event) => {
      remoteVideoRef.current.srcObject = event.streams[0];
    };
  };

  return (
    <div>
      <video ref={localVideoRef} autoPlay muted></video>
      <video ref={remoteVideoRef} autoPlay></video>
      <button onClick={startCall}>Start Call</button>
    </div>
  );
};

export default WebRTCApp;

8.2 Flask 서버 코드

from flask import Flask
from flask_socketio import SocketIO

app = Flask(__name__)
socketio = SocketIO(app, cors_allowed_origins="*")

@app.route("/")
def index():
    return "WebRTC Signaling Server is Running"

@socketio.on("offer")
def handle_offer(data):
    socketio.emit("offer", data, broadcast=True)

@socketio.on("answer")
def handle_answer(data):
    socketio.emit("answer", data, broadcast=True)

@socketio.on("candidate")
def handle_candidate(data):
    socketio.emit("candidate", data, broadcast=True)

if __name__ == "__main__":
    socketio.run(app, host="0.0.0.0", port=5000)

9. 결론

React + Socket.io + Flask 조합은 WebRTC 프로젝트에 적합한 강력한 조합입니다.

  • 확장성
    Signaling 서버로서 역할을 수행하며, React와 연동해 실시간 통신 구현.

  • 호환성
    Electron을 통해 패드에서도 동일한 화면 제공 가능.

  • 효율성
    Signaling 이후 P2P로 데이터 전송, 서버 부하 감소와 지연 시간 최소화.

profile
주니어 개발자

0개의 댓글