1P by GN⁺ 1시간전 | ★ favorite | 댓글 1개
  • WebRTC는 회의 통화처럼 낮은 지연을 우선해 네트워크가 나쁠 때 오디오 패킷을 적극적으로 버리지만, Voice AI에서는 느린 응답보다 음성 프롬프트 손상이 응답 품질을 더 크게 해칠 수 있음
  • TTS는 실시간보다 빠르게 오디오를 만들 수 있어 클라이언트 버퍼링으로 짧은 네트워크 장애를 숨길 수 있지만, WebRTC는 도착 시간 기준 렌더링과 작은 지터 버퍼 때문에 패킷을 제때 보내도록 인위적으로 대기해야 함
  • WebRTC는 임시 포트, ICE, DTLS, SCTP 등으로 연결 설정과 운영이 복잡하며, 단일 포트 다중화에서는 STUN, SRTP/SRTCP, DTLS, TURN 패킷을 각 연결로 라우팅하기 어려움
  • OpenAI가 빠른 연결 설정을 요구해도 WebRTC는 시그널링과 미디어 서버 절차를 합쳐 최소 8 RTT가 들 수 있으며, P2P 지원 구조 때문에 서버가 고정 IP를 가져도 같은 절차를 거쳐야 함
  • 대안으로 WebSocketsQUIC/WebTransport가 제시되며, QUIC은 CONNECTION_ID, QUIC-LB, preferred_address를 통해 단일 포트, 주소 변경, 상태 없는 로드밸런싱, anycast와 unicast 조합을 더 단순하게 지원함

WebRTC가 Voice AI에 맞지 않는 이유

  • WebRTC는 회의 통화처럼 빠른 왕복 대화에 맞춰 설계되어, 네트워크 상태가 나쁠 때 지연을 낮게 유지하려고 오디오 패킷을 적극적으로 버림
  • Voice AI에서는 사용자가 느린 응답을 조금 더 기다리더라도 프롬프트가 정확히 전달되는 편이 더 중요함
    • 예를 들어 “세차장에 걸어갈지 운전해 갈지” 같은 음성 프롬프트가 손상되면, 이후 응답 품질도 나빠질 수 있음
  • 브라우저의 WebRTC 오디오 구현은 실시간 지연을 강하게 전제하며, Discord에서 시도했을 때 WebRTC 오디오 패킷 재전송은 불가능했다고 함
    • 업데이트로 일부 WebRTC 관계자들은 오디오 NACK 활성화가 가능할 수 있다고 봤지만, Discord에서는 올바른 SDP 조작 방법을 찾지 못했고 WebRTC 지터 버퍼가 매우 작다는 한계도 남음
  • Voice AI 에이전트가 언젠가 대화 수준의 지연 시간에 도달하더라도, 지연을 줄이는 데는 트레이드오프가 있으며 음성 프롬프트를 일부러 열화시키는 선택이 가치 있는지는 불확실함

TTS와 WebRTC의 버퍼링 문제

  • 텍스트 음성 변환(TTS)은 실시간보다 빠르게 오디오를 생성할 수 있음
    • 예를 들어 GPU가 2초 동안 8초 분량의 오디오를 생성한다면, 이상적으로는 생성 중인 2초 동안 오디오를 스트리밍하고 클라이언트가 8초 동안 재생하면서 로컬 버퍼를 확보할 수 있음
    • 이렇게 하면 짧은 네트워크 장애가 있어도 사용자가 알아차리지 못할 가능성이 있음
  • WebRTC는 이런 방식과 맞지 않음
    • WebRTC는 버퍼링이 없고 도착 시간 기준으로 렌더링하며, 타임스탬프는 강한 재생 기준이 되지 않는다고 봄
    • 비디오까지 포함되면 문제가 더 까다로워짐
  • OpenAI 같은 서비스는 패킷이 재생되어야 할 정확한 시점에 도착하도록, 각 오디오 패킷 전송 전에 인위적으로 대기해야 함
    • 네트워크 혼잡이 생기면 해당 오디오 패킷은 손실되고 재전송되지 않음
  • 결과적으로 인위적 지연을 넣은 뒤 “낮은 지연”을 위해 패킷을 적극적으로 버리는 구조가 되며, 이는 YouTube 영상을 버퍼링하지 않고 화면 공유로 보여주는 것과 비슷함
  • WebRTC는 오디오에 대해 20ms에서 200ms까지 동적으로 조정되는 지터 버퍼를 두며, 이는 네트워크 지터를 완화하기 위한 것이지만 실시간보다 빠르게 전송할 수 있다면 필요하지 않다고 봄

