시리즈: 실시간 통화, 어떻게 녹화하는가1/6
- 1.실시간 통화, 왜 녹화해야 하는가 ← 현재 글
- 2.내 서버에서 직접 녹화한다면
- 3.녹화 모드 해부
- 4.M3U8과 TS 파일의 모든 것
- 5.FFmpeg, 미디어의 스위스 아미 나이프
- 6.FFmpeg 실전 파이프라인
실시간 통화, 왜 녹화해야 하는가 — Cloud Recording Architecture
통화가 끝나면 사라지는 실시간 통신. Ghost Participant 패턴, Recording Lifecycle, 인증 체계 분리까지 Cloud Recording 아키텍처를 해부합니다.
목차(13개 항목)
통화가 끝나면 사라진다. WebRTC 기반의 실시간 통신은 본질적으로 **ephemeral(일시적)**입니다. 두 피어가 연결되고, 미디어가 흐르고, 연결이 끊기면 — 그걸로 끝입니다. 서버 어딘가에 대화가 저장되지 않습니다. 실시간성이 강점인 동시에, 영속성이 없다는 게 한계입니다.
그런데 비즈니스 현실은 다릅니다. 법적 의무, 사용자 요구, 품질 보증 — 통화가 "그냥 사라지면 안 되는" 이유가 점점 많아지고 있습니다. 금융사 상담원이 고객과 나눈 대화는 규제 기관이 요구하는 경우 제출할 수 있어야 합니다. 온라인 과외 플랫폼에서는 학생이 수업을 다시 볼 수 있어야 합니다. 병원 원격 진료 기록은 EMR에 연동되어야 하고, 분쟁이 생기면 콜센터 통화를 증거로 제출해야 합니다.
이 시리즈는 이 문제를 다룹니다. 실시간 통화를 어떻게 녹화하는가 — 아키텍처부터 파일 포맷, FFmpeg 실전 파이프라인까지 6편에 걸쳐 풀어봅니다. 1편인 이 글에서는 "왜 녹화해야 하는가"와 Cloud Recording의 핵심 아키텍처를 다룹니다.
왜 클라이언트 녹화는 안 되는가
가장 직관적인 접근은 브라우저에서 직접 녹화하는 겁니다. Web API에는 MediaRecorder가 있고, 스트림을 받아서 Blob으로 저장할 수 있습니다.
문제는 여러 겹으로 쌓입니다.
첫째, 단일 스트림만 녹화됩니다. MediaRecorder는 로컬 미디어 스트림을 녹화합니다. 3명이 통화 중이라면 각자의 브라우저에서 각자의 스트림만 녹화됩니다. 합쳐진 결과물이 없습니다.
둘째, 믹싱을 직접 구현하면 CPU 폭발입니다. 다자간 통화를 하나의 파일로 합치려면 클라이언트가 여러 스트림을 실시간으로 믹싱(mixing)하고, 동시에 인코딩(encoding)해야 합니다. OffscreenCanvas + Web Audio API로 구현이 가능하긴 하지만, 브라우저 탭이 CPU를 먹어치웁니다. 모바일에서는 배터리가 급격히 소모되고, 저사양 기기에서는 통화 품질 자체가 저하됩니다.
셋째, 데이터 유실 위험이 너무 큽니다. 녹화 중 브라우저 탭이 닫히거나 앱이 크래시되면 메모리에 있던 chunks 전체가 사라집니다. 업로드 전에 연결이 끊기면? 30분짜리 상담 녹화가 통째로 날아갑니다. 재시도 로직, 청크 업로드, 체크포인트 관리를 모두 클라이언트 코드에 구현해야 합니다.
넷째, 자체 미디어 서버(SFU/MCU) 구축은 현실적이지 않습니다. 서버 사이드 믹싱을 위해 Janus, Medea, Mediasoup 같은 SFU를 직접 운영하거나, MCU(Multipoint Control Unit)를 구축할 수 있습니다. 하지만 미디어 서버는 운영 비용이 상당하고, 스케일링이 복잡하며, 전문 인력이 필요합니다. 녹화 기능 하나를 위해 인프라 전체를 구축하는 것은 과잉 투자입니다.
결론: 클라이언트 녹화는 간단한 데모 수준에서는 가능하지만, 프로덕션 요구사항을 충족하기 어렵습니다.
Ghost Participant 패턴
Agora Cloud Recording이 채택한 아키텍처는 "유령 참가자(Ghost Participant)" 패턴입니다. 개념적으로는 단순합니다 — 채널에 조용히 들어와서 모든 미디어를 수신하고 저장하는, 사용자 눈에 보이지 않는 봇을 투입하는 것입니다.
Recorder는 어떻게 동작하는가
Recorder는 일반 RTC 참가자와 동일한 방식으로 채널에 조인합니다. 차이점은 두 가지입니다:
- Subscribe-only — 미디어를 수신(subscribe)하기만 하고, 발행(publish)하지 않습니다. 다른 참가자 화면에 나타나지 않습니다.
- Agora SD-RTN 내부 네트워크 — Recorder는 Agora의 SD-RTN(Software Defined Real-Time Network)을 통해 미디어를 수신합니다. SD-RTN은 Agora가 운영하는 글로벌 엣지 네트워크로, 일반 공중망보다 레이턴시와 패킷 로스가 낮습니다. Recorder가 SD-RTN 내부에 있기 때문에 미디어 품질 저하 없이 안정적으로 스트림을 수신할 수 있습니다.
하나의 채널에 여러 Recorder를 동시에 투입할 수 있습니다
같은 채널에 Recorder를 여러 개 띄울 수 있습니다. 실제 사용 사례:
운영 안정성을 위해 동일 설정의 Recorder를 두 개 띄워두고 하나가 실패하면 나머지로 폴백하는 중복 녹화(redundant recording) 패턴도 가능합니다.
Recording Lifecycle 심화
Cloud Recording은 4단계 REST API 호출로 제어합니다.
acquire — resourceId 확보
주의: resourceId에는 만료 시간이 있습니다. resourceExpiredHour 파라미터로 설정 가능하며(기본 72시간, 최대 720시간), 과거에는 5분이었으나 현재는 변경되었습니다. 그래도 acquire 후 가능한 빨리 start를 호출하는 것이 안전합니다. 두 호출 사이에 사용자 확인 UI를 넣거나, 별도 큐에 넣어서 처리하는 것은 권장하지 않습니다.
start — 녹화 시작
start 호출 응답에서 sid(세션 ID)를 받습니다. sid는 이후 query와 stop에 모두 필요합니다. 반드시 DB에 저장하세요.
query — 상태 확인
녹화 중에 query를 주기적으로 호출해서 상태를 확인할 수 있습니다. serverResponse.fileList에서 현재까지 업로드된 파일 목록을 확인할 수 있습니다.
stop — 녹화 종료
stop 이후 최종 파일(M3U8, MP4)이 스토리지에 업로드됩니다. stop 응답의 serverResponse.uploadingStatus가 "uploaded"인지 확인하세요. "backuped"라면 Agora 백업 서버에 있다는 의미로, 잠시 후 스토리지로 이동됩니다.
자세한 REST API 호출 예시와 코드는 Cloud Recording으로 스트림 자동 녹화하기를 참고하세요.
인증 체계: 두 개의 키가 왜 필요한가
Cloud Recording을 처음 도입할 때 가장 헷갈리는 부분이 인증입니다. 키가 두 종류나 있습니다.
| REST API (Cloud Recording) | RTC SDK (클라이언트) | |
|---|---|---|
| 인증 수단 | Customer Key + Secret | Token (App ID + Certificate) |
| 용도 | 녹화 시작/중지 제어 | 채널 입장 |
| 위치 | 서버 사이드 | 클라이언트 사이드 |
| 방식 | HTTP Basic Auth | SDK 파라미터 |
| 발급처 | Agora 콘솔 → RESTful API | 서버에서 Token Builder로 생성 |
Customer Key + Secret은 Agora 계정 수준의 관리자 권한입니다. 모든 REST API 호출(녹화, 채널 관리, 사용량 조회 등)에 사용됩니다. 절대로 클라이언트에 노출하면 안 됩니다.
RTC Token은 특정 채널에 입장하기 위한 1회성 자격증명입니다. App Certificate가 활성화된 경우 필수입니다. Recorder도 채널에 조인하는 참가자이므로, start 호출 시 Recorder용 Token을 생성해서 전달해야 합니다.
스토리지 연동
Cloud Recording이 생성한 파일은 직접 Agora 서버에 저장되지 않습니다. 반드시 서드파티 클라우드 스토리지를 연동해야 합니다.
지원 CSP:
- AWS S3 (리전별 endpoint 설정 가능)
- Google Cloud Storage
- Azure Blob Storage
- Alibaba OSS
- Tencent Cloud COS
- Baidu Cloud BOS
- Huawei Cloud OBS
- Kingsoft Cloud KS3
storageConfig는 start 호출 시 clientRequest 안에 포함합니다:
S3 권한 설정과 저장 흐름, TS 파일 실시간 업로드 동작, 끊김 복구 메커니즘은 녹화 파일은 어떻게 저장되는가에서 자세히 다룹니다.
핵심 요약
- 클라이언트 녹화(MediaRecorder)는 프로덕션 요구사항을 충족하지 못합니다 — 단일 스트림, CPU 부하, 데이터 유실 위험이 복합적으로 문제가 됩니다.
- Ghost Participant 패턴: Recorder가 채널에 Subscribe-only로 조인해서 SD-RTN을 통해 미디어를 안정적으로 수신합니다. 사용자 화면에는 보이지 않습니다.
- 하나의 채널에 여러 Recorder를 동시에 투입할 수 있습니다 — 용도(컴플라이언스/AI 처리)나 모드(Individual/Mix)를 분리하거나, 중복 녹화로 안정성을 높일 수 있습니다.
- resourceId에는 TTL이 있음 (
resourceExpiredHour로 설정, 기본 72시간) — 그래도acquire직후 즉시start를 호출하는 것이 안전합니다.sid는 DB에 저장하세요. - 인증 키는 두 종류: REST API용 Customer Key/Secret(서버 전용)과 RTC 채널 입장용 Token(Recorder 포함)을 혼동하지 마세요.
시리즈 네비게이션
실시간 통화, 어떻게 녹화하는가 시리즈