Meta는 WebRTC를 어떻게 자체 엔진으로 만들었나 — libwebrtc Fork의 함정과 Shim 아키텍처
"Meta 정도면 WebRTC도 바닥부터 만들지 않았을까?" 매일 수십억 통화를 처리하는 회사라면 그럴 법하지만, 실제로는 구글 libwebrtc를 fork해서 출발했고 수년 뒤 오히려 upstream으로 되돌아왔다. 이 글은 fork가 왜 시간이 갈수록 부채가 되는지, Meta가 두 버전을 한 바이너리에 공존시키며 빠져나온 shim 아키텍처가 무엇인지, 그리고 AV1 코덱처럼 진짜 자체 개발한 영역과 공개 자료로 확인되지 않는 주장을 어떻게 구분해야 하는지 정리한다.
목차(25개 항목)
- 0. 핵심 명제 — Meta는 "자체 엔진"을 만든 게 아니라 "fork를 길들였다"
1. 왜 fork로 시작했나 — libwebrtc라는 사실상의 표준
2. fork의 함정 — upstream과 멀어지는 비용은 복리로 늘어난다
3. shim 아키텍처 — fork를 빠져나오는 다리
4. 자체 개발이 명확한 영역 — AV1 코덱과 비디오 스케일러
5. P2P → 미디어 서버 전환 — 어디까지가 사실인가
6. 업계 지형 — 다른 벤더들은 어디서 출발했나
7. 그래서 Meta 사례에서 배울 것 — 의사결정 체크리스트
- 8. 한 줄 결론
- 관련 글
- 참고 자료
"Meta 정도 되는 회사면 WebRTC도 바닥부터 자체 개발하지 않았을까요?". 메신저·인스타그램·왓츠앱이 매일 수십억 건의 통화를 처리한다는 사실을 들으면 자연스럽게 떠오르는 질문입니다. 답은 정반대에 가깝습니다 — Meta는 바닥부터 만들지 않았습니다. 구글의 오픈소스 libwebrtc를 fork해서 시작했고, 그 fork를 수년간(Meta 공식 표현은 'years', 구체 연수 미공개) 끌고 가다 결국 upstream으로 돌아오는 대규모 마이그레이션을 단행했습니다.
이 글은 그 여정을 정리합니다. fork가 왜 매력적이었고, 왜 함정이 되었으며, Meta가 그 함정을 빠져나오기 위해 설계한 shim 아키텍처가 무엇인지. 그리고 AV1 코덱·자체 비디오 스케일러처럼 "진짜 자체 개발"한 영역과, 공개 자료로 확인되지 않는 영역을 정직하게 구분합니다. 검증되지 않은 주장은 본문에서 "정정:" 또는 [NEEDS VERIFICATION]으로 표시했습니다.
0. 핵심 명제 — Meta는 "자체 엔진"을 만든 게 아니라 "fork를 길들였다"
Meta는 google libwebrtc를 fork해서 수년간(Meta 공식 표현은 'years', 구체 연수 미공개) 썼지만, fork 유지 비용이 통제 불능이 되자 'shim 아키텍처'를 만들어 upstream libwebrtc로 완전히 돌아왔다. 즉 Meta의 진짜 엔지니어링 성과는 '바닥부터 만든 엔진'이 아니라 '거대한 monorepo가 upstream과 다시 동기화될 수 있게 만든 추상화 레이어'다. 자체 개발이 명확히 확인되는 영역은 코덱(AV1)과 비디오 스케일러이며, 그것조차 라이선스 비용(royalty-free)과 통제권이 동기였다.
흔한 오해와 정정부터 박아둡니다.
| 오해 | 정확한 이해 |
|---|---|
| Meta는 WebRTC를 바닥부터 자체 개발했다 | ❌ google libwebrtc를 fork해서 시작 |
| Meta는 지금도 자체 fork를 쓴다 | ❌ 정정: 2026년 기준 upstream libwebrtc로 마이그레이션 완료 ('Escaping the Fork') |
| fork는 통제권을 주니 무조건 좋다 | ⚠️ 초기엔 좋지만 upstream과 멀어질수록 유지비가 기하급수적 |
| Meta가 전 세계 SFU 미디어 서버를 깔았다 | ⚠️ 공개 자료로 확인 불가 — Rsys는 signaling 통합을 문서화했으나 SFU 인프라는 미문서화 |
| 자체 코덱으로 라이선스 "조 단위" 절감 | ⚠️ AV1이 royalty-free인 건 사실, 그러나 구체적 절감액은 Meta가 공개 안 함 |
1. 왜 fork로 시작했나 — libwebrtc라는 사실상의 표준
WebRTC를 "직접" 구현한다는 건 실제로는 거의 불가능에 가깝습니다. 오디오/비디오 캡처, 코덱 통합, 지터 버퍼(#23 참고), NACK/FEC, 혼잡 제어(GCC), ICE/STUN/TURN(#0, #8 참고), DTLS-SRTP 암호화까지 — 수백만 줄의 검증된 코드가 필요합니다.
이 모든 걸 구글이 오픈소스로 푼 것이 libwebrtc(webrtc.org)입니다. 그래서 거의 모든 RTC 회사가 여기서 출발합니다.
fork를 선택하는 이유
거대 서비스가 라이브러리를 그냥 가져다 쓰지 않고 fork(코드를 통째로 복사해 자기 저장소에 넣음) 하는 이유는 명확합니다.
| 동기 | 설명 |
|---|---|
| 통제권 | upstream의 변경 일정에 끌려가지 않고 내 일정으로 패치 |
| 커스텀 패치 | 자사 인프라(로깅, 메트릭, A/B 실험)에 맞춘 hook 삽입 |
| 독자 최적화 | 자체 코덱·스케일러·혼잡 제어를 직접 이식 |
| 빌드 통합 | 거대 monorepo 빌드 시스템에 소스째 편입 |
🟢 단기적으로 fork는 합리적입니다. "내 코드처럼" 마음대로 고칠 수 있으니까요.
⚠️ 문제는 시간입니다. 다음 섹션이 이 글의 핵심입니다.
2. fork의 함정 — upstream과 멀어지는 비용은 복리로 늘어난다
fork의 진짜 비용은 fork하는 순간이 아니라, upstream이 계속 발전하는 동안 발생합니다.
무엇이 비싸지는가
🔴 1. 보안 패치 백포팅 지옥 upstream이 보안 취약점을 고쳐도, 내 fork에 자동으로 들어오지 않습니다. 수년치 커스텀 변경과 충돌하는 패치를 손으로 병합해야 합니다.
🔴 2. 신규 기능 누락 upstream이 AV1, 향상된 혼잡 제어, 새 FEC를 추가해도 내 fork는 옛 버전에 갇힙니다. 받으려면 다시 거대한 rebase.
🔴 3. 점점 커지는 diff 변경이 쌓일수록 "upstream을 따라잡는" 작업이 기하급수적으로 비싸집니다. 결국 아무도 감히 rebase를 시도하지 못하는 상태가 됩니다.
비유: fork는 "본가에서 분가해 따로 집을 짓는 것"과 같습니다. 처음엔 자유롭지만, 본가가 수도·전기·보안 시스템을 계속 업그레이드하는 동안 내 집은 그대로입니다. 본가 업그레이드를 가져오려면 매번 벽을 뜯어야 합니다. 기술적으로 환원하면: upstream의 매 커밋이 내 fork의 커스텀 패치와 merge conflict를 일으킬 잠재적 후보이며, conflict 해결 비용은 누적 diff 크기에 비례합니다.
Meta의 실제 상황
정정/사실: Meta는 약 7년 된 libwebrtc fork [원문은 'years'만 언급, 구체 연수 미공개]를 운영했고, 이를 최신 upstream으로 교체하는 작업을 'Escaping the Fork'(2026년 4월, engineering.fb.com)로 문서화했습니다. 핵심 동기는 "fork 유지의 비효율"이었습니다. 2026년 기준 50개 이상의 use case가 upstream 기반 아키텍처로 운영됩니다.
이게 fork의 함정입니다. 통제권을 얻는 대신, 시간이 지날수록 "산업 표준의 발전에서 고립"되는 비용을 냅니다.
3. shim 아키텍처 — fork를 빠져나오는 다리
여기가 Meta 엔지니어링의 진짜 묘수입니다. 수년 된 fork [원문은 'years'만 언급]를 한 번에 upstream으로 갈아끼우는 건 "big bang" 교체 — 수만 곳의 호출부를 동시에 바꿔야 하고, 실패하면 수십억 통화가 멈춥니다. Meta는 그 대신 점진적 마이그레이션을 가능하게 하는 중간 레이어(shim)를 만들었습니다.
사실: shim 아키텍처는 Meta 공식 블로그('Escaping the Fork')에 명시적으로 문서화되어 있습니다. shim layer는 'flavor' 설정을 들고 있다가 런타임에 각 호출을 legacy WebRTC 또는 최신(upstream) WebRTC 구현 중 하나로 dispatch합니다.
shim이 푸는 문제 — 두 버전 공존
마이그레이션 기간에는 옛 fork와 새 upstream이 한 바이너리 안에 동시에 존재해야 합니다. 그런데 둘 다 namespace webrtc { ... }를 씁니다. 같은 심볼이 충돌합니다.
Meta는 자동화된 renamespacing으로 이를 갈랐습니다.
그리고 호출부는 webrtc::를 직접 부르지 않고 shim을 거칩니다.
왜 이게 안전한가
| 항목 | big bang 교체 | shim 점진 교체 |
|---|---|---|
| 전환 단위 | 전부 한 번에 | use case 하나씩 (flavor 토글) |
| 롤백 | ❌ 거의 불가능 | ✅ flavor만 되돌리면 됨 |
| 두 버전 공존 | ❌ 불가 | ✅ renamespacing으로 가능 |
| 위험 노출 | 수십억 통화 동시 | 소수 트래픽부터 점진 |
비용 문제 — 바이너리 크기
두 버전을 다 넣으면 바이너리가 뚱뚱해집니다. 모바일 앱에서 이건 심각한 문제(다운로드/메모리)입니다.
사실: Meta는 두 버전을 그대로 모두 포함하면 바이너리가 약 38MB 늘 것을, shim 설계로 약 5MB 수준으로 억제했다고 기술했습니다. 또한 shim 생성을 AST(Abstract Syntax Tree) 기반 자동 코드 생성으로 자동화해, 수작업이라면 하루 1개 수준이던 shim 생성을 하루 3~4개로 끌어올렸습니다.
비유: shim은 "통역사를 가운데 두고 옛 직원과 새 직원을 한 사무실에서 동시에 일하게 하는 것"입니다. 기술적으로 환원하면: shim은 호출 인터페이스를 안정적으로 고정한 채(애플리케이션은 shim API만 봄), 뒤에서 실제 구현(legacy/latest)을 런타임 설정으로 교체하는 indirection layer입니다. 즉 fork 교체를 "코드 수정"이 아니라 "설정 토글" 문제로 바꿉니다.
⚠️ 추상화 레이어의 일반 원리로서의 타당성: "버전 독립을 위해 호출부와 구현 사이에 indirection을 둔다"는 것은 소프트웨어 공학의 표준 기법(예: facade/adapter 패턴, ABI 안정화)입니다. Meta의 shim은 이 원리를 monorepo 규모에서 자동화한 구체적 사례입니다.
4. 자체 개발이 명확한 영역 — AV1 코덱과 비디오 스케일러
fork/shim은 "엔진을 어떻게 관리했나"의 이야기입니다. 그럼 Meta가 실제로 자체 개발한 차별화 요소는 무엇인가? 공개 문서로 확인되는 건 코덱 영역입니다.
AV1 도입 — royalty-free가 핵심 동기
사실: Meta는 모바일 RTC에 AV1을 도입했고 engineering.fb.com에 상세 문서를 냈습니다(2024-03, 2025-09). AV1로 H.264 대비 약 2dB(지표 기준은 원문 확인 필요) 품질 향상을 보고했습니다.
AV1을 택한 이유 중 하나는 명시적으로 라이선스(royalty-free)입니다. H.264/HEVC는 라이선스·동시접속 과금 구조가 있지만, AV1(AOMedia)은 royalty-free입니다.
정정 — '조 단위 절감'은 확인 불가: Meta는 "codec licensing과 concurrent fees가 의사결정의 중요한 측면"이라고 기술했고 AV1의 royalty-free 특성을 강조했습니다. 그러나 '조 단위'·'billions' 같은 수치화된 절감액은 공개하지 않았습니다. 참고로 H.264 라이선스는 연간 상한이 알려져 있고(업계 자료상 연 $9.75M 수준), HEVC는 다중 풀(multi-pool) 구조로 더 복잡합니다. Meta 규모에서 라이선스 제거가 큰 의미인 건 맞지만, 구체적 액수는 [NEEDS VERIFICATION].
AV1의 트레이드오프 — 공짜 점심은 없다
AV1은 품질은 좋지만 비쌉니다.
| 항목 | 효과 | 트레이드오프 |
|---|---|---|
| 압축 효율 | 🟢 H.264 대비 ~2dB ↑ (지표 기준 원문 확인 필요) | 🔴 인코딩 CPU H.264 대비 약 3배 (Meta 2024-03 원문) |
| 라이선스 | 🟢 royalty-free | — |
| 배터리 | — | 🔴 소비 5~6% 증가 → hybrid encoder로 완화 |
| 저사양 기기 | — | 🔴 너무 무거워 비활성화 (기기별 분기) |
즉 AV1은 "모든 기기에 무조건 켜는 코덱"이 아니라, 기기 성능에 따라 조건부로 켜는 코덱입니다. 코덱 선택 자체가 적응형 의사결정입니다(#28에서 H.264 프로파일/비트레이트 트레이드오프와 같은 맥락).
자체 비디오 스케일러
사실: Meta는 커스텀 비디오 스케일러를 개발해, 공개 테스트에서 PSNR 평균 0.75dB 이득을 보고했습니다. 이는 표준 스케일러 대비 우수한 성능으로 기술됩니다.
스케일러는 인코딩 전 해상도를 줄이거나 키울 때 쓰는 모듈입니다. 저대역폭 사용자에게 보내는 저해상도 영상의 품질을 좌우합니다. Meta는 여기에 콘텐츠 인식 인코딩(얼굴 영역 우선, Region-of-Interest)을 결합했습니다.
정정 — libyuv 대체 범위: Meta 원문은 커스텀 스케일러의 PSNR +0.75dB가 WebRTC 기본 libyuv box filter 대비라고 명시합니다. 다만 libyuv를 전면 대체했는지(부분 보강인지)까지는 단정하지 않습니다.
5. P2P → 미디어 서버 전환 — 어디까지가 사실인가
"수십억 통화"라면 당연히 거대한 미디어 서버 인프라가 있을 것 같습니다. 여기서는 확인되는 것과 확인되지 않는 것을 엄격히 구분합니다.
확인되는 것 — Rsys signaling 통합
사실: Meta는 2020년 Rsys라는 RTC 아키텍처 재구성을 문서화했습니다(engineering.fb.com, 2020-12). Rsys는 **1:1 통화와 그룹 통화를 하나로 통합한 '상태 머신 기반 signaling 아키텍처'**입니다.
확인되지 않는 것 — 전 세계 SFU 인프라
정정/UNVERIFIABLE: "Meta가 P2P에서 SFU(Selective Forwarding Unit)로 전환하고 전 세계에 SFU 미디어 서버를 배포했다"는 주장은 Meta 공식 엔지니어링 블로그에서 구체적으로 확인되지 않습니다. Rsys 글은 signaling 통합을 다루지만, SFU 아키텍처 도입이나 worldwide media server 배포를 구체적으로 기술하지 않습니다. P2P→SFU 전환이 업계 일반 관행인 것은 맞으나, Meta의 실제 구현 여부는 공개 자료만으로는 단정할 수 없습니다. [NEEDS VERIFICATION]
| 주장 | 판정 | 근거 |
|---|---|---|
| Rsys로 1:1/그룹 signaling 통합 | ✅ 확인됨 | engineering.fb.com Rsys(2020) |
| P2P → SFU 전환 | ⚠️ 확인 불가 | 공식 문서에 구체적 기술 없음 |
| 전 세계 SFU 인프라 배포 | ⚠️ 확인 불가 | 상동 |
참고로 SFU가 무엇이고 왜 필요한지는 일반 RTC 토폴로지 지식입니다.
다만 위 SFU 다이어그램은 일반 원리이며, Meta가 정확히 이 토폴로지를 전역 배포했다는 근거는 아닙니다.
6. 업계 지형 — 다른 벤더들은 어디서 출발했나
Meta의 선택을 맥락에 놓으려면 동종 벤더와 비교하는 게 유용합니다. "대부분 libwebrtc에서 출발했다"는 큰 틀은 맞지만, '모두'는 아닙니다. 정정 포인트가 많아 표로 정리합니다.
| 벤더 | 기반 | 정정/주의 |
|---|---|---|
| Agora | libwebrtc 기반 (+ SD-RTN 전용망) | 네트워크 레이어로 차별화 (#43) |
| Twilio Video | libwebrtc 채택 | ⚠️ 정정: EOL 발표했다가 번복(reversal). 2024-10 지속 투자 재공표 — '종료'가 아님 |
| LiveKit | Go 기반 Pion WebRTC (C++ libwebrtc 아님) | ⚠️ SFU 서버는 Go. Rust는 일부 SDK 레벨, 핵심 서버는 Go |
| Daily | WebRTC 표준 기반 SFU | P2P/SFU 동적 전환 |
| Zoom | 독자 비중 큼 | 고유 H.264 스택, 웹은 WebAssembly 커스텀 인코딩 → 표준 대비 CPU↑ |
| Discord | WebRTC + 커스텀 SFU (Rust/Elixir 혼합) | ⚠️ 정정: Rust 재작성은 음성 엔진이 아니라 'Read States' 서비스 |
| Slack Huddles | Amazon Chime SDK | ✅ AWS 파트너십, Chime Transcribe로 캡션 |
특히 강조할 정정 3가지
🔴 "Discord가 미디어 엔진을 Rust로 재작성했다" → 부분 오류
정정: Discord가 Go→Rust로 재작성한 건 'Read States'(채널/메시지 읽음 상태 추적 서비스)입니다. GC 지연으로 인한 latency spike를 제거하려는 목적이었습니다. 음성 미디어 엔진과는 다른 컴포넌트입니다. 음성 스택은 Rust/Elixir/WebRTC 혼합 + 커스텀 SFU 구성입니다.
🔴 "LiveKit은 Rust/libwebrtc 네이티브" → 부정확
정정: LiveKit SFU 서버는 Go(Pion WebRTC 기반)입니다. C++ libwebrtc 기반이 아닙니다. Rust 컴포넌트는 일부 SDK 수준에서 존재하지만 핵심 서버의 언어는 Go입니다.
🔴 "Twilio Video는 2024년 종료됐다" → 거짓
정정: EOL 발표는 있었으나 이후 번복되었습니다. 2024-10 Twilio가 Twilio Video 지속 투자를 재공표했습니다. 최종 상태는 '종료'가 아니라 '결정 역행(reversal)'입니다.
큰 그림 — 차별화는 코덱이 아니라 네트워크
사실(일반화): 코덱(Opus/VP8/VP9/H.264)은 사실상 표준화되어 차별화 요인이 약합니다. 현대 RTC 벤더의 핵심 차별점은 SFU 아키텍처, 지역 네트워크 인프라, 라우팅 최적화, 적응형 비트레이트, 스케일링 능력입니다. (예: Agora SD-RTN, #43 참고.)
Meta의 AV1 자체 개발이 흥미로운 건, 바로 이 "코덱은 별 차별화 안 된다"는 통념의 예외라는 점입니다. Meta 규모에서는 코덱의 라이선스·압축률·CPU가 곧 인프라 비용이라, 코덱 자체가 다시 차별화 영역이 됩니다.
7. 그래서 Meta 사례에서 배울 것 — 의사결정 체크리스트
Meta의 여정은 "fork할 것인가, upstream을 따를 것인가"라는 모든 인프라 팀의 질문에 데이터를 줍니다.
핵심 교훈 카드
| 교훈 | 한 줄 |
|---|---|
| fork는 부채다 | 통제권을 얻는 대신 upstream 고립 비용을 복리로 지불 |
| indirection이 탈출구다 | shim/adapter로 "코드 교체"를 "설정 토글"로 전환 |
| 자동화가 규모를 만든다 | AST 기반 코드 생성으로 shim 생성 1→3~4개/일 |
| 코덱은 보통 차별화 아님 | 단, Meta급 규모에선 라이선스/CPU가 인프라 비용 → 예외 |
| 공개 자료의 한계를 인정하라 | SFU 인프라처럼 "그럴듯하지만 미문서화"인 영역 구분 |
8. 한 줄 결론
Meta는 WebRTC를 바닥부터 만든 적이 없다. google libwebrtc를 fork해 수년간(Meta 공식 표현은 'years', 구체 연수 미공개) 쓰다가, fork 유지 비용이 통제 불능이 되자 'shim 아키텍처'(flavor 기반 런타임 dispatch + AST 자동 renamespacing)를 만들어 upstream으로 완전히 돌아왔다 — 이것이 'Escaping the Fork'의 본질이다. 진짜 자체 개발이 확인되는 영역은 AV1 코덱(royalty-free 동기, 단 CPU 약 3배·기기별 조건부)과 커스텀 비디오 스케일러(PSNR +0.75dB)뿐이며, '전 세계 SFU 인프라'나 '조 단위 라이선스 절감' 같은 화려한 주장은 공개 자료로 확인되지 않는다. 교훈은 단순하다 — fork는 부채이고, indirection(shim/adapter)이 그 부채를 갚는 표준적 탈출구다.
관련 글
- #43 Agora 자체 코덱 vs Web SDK — SD-RTN과 FEC의 실체 — "코덱 레이어 vs 네트워크 레이어" 분리 관점, Meta 사례와 직접 대비
- #40 라이브 스트리밍 프로토콜 선택 — HLS / LL-HLS / WebRTC — WebRTC가 어느 위치에 있는지
- #28 H.264 Profile·인코더 옵션·비트레이트의 현실 — 코덱 트레이드오프(AV1 vs H.264 맥락)
- #23 오디오 파이프라인 — Opus / RTP / Jitter Buffer — libwebrtc가 내장한 미디어 처리 스택
- #0 WebRTC란? ICE? STUN? NAT? TURN? — libwebrtc가 추상화하는 기본 구조
참고 자료
- Escaping the Fork: How Meta modernized WebRTC across 50 use cases (engineering.fb.com, 2026-04) — shim 아키텍처·renamespacing·AST 자동화 원문
- Rsys: Meta's RTC architecture (engineering.fb.com, 2020-12) — signaling 통합 (SFU 인프라는 미문서화)
- Bringing AV1 to RTC video for HD on mobile (engineering.fb.com, 2024-03) — AV1 도입·커스텀 스케일러·라이선스 동기
- Video streaming with AV1 on mobile — white paper (engineering.fb.com, 2025-09) — AV1 CPU/배터리 트레이드오프
- How AV1 powers Facebook & Instagram Reels (engineering.fb.com, 2023-02) — AV1 채택 배경
- Why Discord is switching from Go to Rust — 정정 근거: Rust 재작성 대상은 'Read States'
- LiveKit SFU internals — 정정 근거: SFU 서버는 Go(Pion)
- Twilio Programmable Video End-of-Life Notice — 정정 근거: EOL 번복
- Slack & Amazon Chime SDK (AWS Blog) — Slack Huddles 기반
- WebRTC.org / libwebrtc — 공통 출발점인 오픈소스 구현