포트와 연결 식별의 한계

  • TCP 서버는 보통 443 같은 포트를 열고 연결을 받으며, 연결은 소스·목적지 IP와 포트 조합으로 식별됨
    • 예: 123.45.67.89:54321 -> 192.168.1.2:443
  • 휴대폰이 WiFi에서 셀룰러로 전환되거나 NAT가 소스 IP·포트를 바꾸면 TCP 연결은 끊기고 새 연결을 맺어야 함
    • TCP와 TLS 핸드셰이크에는 최소 2~3 RTT가 들며, 라이브 스트리밍에서는 사용자가 네트워크 끊김을 느낄 수 있음
  • WebRTC는 이 문제를 풀기 위해 각 연결마다 임시 목적지 포트를 할당하는 방식을 전제함
    • 세션을 목적지 IP·포트만으로 식별하면, 소스 IP·포트가 바뀌어도 같은 사용자로 인식할 수 있음
  • 하지만 OpenAI의 구조와 맞물리면 이 방식은 대규모 운영에서 문제가 됨
    • 서버가 사용할 수 있는 포트 수에는 한계가 있음
    • 방화벽은 임시 포트를 자주 차단함
    • Kubernetes 환경과도 잘 맞지 않음

WebRTC 서비스가 단일 포트 다중화로 가는 이유

  • 많은 서비스는 WebRTC 사양을 그대로 따르지 않고, 여러 연결을 단일 포트에 다중화
  • Twitch에서는 WebRTC 서버를 UDP:443에서 운영했음
    • 원래 443은 HTTPS/QUIC 포트지만, 이렇게 하면 더 많은 방화벽을 통과할 수 있었음
    • Amazon 사내 네트워크는 약 30개 포트만 허용했다고 함
  • Discord는 CPU 코어마다 하나씩 50000-50032 포트를 사용함
    • 이 방식은 더 많은 사내 네트워크에서 차단될 수 있음
  • 단일 포트 다중화의 큰 문제는 WebRTC가 여러 표준을 묶은 구조라는 데 있음
    • UDP 위로 직접 올라가는 프로토콜이 5개 있으며, 패킷이 어떤 프로토콜인지 구분하는 일 자체는 어렵지 않지만 각 패킷을 어떤 연결로 라우팅할지가 어려움
  • 프로토콜별 라우팅 난점

    • STUN
      • 고유한 ufrag를 선택해 이를 기준으로 라우팅할 수 있음
    • SRTP/SRTCP
      • 브라우저가 임의의 ssrc 값을 선택하며, 보통은 이를 바탕으로 라우팅할 수 있음
    • DTLS
      • RFC9146의 광범위한 지원을 기대해야 하는 상황임
    • TURN
      • 구현 경험이 없다고 밝힘
    • OpenAI는 STUN만 파싱하고 이후 DTLS, RTP, RTCP는 캐시된 상태로 불투명하게 처리한다고 밝힘
    • 이는 사용자 소스 IP·포트가 바뀌지 않기를 기대하는 구조로 해석됨
    • 브라우저가 같은 ssrc를 임의 생성할 수도 있음
    • 충돌이 생기고 소스 IP·포트 매핑이 없으면, Discord는 가능한 각 복호화 키로 패킷 복호화를 시도해 맞는 키를 찾는 방식으로 연결을 식별한다고 함

WebRTC 연결 설정의 왕복 지연

  • OpenAI는 “세션이 시작되자마자 사용자가 말할 수 있도록 빠른 연결 설정”을 요구사항 중 하나로 제시했지만, WebRTC 연결 설정에는 최소 8 RTT가 든다고 봄
  • 시그널링 서버 예시

    • WHIP 같은 시그널링 서버 기준으로 다음 왕복이 필요함
      • TCP에 1 RTT
      • TLS 1.3에 1 RTT
      • HTTP에 1 RTT
  • 미디어 서버

    • ICE에 1 RTT
    • DTLS 1.2에 2 RTT
    • SCTP에 2 RTT
    • 일부 프로토콜은 파이프라이닝으로 0.5 RTT를 피할 수 있어 정확한 계산은 복잡하지만, 전체적으로 많은 왕복이 필요함
    • 이 절차는 WebRTC가 P2P를 지원해야 하기 때문에 생기며, 서버가 고정 IP를 갖고 있어도 같은 과정을 거쳐야 함
    • 시그널링 서버와 미디어 서버가 같은 호스트나 프로세스에서 실행될 때는 중복되고 비싼 핸드셰이크가 두 번 일어남

