핵심 챌린지

기술적 문제 해결 경험 3 가지.


1. Consumer N² 스케일링 문제

문제

SFU 아키텍처에서 참가자 수 증가 시 Consumer 가 기하급수적으로 증가.

Consumer 수 = 참가자 × (참가자 - 1) × 2(비디오 + 오디오) 10 명: 10 × 9 × 2 = 180 개 30 명: 30 × 29 × 2 = 1,740 개

원인 분석

P2P → SFU 전환 시 클라이언트 부하는 줄었으나, 서버 리소스 (메모리, CPU) 가 N² 비례 증가.

특히 30 명 1080P/30fps 테스트에서 Consumer 1,510 개 생성 → CPU 99% 도달.

해결

  1. Simulcast 적용: 3 단계 해상도 자동 조절 (100k/300k/900k bps)
  2. Consumer 지연 생성: 화면에 보이는 참가자만 구독
  3. 스펙업 가이드라인 도출: 인원별 필요 인스턴스 타입 정리
결과BeforeAfter
30 명 CPU99%65% (Simulcast)
대역폭1,272 Mbps~400 Mbps

2. Producer 라이프사이클 설계

문제

화면 공유 시작 시 카메라 비디오가 사라짐. 카메라 + 화면 공유 동시 사용 불가.

원인 분석

  1. 카메라 비디오 사라짐
  2. → 화면 공유 Producer 가 카메라 Producer 를 덮어씀
  3. → 두 Producer 를 구분하지 못함
  4. → kind(video) 만으로 Producer 식별
  5. → 근본 원인: 초기 설계 시 비디오 트랙 1 개만 가정

mediasoup Producer 는 kind(audio/video) 로만 구분. 동일 kind 의 다중 스트림 시나리오 미고려.

해결

Producer 생성 시 appData 에 스트림 타입 메타데이터 추가:

// appData로 스트림 타입 구분
{
  kind: "video",
  appData: {
    isScreenShare: true,  // 카메라 vs 화면 공유 구분
    socketId: "socket-123"
  }
}
결과BeforeAfter
동시 전송불가가능
Producer 수1 개 (충돌)2 개 (공존)

Lessons

  • 요구사항 확장 시 기존 식별자 체계 검토 필수.
  • mediasoup appData 는 스트림 메타데이터 관리에 유용.

3. 이중 병목 구조 발견

문제

부하 테스트 결과의 비선형 현상:

  • 참가자 3 배 증가 (10 명 → 30 명)
  • Jitter 1.4 배만 증가 (2.1 초 → 3.0 초)

왜 3 배 증가했는데 Jitter 는 1.4 배만 증가했는가?

원인 분석

  1. Jitter 가 예상보다 적게 증가
  2. → 10 명 시점에서 이미 병목 발생
  3. → 네트워크 대역폭 초과 (434Mbps > 100Mbps baseline)
  4. → 30 명에서 CPU 도 포화 (99%)
  5. → 근본 원인: 1 차 병목 (네트워크) 이 2 차 병목 (CPU) 영향을 가림
시나리오1 차 병목2 차 병목Jitter
10 명네트워크 (포화)CPU (50%)2.1 초
30 명네트워크 (포화)CPU (99%)3.0 초

네트워크가 먼저 포화되면 추가 트래픽이 드롭되어 CPU 병목 영향이 제한적으로 나타남.

해결

  1. 스펙업 시 네트워크 대역폭과 CPU 동시 고려
  2. 인스턴스 타입별 예상 수용 인원 가이드라인 도출
인스턴스네트워크예상 수용
t3.small~100 Mbps2~3 명
c5.large최대 10 Gbps10~15 명
c5.xlarge최대 10 Gbps20~30 명

Lessons

  • 성능 이슈는 단일 원인이 아닐 수 있음. 데이터 기반 의사결정 (추측 → 측정 → 분석).

구현된 최적화 현황

항목상태설명
Simulcast완료3 단계 해상도 자동 조절
appData 스트림 구분완료카메라/화면 공유 동시 지원
트래픽 로거완료getStats() 기반 실시간 메트릭
Active Speaker 모드미구현Consumer 수 감소 최적화

사용 디버깅 도구

도구용도
chrome://webrtc-internalsICE 상태, RTP 통계
producer.getStats()Jitter, RTT, 패킷 손실
커스텀 트래픽 로거세션별 메트릭 집계
v8-profiler-nextNode.js CPU 프로파일