WebRTC를 포크하게 되는 구조

  • WebRTC는 많은 한계 때문에 사실상 프로토콜 포크를 유도한다고 봄
  • WebRTC는 약 45개의 RFC와 TWCC, REMB 같은 사실상 표준 초안으로 구성되어 구현 부담이 큼
  • 브라우저 구현은 Google이 소유하고 Google Meet에 맞춰져 있어, 회의 앱에는 존재론적 위협이 된다고 봄
  • Google Meet을 제외한 회의 앱들이 네이티브 앱 설치를 유도하는 이유도 WebRTC 사용을 피하기 위해서라고 봄
  • Discord는 네이티브 클라이언트에서 WebRTC를 크게 포크해 SDP, ICE, STUN, TURN, DTLS, SCTP, SRTP 등의 대부분을 구현하지 않지만, 웹 클라이언트를 위해서는 여전히 전체를 구현해야 함
  • OpenAI도 자금이 충분하겠지만, WebRTC를 포크하기보다 브라우저 지원이 있는 다른 방식으로 대체하는 편이 낫다고 봄

대안: WebSockets와 QUIC

  • Voice AI에서 WebRTC 대신 시작할 대안으로 WebSockets가 제시됨
    • 기존 TCP/HTTP 인프라를 활용할 수 있음
    • 커스텀 WebRTC 로드밸런서를 만들 필요가 없음
    • Kubernetes와 잘 맞고 확장 가능하다고 봄
  • Head-of-line blocking은 이 맥락에서 단점이 아니라 바람직한 사용자 경험일 수 있다고 봄
    • 음성 프롬프트의 일부가 빠지는 것보다 순서대로 전달되는 편이 더 낫다는 전제임
  • 언젠가 일부 패킷을 드롭하거나 우선순위를 둬야 하는 시점이 오면, OpenAI는 MoQ처럼 WebTransport를 활용해야 한다고 봄
  • QUIC 연결 설정은 QUIC+TLS 1 RTT로 가능해 WebRTC의 다중 핸드셰이크보다 단순함

QUIC Connection ID의 장점

  • QUIC은 소스 IP·포트 기반 라우팅을 버리고, 모든 패킷에 CONNECTION_ID를 포함함
    • CONNECTION_ID는 0~20바이트 길이일 수 있음
    • 중요한 점은 수신자가 이 값을 선택한다는 점임
  • QUIC 서버는 각 연결마다 고유한 CONNECTION_ID를 생성할 수 있음
    • 단일 포트를 쓰면서도 소스 IP·포트가 바뀐 연결을 식별할 수 있음
    • 소스 주소가 바뀌면 TCP처럼 연결을 끊지 않고 QUIC이 자동으로 새 주소로 전환함
  • RFC9146의 아이디어는 QUIC에서 가져온 것이라고 봄

상태 없는 로드밸런싱

  • OpenAI의 로드밸런서는 많은 로드밸런서처럼 공유 상태에 의존함
    • 소스 IP·포트에서 백엔드 서버로 가는 매핑을 저장해야 함
    • 로드밸런서가 재시작하거나 크래시할 수 있으므로 이 매핑 저장소가 필요함
  • OpenAI는 Redis 인스턴스를 사용해 소스 IP·포트와 백엔드 서버 매핑을 저장함
    • 단순하고 쉬운 방식으로 평가함
  • QUIC-LB는 데이터베이스 없이 더 단순한 방식을 제공함
    • 클라이언트가 QUIC 연결을 시작하면 로드밸런서가 패킷을 정상 백엔드 서버로 전달함
    • 백엔드 서버는 핸드셰이크를 완료하면서 자신의 ID를 CONNECTION_ID에 인코딩함
    • 이후 모든 QUIC 패킷에는 백엔드 서버 ID가 들어감
  • 로드밸런서는 암호화 키나 라우팅 테이블 없이 처음 몇 바이트를 디코딩해 해당 서버로 전달하면 됨
    • 서버가 재부팅되어도 이 방식은 유지될 수 있음
  • 상태가 없다는 것은 전역 상태도 없다는 뜻임
    • 로드밸런서가 전역 anycast 주소에서 수신하고, 표시된 백엔드 서버로 전역 전달할 수 있음
    • Cloudflare는 이를 광범위하게 사용한다고 함
  • AWS NLB는 QUIC-LB를 사용하는 QUIC 로드밸런싱을 제공함

Anycast와 Unicast 조합

  • OpenAI 기준으로는 연결을 지역 로드밸런서에 할당하는 구조로 보이며, 기능적으로는 동작하지만 Anycast가 더 나은 접근으로 제시됨
  • QUIC의 preferred_address는 로드밸런싱에 중요한 기능으로 평가됨
  • 동작 방식

    • 전 세계의 여러 백엔드 서버가 같은 anycast 주소 1.2.3.4를 광고함
    • 클라이언트가 1.2.3.4로 연결을 시도하면 인터넷 라우터가 패킷을 서버 중 하나로 전달함
    • 각 QUIC 서버는 고유한 unicast 주소 5.6.7.8도 가질 수 있음
    • anycast는 핸드셰이크에 사용하고, 상태 있는 연결은 unicast로 유지함
  • 예시 흐름

    • 서버는 1.2.3.45.6.7.8에서 QUIC 패킷을 수신함
    • 클라이언트는 1.2.3.4로 QUIC 핸드셰이크 패킷을 보냄
    • 서버는 QUIC 연결을 만들며 preferred_address=5.6.7.8을 알림
    • 클라이언트는 이후 패킷을 5.6.7.8로 보냄
    • 서버가 과부하되어 새 연결을 받고 싶지 않으면 1.2.3.4 광고를 중단하면 됨
    • 기존 연결은 unicast에 있으므로 끊기지 않음
    • anycast 주소가 사실상 헬스체크처럼 동작함
    • 이 구조에서는 별도 로드밸런서가 필요하지 않다고 봄

한계와 결론

  • OpenAI 엔지니어들은 매우 뛰어나며, 즉시 대규모 확장을 해야 하는 압박을 받고 있다고 인정함
  • 다만 Voice AI에서 WebRTC는 명백한 선택처럼 보여도 제품 적합성이 좋지 않고 확장도 어렵다고 봄
  • MoQ도 Voice AI에 완벽히 맞는 것은 아님
    • 1:1 오디오에서는 캐시와 팬아웃 의미론의 많은 부분이 쓸모없음
    • 그래도 QUIC은 사용해야 한다는 결론임
Hacker News 의견들
  • 글을 끝까지 다 읽진 않았지만, 글쓴이가 WebRTC의 목적을 근본적으로는 이해하고 있다고 봄. 본인이 전문가라고 하고 Go/Rust로 SFU를 여러 회사에서 만든 것도 맞겠지만, 기술 이력이 곧 결론의 정당성을 보장하진 않음
    내가 잘못 이해했을 수도 있지만, STUN과 DTLS를 왕복 시간 문제에서 서로 연관된 누적 요인처럼 다루는 듯한데 실제로는 꽤 직교적인 요소임. 또 패킷 재전송이 안 된다는 얘기에 너무 많은 시간을 쓰고, Discord에서 엄청 노력했다는 식으로 반복하는 지점에서 논지를 잃었다고 느낌
    WebRTC의 RTC는 실시간 통신이고, 사람은 가끔 패킷이 빠진 소리보다 밀린 오디오나 속도가 들쭉날쭉한 오디오를 더 싫어함. 여기서는 사람의 말소리를 말하는 것임
    패킷 손실을 감수하기 싫다면 UDP 대신 TCP 기반 프로토콜을 쓰면 됨. 하지만 나쁜 네트워크에서 TCP로 음성을 보내면 수신 쪽은 다음 올바른 패킷을 기다리느라 멈춤이 생김. 몇 초 지연된 뒤 다시 패킷이 오면, 밀린 오디오를 정상 속도로 재생할지, 다른 채널을 따라잡으려고 빠르게 재생할지 결정해야 하는데 보통 사람들은 그런 경험을 선호하지 않음
    WebRTC를 잠깐 잊고 음성에서 TCP와 UDP를 생각해보면, VoIP가 90년대부터 UDP 기반이었던 데는 이유가 있음

  • 먼저 기술적인 부분에 답하자면, WebRTC가 아닌 미래는 있다고 봄. 다만 그 방향이 WebTransport+WebCodecs 등이 가는 방향과 맞는지는 모르겠음
    사용자가 느린/비싼 프롬프트가 정확해지도록 200ms 더 기다리겠다는 말은 내가 받는 피드백과 정반대임. 사용자는 즉각적인 응답을 원함. 응답 생성이나 끼어들기 처리에 지연이 있으면 마법 같은 느낌이 사라짐. 또한 실시간보다 빠르게 보내는 것도 원치 않음. 사용자가 모델을 중간에 끊으면 10초만 재생된 3분짜리 오디오를 보내느라 대역폭을 낭비한 셈이 됨
    TTS가 실시간보다 빠르다는 주장에 대해서는, 최신/지향점의 음성 AI는 글쓴이가 설명한 방식에서 벗어나고 있음: https://research.nvidia.com/labs/adlr/personaplex/ 20ms 단위로 조금씩 입출력하는 쪽임
    사용자의 원본 IP/포트가 바뀌지 않기를 바란다는 부분은 지원됨. ufrag에 대해 새 IP가 들어오면 처리 가능함
    최소 8회 왕복 시간이 걸린다는 말도 틀림: https://datatracker.ietf.org/doc/draft-hancke-webrtc-sped/
    오디오를 WebSocket으로 스트리밍하겠다는 선택은 AEC 같은 기능을 잃고, 복잡성을 클라이언트로 밀어냄. WebRTC의 단순함, 즉 createOffer -> setRemoteDescription 흐름 덕분에 사람들이 쉽게 시작할 수 있음. Realtime API + WebSocket에서는 많은 개발자가 코드가 많고 직접 처리해야 하는 부분 때문에 고생했음
    개인적으로 고르라면 Offer/Answer 모델은 유지하되 DTLS+SCTP 대신 QUIC을 쓰고 싶음. 어쩌면 QUIC 위에서 RTP를 할 수도 있음. 프로토콜 자체에는 강한 선호가 없지만, 훨씬 큰 코드 footprint로 여러 클라이언트와 고객 클라이언트에 코드를 배포하는 방법은 잘 모르겠음

    • 물론 사용자는 낮은 지연 시간을 원하지만, LLM이 잘못 들은 경우도 줄이고 싶어함. 지연 시간과 품질의 절충을 A/B 실험으로 돌릴 수 있으면 좋겠지만, WebRTC는 그 조절 손잡이를 다루기 어렵게 만듦
      TTS 전문가는 아니지만 결과를 조금씩 흘려보내는 이점이 뭔지 모르겠음. 실리콘은 시간 숫자가 얼마나 빨리 증가하는지 신경 쓰지 않음
      클라이언트가 자기 IP 변경을 알고 ICE 재협상을 할 수 있는 경우도 있지만, 모르는 경우가 많고 보통은 서버가 변경을 감지하길 기대함. 그런데 현재 로드밸런서 구성에서는 그게 불가능함. 큰 문제는 아니지만 이미 넘어야 할 절차가 많은 상황에서는 아쉬움
      그 초안이 8 RTT가 아니라 7 RTT라는 뜻이라면, 일부는 파이프라인화할 수 있으니 실제 수치는 더 낮을 수 있음. 하지만 진짜 문제는 P2P가 쓰일 수도 있다는 이유만으로 필수 시그널링 서버와 이중 TLS 핸드셰이크가 생긴다는 점임
      WebRTC가 새 개발자에게 쉬운 이유는 블랙박스 회의 앱이기 때문임. 하지만 OpenAI 같은 큰 회사에서는 그 블랙박스가 더 낮은 수준의 원시 기능으로 고칠 수 있는 문제를 만들기 시작함
      RTP over QUIC은 꼭 실험해보면 좋겠고 도와줄 의향도 있음. 코드 크기가 걱정이라면 브라우저, 언젠가는 OS가 QUIC 라이브러리를 제공함. MoQ에 가까운 쪽으로 바꾸면 QUIC이 단편화, 재전송, 혼잡 제어 등을 처리하므로 애플리케이션은 놀랄 정도로 작아짐
      RoQ/MoQ의 큰 한계는 QUIC이 데이터그램까지 포함해 혼잡 제어를 하기 때문에 GCC를 구현할 수 없다는 점임. 브라우저에서 보낼 때는 당분간 cubic/BBR에 묶이게 됨
    • 사용자가 즉각적인 오답을 200ms 늦은 정답보다 선호한다는 피드백을 정말 받고 있다는 말은 매우 의심스러움
    • 3분이나 20ms 단위로 보낼 필요 없이 약 1초씩 보내면 됨. 20ms씩 보내는 것도, 10분씩 보내는 것도 둘 다 바보 같음
    • WebRTC는 브라우저에 내장된 라이브러리라 해도 복잡함. 클라이언트/서버 음성 상호작용이라면 굳이 쓸 이유를 모르겠음. 음성 샘플은 다른 방식으로 보내고, 재생에는 지터 버퍼 로직 일부만 빌리면 됨
      지금 하는 일이 음성/화상 회의와 1:1 통화인데, WebRTC의 복잡성은 엄청남. 제품을 빨리 시작하게 해주긴 했지만, 이상한 일을 할 때 고치기가 어렵고, 클라이언트용으로 포크까지 해도 그렇다
      TURN에 대해서는 긴 불평을 쓸 수도 있음. 사실 WebRTC 프로토콜 묶음 전체가 존재하지 않는 인터넷을 대상으로 설계된 것 같음
      TURN은 클라이언트가 할당을 요청할 때 임시 포트가 아니라 rendezvous id를 할당해야 함. 그러면 피어는 서비스 포트로 TURN 서버에 접속해 그 rendezvous id에 대한 연결을 요청하면 되고, 클라이언트가 피어 주소를 알고 permission을 추가할 필요가 없음. 종단 간 릴레이 연결까지 필요한 통신이 줄어듦. 고급 클러스터는 id에 정보를 인코딩해 클라이언트와 피어가 각각 자기와 가까운 TURN 서버에 접속하고 서버끼리 연결하게 할 수 있음. 덜 고급인 클러스터는 id와 함께 TURN 서버 IP와 서비스 포트를 공유해야 함
    • 첫 음소 전달과 중요한 정보 전달은 결합될 필요가 없음. TV 정치인들은 이 요령에 매우 능숙해서, 머리가 돌아가기 시작할 때까지 시간을 메우는 상투 문구 세트를 갖고 있음. 우리의 시스템 1이 상호작용에 대한 신뢰를 잃지 않도록 빈틈을 메우기만 하면 됨
  • 실제 표시 타임스탬프와 그것이 실제 시간에 어떻게 대응하는지 알아야 할 필요가 왜 있겠냐는 대목이 뼈아프게 와닿음. WebRTC를 만든 사람 중 누구도 서로 다른 출처의 데이터 스트림을 밀리초 정확도로 동기화해본 적이 없는 듯함
    브라우저에서 웹캠과 IMU 모듈을 이용한 영상 안정화 데모를 만들었는데, video->rtc->browser 경로와 sensor->websocket->browser 경로의 지연 시간이 크게 다르고 일정하지 않았음. 당연한 해법은 센서 데이터에 UTC 타임스탬프를 보내고 브라우저에서 동기화하는 것이지만, 비디오에는 UTC 타임스탬프 기준이 없어 불가능했음
    WebRTC 파이프 양쪽을 모두 제어하면 스트림 시작 시점의 UTC 타임스탬프를 보내는 식의 재미있는 일을 할 수는 있지만, 브라우저 지터는 해결하지 못함. 개념 증명으로는 충분히 동작했지만 전체 해법은 다시 설계해야 했음

  • 이 분야 경험이 많고 특허 출원도 몇 개 있음. Alexa에서는 기기가 서버로 연결을 맺고 계속 열어둔 뒤, wake word를 감지하면 그 연결 위로 사실상 HTTP2/SPDY 비슷한 것을 보냈음. 그래서 사용자가 말을 끝내기 전에 STT 처리를 시작할 수 있었고, 마지막 몇 조각 처리 지연만 남았음
    답변도 같은 연결로 돌아왔음
    OpenAI의 경우 Alexa처럼 지속 연결을 항상 열어두긴 어렵지만, 휴대폰에서 HTTP2를 쓰면 iOS와 Android가 그 연결을 거의 알아서 관리해줌
    글쓴이가 맞음. 실시간 프로토콜은 꼭 필요하지 않고, 모든 데이터를 받는 게 더 중요함. 사용자는 지연이 500ms를 넘기 전까지는 거의 알아차리지 못함. 특히 모바일 시대에는 대부분 사람이 사람 간 실시간 통신에도 지연이 있는 것에 익숙함
    OpenAI나 Anthropic에서 일한다면 연락해도 좋음. 더 자세히 이야기할 수 있음

    • 전송 지연에 너무 집중하다 보니 LLM 파이프라인 자체가 즉시 끝나지 않는다는 점을 잊는 것 같음
      전송 지연은 이미 큰 다른 모든 지연 위에 더해짐
      그래서 전체 파이프라인의 종단 간 지연을 줄이기 위해 가능한 최저 지연 해법을 택한 것이라고 봄
      사람 간 음성 지연과의 비유는 맞지 않음. 그 경우에는 사람을 지연이 없는 존재처럼 취급하기 때문임
    • 하루 약 6,000건의 음성 대화를 WebRTC + 계단식 STT/LLM/TTS 구조로 처리해보면, 500ms가 사용자가 못 느낄 지연이라는 말은 내 경험과 다름
      500ms는 요즘 최첨단 음성 구현에서 운이 좋고 돈을 아끼지 않으며 speculative decoding과 reasoning 같은 비싼 기법까지 쓸 때의 바닥값에 가까움. LLM 단계만 450ms가 걸림. 상용 음성 AI에서는 모든 ms가 중요하고, 200~300ms만 더해도 대화 품질이 크게 나빠짐
      우리 사업은 주로 비기술 사용자 대상 음성을 많이 다룸. 작년에 턴 간 지연이 1200~1500ms였을 때는 사용자 혼란, 끼어들기, 대화 이탈, 전반적으로 불쾌한 경험이 많았음. 지금은 필요한 도구 사용에 따라 약 700ms 수준이고, 실제 사람과의 상호작용에 견줄 만한 괜찮은 경험에 가까워지고 있음. 여기서 100ms를 더 줄이려고 꽤 많은 비용을 쓰고 있음
      speculative LLM pass, speculative tool execution처럼 비싸고 낭비적인 일도 함. 사용자가 말하는 동안 여러 LLM 추론을 돌리되, 그 pass가 쓸 수 있고 사용자가 문장 끝에 중요한 말을 하지 않았다는 걸 알기 전에는 비멱등 도구 호출을 실제 실행하지 않는 식으로 100~200ms를 줄임. 500ms가 무관하다는 말은 사람-대-AI 음성 상호작용이 아닌 다른 사례를 말하는 것이라고 봄
      음성 AI에서 진짜 어려운 문제는 가끔 빠지는 WebRTC 패킷이 아니라 강한 배경 소음, 에코, 억양임. WebRTC의 잘 다듬어진 AEC 구현은 적어도 에코에는 꽤 도움이 됨. OpenAI 규모에서 구현하기 매우 골치 아픈 프로토콜이라는 건 알지만, 초대규모가 아닌 애플리케이션에는 Daily 같은 상용 제공자와 괜찮은 해법이 많음. 진짜 풀 문제는 다른 곳에 있음. 그래도 내 지연 예산에 500ms를 더하면 애플리케이션은 죽음
  • 안타깝게도 WebRTC만큼 구현하기 싫은 프로토콜이 드묾. 단순 클라이언트 하나를 띄우려 해도 SDP, TURN/STUN, ICE candidates, offer, P2P 프로토콜, 매번 처음부터 구현하는 복잡한 핸드셰이크에 빠르게 적응해야 함
    프로토콜과 의도치 않은 “모범 사례”가 겹겹이 들어간 그 트렌치코트를 전부 다시 쓴다는 건 상상하기도 어렵다

    • Microsoft Graph API로 이메일을 다뤄본 적이 있는지 궁금함
    • LLM이 등장하고 나서야 aiortc로 동작하는 WebRTC datachannel 구성을 처음 만들 수 있었음. 그전에는 사실상 완전히 불가능했음. 무엇을 어떻게 해야 하는지 아는 사람이 없고 예제도 없음. 정말 끔찍한 프로토콜이고 사라져야 함
    • 이런 이유로 LiveKit을 좋아하고, CEO도 괜찮음
    • 어떤 플랫폼을 대상으로 했길래 그렇게 고통스러웠는지 궁금함. 좌절스러웠다니 아쉽다
      교육 자료와 라이브러리가 늘면서 나아지고 있기를 바람. Codex 같은 도구가 이제는 이런 부분을 꽤 잘 밀고 나가는 것도 놀라움
  • 브라우저 API 안정성 전반에는 문서화되지 않은 가장자리 사례가 많고, WebRTC만의 문제는 아님

  • 답답할 정도로 한쪽으로 치우친 글임. WebRTC에 한계가 있는 건 맞지만, 표준에 기대면 많은 정확성을 얻고 장기 엔지니어링 비용을 줄일 수 있음. WebRTC가 복잡하다는 사실은 틀렸다는 뜻이 아니라, 공개 인터넷에서 실시간 미디어가 복잡하다는 뜻임
    네트워킹은 본질적으로 상태를 가짐. NAT traversal, 지터 버퍼, 혼잡 제어, 패킷 손실, 코덱 상태, 암호화, 세션 라우팅은 오디오를 TCP나 WebSocket에 올린다고 사라지지 않음. 그렇지 않은 척하는 건 아키텍처적 명료함이 아니라 복잡성을 덜 보이는 곳으로 옮기는 것일 뿐임

    • 글쓴이는 글 시작부터 본인 배경을 설명했음. 6년 전 Twitch에서 WebRTC SFU를 만들었고, 처음에는 OpenAI처럼 Pion(Go)을 썼지만 벤치마크에서 너무 느려 포크했으며, 결국 모든 프로토콜을 다시 썼다고 함
      1년 전에는 Discord에서 Rust로 WebRTC SFU를 다시 썼고, 반복되는 패턴이 보일 것임
      WebRTC는 2000년대 초반부터 이어진 약 45개의 RFC와, TWCC나 REMB처럼 기술적으로는 초안인 사실상 표준들로 구성됨. 이걸 전부 구현해야 할 때는 전혀 즐겁지 않음
      본인은 공인 WebRTC 전문가로 봐도 좋고, 그래서 다시는 WebRTC를 쓰고 싶지 않다고 함
      보통 방식으로 충분히 시도해봤으니 반대 방향의 견해를 가질 자격은 충분하지 않나 싶음
    • 한쪽으로 치우쳤다는 점이 오히려 요즘 널린 양쪽 다 맞다는 식의 글머리표 AI 문장보다 사람이 쓴 글처럼 신선했음
      주제 자체에 대한 입장은 없지만, 글에 분명히 인간적인 결이 있어서 좋았음
      만약 AI가 쓴 글이라면 정말 큰일임
    • “얼마나 어렵겠어?”라고 허수아비가 물었음
      2026년인데도 원격회의는 여전히 엉망임. 수십억 달러가 걸려 있고 Zoom도 잘해야 평범한 수준이며, Microsoft의 뭐시기만큼 나쁠 때도 있음. 원격회의가 서툴고 거친 난장판이 아닌 걸 본 적이 없음
    • QUIC도 표준임
  • 훌륭한 글임. 글쓴이가 해당 분야 전문가일 때 블로그 글에 상을 줄 수 있으면 좋겠음

  • “WebRTC는 나쁜 네트워크 상황에서 내 프롬프트를 열화시키고 떨어뜨리도록 설계됐다”는 말에 대해, 실시간을 원한다면 감수해야 할 일임. 실시간을 원하지 않고 모든 걸 STT -> Prompt -> TTS로 상상한다면 애초에 오디오를 네트워크로 보낼 필요가 없을 수도 있음

    • 글쓴이임. 댓글 답변이 글만큼 재밌지 않은 점은 양해 바람
      모든 저지연 애플리케이션은 품질과 지연 시간 사이의 사용자 경험 절충을 정해야 함. 혼잡은 큐잉, 즉 지연을 만들고, 이를 피하려면 무언가를 건너뛰어야 해서 품질이 낮아짐
      WebRTC의 지연 시간 대 품질 조절 손잡이는 고정돼 있음. 지연 최소화에는 훌륭하지만 유연성이 부족함. 그래도 브라우저 지원 덕분에 사실상 몇 안 되는 선택지라서 여전히 WebRTC를 쓰려고 함
      하지만 이제는 WebTransport가 있음. 범용 프로토콜로 WebRTC 비슷한 동작을 만들 수 있음. 스트림을 drop/reset하기 전에 얼마나 기다릴지 애플리케이션이 선택할 수 있고, 그 결정을 대신 당하지 않아도 됨
      글의 요지는 사용자가 대개 스트리밍은 원하지만 드롭은 원하지 않는다는 것임. 오디오 입출력 스트리밍은 WebRTC 없이도 당연히 가능함. 오디오 패킷이 영원히 사라지는 시점을 애플리케이션이 정할 수 있어야 함. 50ms인지 500ms인지 5000ms인지 말임. 음성 AI가 50ms 옵션을 고르면 안 된다는 주장임
    • 핵심은 OpenAI의 사용 사례가 실시간을 요구하지 않는다는 것 아닌가 싶음
      OpenAI가 응답할 때는 사용자가 들어야 하는 시점보다 앞서 오디오 대부분을 갖고 있음. 실시간보다 빠르게 오디오를 생성하므로 실시간 프로토콜은 맞지 않는 선택임
    • 지연을 줄이는 추가 설정을 내가 놓쳤을 수도 있지만, 클라이언트들은 STT -> Prompt -> TTS의 지연을 감수하고 싶어하지 않는 듯함. 대화가 “진짜”처럼 느껴진다면 가끔 품질 문제가 생기는 건 기꺼이 받아들임
  • Gemini Live API를 관리형 WebRTC 클라우드 메시 위에서 돌리고 있는데 아주 잘 동작하고, 2년째 운영 중임. WebSocket을 시도하고 임시 키 등을 직접 처리할 수도 있지만, 이 영역에서 대규모 음성 에이전트를 운영하는 사람들과 이야기해보면 WebRTC와 Pipecat, 그리고 이미 해결된 문제들에 투입된 많은 리소스로 상당수가 풀려 있음
    분명 과하다는 느낌이 들고 실제로도 그럴 수 있지만, 연결이 맺어진 뒤에는 꽤 마법 같음. 시작 시간과 버퍼링도 더 빠른 음성 연결을 위해 해결돼 있음: https://github.com/pipecat-ai/pipecat-examples/tree/main/ins... 영상은 더 어려움