Technical Blog

기술 인사이트

실시간 통신, 미디어 처리, AI 통합에 대한 심층 분석.Agora SDK를 중심으로 프로덕션 레벨의 구현을 다룹니다.

53
포스트
7
카테고리
추천 자료아키텍처 트랙

WebRTC 아키텍처 트랙

WebRTC 아키텍처 글을 읽기 전에 먼저 보는 추천 자료입니다. Mesh, SFU, MCU, Hybrid 구조를 다이어그램과 시퀀스 흐름으로 비교합니다.

아키텍처 트랙 열기
MeshSFUMCUclient loadserver control
Media
·18분 읽기

YouTube·Twitch 라이브 스트리밍 아키텍처 — OBS에서 시청자 화면까지 glass-to-glass 지연 분해

라이브 방송은 카메라 앞 장면이 어떻게 수십 초 이하 지연으로 전 세계 시청자 화면에 도착할까요? OBS 인코더, RTMP/RTMPS ingest, 가까운 PoP, 플랫폼 백본, 트랜스코딩, ABR ladder, HLS/DASH 패키징, CDN, 플레이어 버퍼까지 glass-to-glass 경로를 시각적으로 분해합니다. YouTube의 latency knob과 Twitch의 low latency 모드가 실제로 무엇을 줄이고 무엇을 희생하는지도 함께 정리합니다.

Live StreamingYouTube LiveTwitchRTMP+7
Media
·12분 읽기

Stream과 RTP의 관계 — Cloud Recording 디버깅에서 헷갈리지 않는 법

stream은 논리적인 미디어 흐름이고 RTP는 그 미디어를 네트워크로 운반하는 패킷 프로토콜입니다. 하지만 WebRTC API의 MediaStream, Agora 운영 문맥의 stream, RTP의 SSRC packet stream은 같은 말이 아닙니다. 이 글은 track, stream, RTP, RTCP의 층위를 분리하고, muteLocalVideoStream, enableLocalVideo, stopPreview, leaveChannel이 Cloud Recording에서 어떻게 다르게 보이는지 검증된 기준으로 정리합니다.

WebRTCAgoraCloud RecordingRTP+6
Backend
·24분 읽기

SSL 인증서 완전 이해 가이드 — 만료·갱신 책임·DNS-01·CNAME 자동화

인증서 만료 6일 전 알림을 받았다면 무엇부터 확인해야 할까요? TLS 인증서가 일부러 만료되도록 설계된 이유부터 서비스 제공자가 Not After를 감지하는 방식, 고객 직접 제공과 관리형 인증서의 책임 경계, DNS-01에서 CNAME의 HOST와 VALUE가 맡는 역할까지 시각적인 흐름으로 정리합니다. 실고객 주소 대신 live.frank.example 가상 도메인으로 Cloudflare·Route 53 설정, dig·openssl 검증, CAA와 기존 TXT 충돌 같은 자동 갱신 실패 원인까지 실무 체크리스트로 설명합니다.

SSLTLS인증서ACME+6
Fundamentals
·17분 읽기

WebRTC 첫걸음 — 왜 UDP인가, P2P는 왜 무너지나, 그리고 SFU라는 우체국

화상회의에 10명이 들어가면 왜 서버가 필요할까요? 브라우저끼리 직접 연결하면 공짜 아닌가요? 이 질문에 답하려면 세 가지를 순서대로 설명해야 합니다 — 왜 실시간 미디어는 TCP가 아닌 UDP여야 하는지(Head-of-Line Blocking), 왜 P2P는 인원이 늘면 업로드 회선부터 무너지는지, 그리고 SFU라는 중간 서버가 정확히 무슨 일을 하는지. WebRTC를 처음 접하는 분도 따라올 수 있게 택배·우체국 비유와 다이어그램으로 풀고, 프리세일즈 미팅의 단골 심화 질문 두 가지 — 인코딩·디코딩은 기기와 서버 중 어디서 하는가, 1:1 통화도 SFU를 거치는가 — 까지 논리적으로 정리합니다. 마지막에는 고객 질문별 30초 답변 치트시트를 붙였습니다.

WebRTCSFUP2PUDP+7
AI
·20분 읽기

TEN Framework TTS 딥다이브 — Template Method 패턴, HTTP vs WebSocket, Chunk Size 트레이드오프

TEN Framework의 TTS 확장을 개발하면서 마주치는 핵심 설계 결정을 정리합니다. AsyncTTS2HttpExtension과 AsyncTTS2WSExtension이 Template Method 패턴으로 어떻게 복잡한 큐 관리·TTFB 계측·에러 핸들링을 숨기는지, HTTP와 WebSocket 각각의 TTFB 차이(~300ms vs ~50ms), 그리고 chunk_size 4096B 권장치의 근거를 인터랙티브하게 탐색합니다.

TEN FrameworkTTSAsyncTTS2HttpExtensionAsyncTTS2WSExtension+8
Media
·18분 읽기

HLS vs DASH — 매니페스트·세그먼트·DRM·저지연, 그리고 CMAF가 둘을 합친 방법

iOS 앱과 웹, 스마트TV를 한 서비스에서 다 지원해야 할 때 HLS와 DASH 중 무엇을 골라야 할까요? 사실 양자택일 문제가 아닙니다. 둘은 영상을 짧은 조각으로 잘라 HTTP로 배달한다는 본질이 같고, 매니페스트 문법과 세그먼트 포맷, DRM 생태계만 다릅니다. 이 글은 .m3u8과 .mpd, MPEG-TS와 fMP4, FairPlay와 Widevine, 그리고 LL-HLS와 LL-DASH의 저지연 방식을 비교하고, 세그먼트 한 벌로 양쪽을 동시에 서비스하는 CMAF까지 정리합니다. 흔히 LL-HLS의 핵심으로 알려진 HTTP/2 Push가 사실 2020년 스펙에서 빠졌다는 점도 바로잡습니다.

HLSDASHCMAFfMP4+8
Media
·22분 읽기

라이브 스트리밍 송출 파이프라인 — RTMP 수신부터 ABR·m3u8 실시간 갱신, 그리고 6초 지연의 정체

유튜브 라이브는 왜 항상 6초, 길게는 30초씩 늦게 보일까요? 흔히 느린 서버 탓이라 생각하지만, 진짜 원인은 영상을 작은 파일로 잘라 HTTP로 주기적으로 가져가는 HLS의 구조 자체에 있습니다. 이 글은 OBS가 RTMP를 쏘는 순간부터 시청자 화면에 픽셀이 그려질 때까지의 4단 파이프라인을 따라가며, 세그먼트 길이와 플레이어 버퍼가 어떻게 지연을 쌓는지, AWS MediaLive와 MediaConvert는 왜 역할이 다른지, 그리고 같은 라이브라도 양방향 대화엔 왜 WebRTC가 답인지를 풀어냅니다.

라이브 스트리밍RTMPHLSABR+7
Media
·20분 읽기

SFU는 어떻게 100명·1000명을 감당하나 — 단일 노드 한계와 Cascading

화상회의는 100명까지 되는데, 라이브 방송은 어떻게 같은 WebRTC로 10만 명에게 영상을 뿌릴까요? 답은 단일 기술이 아니라 규모에 따라 토폴로지를 갈아끼우는 데 있습니다. 서버 없이 직결하는 P2P가 왜 4~6명에서 무너지는지, SFU가 디코딩 없이 패킷만 포워딩해 0.2~0.5초 저지연을 내는 원리, 단일 노드가 보통 500~1000명에서 막히는 복합적 이유, 그리고 그 한계를 지역 엣지를 묶는 Cascading으로 넘다가 수십만 시청자 앞에서는 결국 HLS/CDN으로 갈아타는 분기점까지 짚어 봅니다.

SFUMCUMeshP2P+6
Media
·18분 읽기

WebRTC 벤더 지형도 — 누가 libwebrtc 위에 무엇을 얹었나 (Zoom·Discord·LiveKit·Agora·Slack·Meta)

"주요 RTC 벤더들은 결국 다 구글 libwebrtc 위에 얹은 거 아닌가요?" 벤더 비교 자리에서 흔히 나오는 이 질문의 답은 절반만 맞습니다. 대부분 WebRTC 표준이나 libwebrtc에서 출발하지만 Zoom은 독자 구현 비중이 크고 Agora 네이티브는 표준 밖으로 나갔으며, 진짜 차별화는 코덱이 아니라 SFU와 글로벌 네트워크, 손실 복구, 운영 모델 같은 인프라에서 갈립니다. Zoom, Discord, LiveKit, Agora, Slack, Meta 여섯 벤더가 무엇을 코어로 깔고 그 위에 무엇을 얹었는지 검증된 출처로 정리하고, "Discord가 미디어 엔진을 Rust로 재작성했다" 같은 흔한 오해도 함께 바로잡습니다.

WebRTClibwebrtcZoomDiscord+7
Media
·18분 읽기

모바일 영상 파이프라인의 발열 — 메모리 복사, GPU Texture, Zero-Copy, 하드웨어 코덱

"영상 통화를 좀 하면 폰이 뜨끈해지고 배터리가 훅 닳는데, 코덱 설정이 문제일까요?" 답은 코덱만이 아니라, 카메라 센서에서 화면까지 가는 동안 프레임 버퍼를 몇 번이나 복사하느냐, 그리고 인코딩을 CPU가 떠안느냐 전용 칩이 처리하느냐에서 갈립니다. 이 글은 모바일 영상 파이프라인을 따라가며 메모리 복사가 왜 생기고 Zero-Copy가 이를 어떻게 없애는지, 안드로이드와 iOS가 텍스처 핸들 공유로 같은 철학을 어떻게 구현하는지, 하드웨어 인코딩이 전력에서 왜 압도적인지를 짚습니다. 모바일에 별도 VRAM이 있다는 통념과 통합 메모리의 실제도 함께 정리합니다.

Zero-CopyGPUTextureSurfaceTexture+6
Fundamentals
·25분 읽기

하나의 C++ 코어로 iOS와 Android를 — 네이티브 코드, 크로스 컴파일, .so/.a, JNI, Objective-C++

"WebRTC 엔진이 C++라는데, iOS랑 Android에서 그 코드를 같이 쓰는 건가요? 플랫폼마다 다시 짜는 거 아닌가요?" 모바일 RTC 도입 자리에서 자주 나오는 질문입니다. 답은 코어 로직을 C++ 하나로 짜고 플랫폼마다 얇은 연결 계층만 따로 붙인다는 것입니다. 왜 코어가 C++인지, ABI가 다르면 왜 .so 하나로 안 되는지, 정적과 동적 라이브러리의 진짜 구분 기준은 무엇인지, Android는 JNI로 iOS는 Objective-C++로 어떻게 잇는지, 그리고 코어가 앱에 박혀 있어 업데이트하려면 앱을 다시 빌드해야 한다는 대가까지 차근히 짚어 드립니다.

C++JNIObjective-C++크로스 컴파일+8
Media
·16분 읽기

Meta는 WebRTC를 어떻게 자체 엔진으로 만들었나 — libwebrtc Fork의 함정과 Shim 아키텍처

"Meta 정도면 WebRTC도 바닥부터 만들지 않았을까?" 매일 수십억 통화를 처리하는 회사라면 그럴 법하지만, 실제로는 구글 libwebrtc를 fork해서 출발했고 수년 뒤 오히려 upstream으로 되돌아왔다. 이 글은 fork가 왜 시간이 갈수록 부채가 되는지, Meta가 두 버전을 한 바이너리에 공존시키며 빠져나온 shim 아키텍처가 무엇인지, 그리고 AV1 코덱처럼 진짜 자체 개발한 영역과 공개 자료로 확인되지 않는 주장을 어떻게 구분해야 하는지 정리한다.

MetaFacebookWebRTClibwebrtc+6
Media
·15분 읽기

Agora 자체 코덱과 Web SDK의 정체 — WebRTC 표준, SD-RTN 전용망, FEC의 분업

"Agora는 자체 코덱을 써서 빠르다는데, 브라우저에서는 어떻게 동작하나요?" 도입 검토 자리에서 가장 자주 나오는 질문입니다. 답의 핵심은 코덱과 네트워크를 분리해서 보는 것. 네이티브에서는 자체 코덱과 SD-RTN 전용망을 모두 쓰지만, 웹은 WebRTC 제약 때문에 VP8/H.264 표준 코덱을 강제당하고 오직 경로 최적화로만 차별화합니다. 이 글은 그 분업 구조와 함께, 해저케이블을 깐 게 아니라 같은 ISP 회선 위에서 라우팅 제어권을 가져간다는 SD-RTN의 실체, 재전송 없이 손실을 복원하는 FEC의 원리까지 풀어냅니다.

AgoraWebRTCSD-RTNWeb SDK+6
Media
·20분 읽기

영상 압축의 본질 — I/P/B-frame, GOP, 그리고 HLS가 같이 죽는 이유

라이브 송출 중 화면이 멈추고 로그에 EXTINF:18이 찍혔다면, 진짜 범인은 HLS 패키저가 아니라 인코딩 파이프라인 위쪽일 가능성이 큽니다. 이 글은 영상이 왜 압축되어야 하는지부터 I·P·B 프레임의 역할, keyint이 시간이 아니라 프레임 개수라는 사실, 그리고 CPU 과부하로 fps가 무너지면 같은 설정인데도 GOP가 늘어나 HLS까지 같이 죽는 인과 사슬을 설명합니다. 끝까지 읽으면 segment 길이 한 줄만 보고 어디가 깨졌는지 거꾸로 추적하는 법을 알게 됩니다.

영상 압축I-frameP-frameB-frame+8
Telephony
·22분 읽기

AI 콜봇 멀티콜이 안 되던 날 — SIP 트렁크 Bridge 모드 vs B2BUA(IVR) 모드

단일콜은 그럭저럭 되는데, 여러 명에게 동시에 거니까 콜 상태가 꼬인다면 트렁크의 동작 모드를 의심해야 합니다. 같은 SIP 트렁크 장비라도 발신 주체가 누구냐에 따라 셋업이 달라지는데, AI 콜봇처럼 시스템이 직접 발신하는 구조에서는 Bridge 모드로는 멀티콜이 깨지고 B2BUA, 현장에서 흔히 IVR 모드라 부르는 방식이 필요합니다. 이 글은 SIP 기초와 두 모드의 차이, 그리고 AI가 ringback에 대고 인사하던 200 OK 타이밍 문제까지 실제 트러블슈팅 과정을 따라가며 풀어냅니다.

SIPB2BUAIVRPDS+7
Media
·25분 읽기

라이브 스트리밍 프로토콜 선택 — HLS / LL-HLS / WebRTC 의사결정

"라이브 커머스에 HLS면 충분할까, 스포츠 중계는 LL-HLS와 WebRTC 중 뭘 써야 할까?" 답은 늘 같습니다. 시청자에게 허용되는 지연 예산이 프로토콜을 자동으로 결정하기 때문입니다. 이 글은 HLS, LL-HLS, WebRTC 세 가지를 지연 분해와 내부 동작, 비용과 호환성, 한국 시장 현실까지 비교해 30초면 표준 HLS, 5초 이내면 LL-HLS, 1초 미만이면 WebRTC라는 의사결정 프레임을 정리합니다.

HLSLL-HLSWebRTC프로토콜 선택+7
Media
·25분 읽기

Agora SEI 메타데이터 — 비디오에 박힌 레이아웃 정보의 바이너리 해부

합성 송출을 받는 시청자 앱에서 "지금 화면 어디에 누가 있는지"를 어떻게 알아낼까요? 별도 시그널링으로 보내면 비디오 프레임과 타이밍이 어긋나기 마련인데, 답은 비디오 스트림 안에 메타데이터를 박아 보내는 SEI에 있습니다. 이 글은 H.264와 H.265 표준의 SEI가 무엇인지, Agora Media Push가 레이아웃 JSON을 어떤 바이트 포맷으로 박아 주는지, 그리고 시청자 파서가 NAL 헤더부터 0xFF 누적 길이, JSON 파싱까지 어떻게 풀어내는지 차근차근 짚어 줍니다.

SEIH.264H.265NAL+7
Media
·22분 읽기

ABR Ladder의 Layer B 정렬 — 화질 전환 시 키프레임 동기화

"720p로 보다가 1080p로 자동 전환되는 순간 화면이 깨져요." 화질을 바꿀 때 잠깐 멈추거나 검은 화면이 뜨는 신고는 대부분 ABR ladder의 모든 화질이 같은 시간점에 키프레임을 갖지 못해서 생깁니다. 이 글은 화질 전환이 결국 다른 스트림으로 갈아타는 일이라는 점에서 출발해, 왜 모든 화질의 I-frame이 같은 시각에 박혀야 하는지, 그리고 단일 인코더 동시 출력과 force_key_frames, scene-cut 끄기로 그 정렬을 보장하고 ffprobe로 검증하는 방법까지 풀어냅니다.

ABRHLS키프레임 정렬Layer B+5
Media
·20분 읽기

GOP-세그먼트 정렬의 산수 — Agora Media Push에서 YouTube/Twitch까지

YouTube Studio가 자꾸 키프레임 경고를 띄우거나, Agora Media Push에 GOP를 넉넉히 잡았는데 오히려 화질이 떨어진 적이 있나요? 두 증상 모두 결국 한 줄의 산수로 풀립니다. 세그먼트 길이는 인코더가 아니라 YouTube나 Twitch 같은 송출 플랫폼이 정하고, GOP는 그 길이의 정수 약수로 맞춰야 한다는 규칙이죠. 이 글은 GOP가 어긋났을 때 HLS 패키저가 무엇을 하는지, 그리고 Agora Media Push의 gop 값을 플랫폼에 맞게 어떻게 계산하는지를 정리합니다.

GOPHLSSegmentAgora Media Push+8
Telephony
·30분 읽기

VoIP 푸시 인프라 완전 가이드 — APNs · PushKit · CallKit · Agora 통합 구현

"통화용 푸시 토큰은 일반 알림 토큰이랑 같은 거 아닌가요? 인증서는 왜 두 개나 받으라는 거죠?" RTC를 도입하는 고객이 가장 자주 던지는 질문입니다. 이 글은 PushKit이 별도 시스템이 아니라 APNs 위에서 도는 특수 모드라는 핵심을 짚으면서, 일반 푸시와 VoIP 푸시가 인증서, 토큰, 페이로드, 처리 방식까지 왜 갈라지는지 풀어냅니다. PushKit 등록부터 CallKit과 Agora RTC를 묶는 통합 코드, 그리고 자체 구축과 Agora Chat 매니지드 중 무엇을 골라야 하는지까지 실무 기준으로 정리했습니다.

iOSPushKitAPNsVoIP+5
Telephony
·25분 읽기

iOS VoIP 통합의 4-레이어 모델 — CallKit · PushKit · AVAudioSession · Agora ADM

CallKit을 붙였더니 수신은 되는데 처음 3초가 무음이고, 통화 중 알람 한 번에 마이크가 죽는다면 원인은 한 곳에 있습니다. CallKit의 진짜 역할은 통화 UI를 그리는 게 아니라 오디오 세션을 언제 켤지 결정하는 권한을 시스템이 가져가는 것이기 때문입니다. 이 글은 PushKit, CallKit, AVAudioSession, Agora ADM이 어떻게 얽히는지 4개 레이어로 정리하고, didActivate에서 채널에 들어가고 didDeactivate에서 ADM을 재시작하는 원칙으로 무음과 인터럽트, 멀티앱 오디오 누수까지 여섯 가지 실전 케이스를 풀어냅니다.

iOSCallKitPushKitAVAudioSession+5
Backend
·18분 읽기

TTFB 분해 — DNS / TCP / TLS / 서버 처리, 어디서 350ms가 새는가

"TTFB는 350ms인데 ping은 7ms입니다. 서버가 느린 건가요?" 답하려면 TTFB가 서버 처리 시간이 아니라는 사실부터 짚어야 합니다. 이 글은 요청부터 첫 바이트가 도착하기까지를 DNS 조회, TCP 핸드셰이크, TLS 협상, 서버 처리 네 단계로 분해하고, curl 한 줄로 각 구간 비용을 측정해 350ms가 실제로 어디서 새는지 찾아냅니다. ping 값에 따라 병목이 서버인지 네트워크인지 DNS 콜드 스타트인지 가려내는 진단법과 단계별 처방까지 정리했습니다.

TTFBDNSTCPTLS+5
Backend
·15분 읽기

Cloud Recording 점프 재생 무한 로딩 — moov / ENDLIST / DISCONTINUITY 트러블슈팅

다운로드는 다 끝났는데 영상을 중간으로 점프하면 무한 로딩이 걸리거나 아예 재생이 안 됩니다. 알고 보면 데이터가 손상된 게 아니라 인덱스가 불완전한 경우가 대부분입니다. 이 글은 MP4의 moov atom 위치, HLS의 ENDLIST 누락, 그리고 DISCONTINUITY 누락이라는 세 가지 패턴을 진단하는 법과 ffmpeg으로 고치는 처방을 정리하고, Agora Cloud Recording 결과물에 바로 쓸 수 있는 후처리 파이프라인까지 안내합니다.

Cloud RecordingMP4HLSmoov+5
Telephony
·12분 읽기

시그널링과 미디어의 분리 — RTSP / SIP vs RTP의 통제 평면

"통화는 멀쩡히 연결됐는데 왜 한쪽 음성만 안 들릴까?" SIP와 RTSP 같은 시그널링은 통화를 걸고 코덱을 협상할 뿐, 실제 음성과 영상은 RTP가 따로 운반합니다. 이 글은 둘이 왜 다른 포트와 경로로 분리됐는지 설명하고, 그 구조 덕에 "신호는 OK, 미디어만 실패" 같은 증상을 어떻게 갈라서 진단하는지까지 짚습니다.

RTSPSIPRTPRTCP+5
Media
·10분 읽기

라이브 스트림 상태 점검 — ffprobe / gstreamer 실전 명령어

"이 RTSP 카메라 살아있나?" 라이브 스트림에 문제가 생기면 제일 먼저 던지는 질문입니다. 이 글은 현장에서 실제로 쓰는 네 가지 점검 명령어를 상황별로 정리합니다. ffprobe로 응답 여부를 찔러보고, 패킷의 pts/dts 타임스탬프를 까서 끊김이나 시간 어긋남을 진단하고, 프레임별 시각을 csv로 뽑아 이미지와 매칭하고, gst-discoverer로 코덱과 해상도를 한 화면에 확인하는 법까지 다룹니다. 각 도구가 무엇을 보여주고 어떤 신호를 읽어야 하는지에 초점을 맞췄습니다.

ffprobeffmpeggstreamerRTSP+4
Media
·15분 읽기

x264 실전 옵션 — ref, tune, keyint 완전 가이드

OBS나 FFmpeg 설정 화면에서 ref, tune, keyint 같은 x264 옵션을 만나면 무슨 값을 넣어야 할지 막막하시죠? 실시간 송출과 VOD가 왜 정반대 값을 쓰는지, ref=1과 zerolatency가 지연과 손실 복구에 어떻게 작용하는지 하나씩 풀어봅니다. 특히 '키프레임 2초'가 업계 표준이 된 이유를 HLS 세그먼트, 채널 조인 대기, 손실 복구 관점에서 짚어 실전 설정값까지 바로 가져갈 수 있게 정리했습니다.

x264H.264reftune+6
Fundamentals
·30분 읽기

B-frame 완전정복 — 5 STEP으로 이해하는 '미래를 아는 인코더'

B-frame은 대체 어떻게 미래 프레임을 미리 알고 압축하는 걸까요? 답은 의외로 단순합니다. 카메라가 이미 다 찍어 버퍼에 쌓아둔 데이터를 인코더가 꺼내 쓰는 것뿐입니다. 이 글은 앞뒤 프레임을 모두 참조하는 B-frame의 원리를 비유와 그림으로 따라가며, 촬영 순서와 전송 순서가 왜 달라지는지, 그리고 압축률이 가장 높은데도 영상통화 같은 WebRTC 환경에서는 왜 쓰지 않는지를 인코딩 지연과 패킷 손실의 관점에서 풀어냅니다.

B-frameI-frameP-frameGOP+9
Media
·22분 읽기

H.264 Profile·인코더 옵션·비트레이트의 현실 — WebRTC 운영자를 위한 코덱 현장 지침

"720p라는데 왜 이렇게 화질이 구리지?" 같은 리포트를 받아본 적 있다면, 답은 대개 비트레이트 부족, 프로파일 미스매치, 하드웨어 인코더 실패 셋 중 하나입니다. 이 글은 WebRTC 운영자가 실무에서 마주치는 코덱 선택을 정리합니다. H.264 네 가지 프로파일의 차이부터, 왜 Main이나 High에 B-frame을 꺼서 쓰는 것이 현실적인 답인지, 720p 30fps에 1.5에서 2.5Mbps가 필요한 수학적 근거, 그리고 해상도와 프레임레이트별 권장 비트레이트까지 체크리스트로 쓸 수 있게 풀어냅니다.

H.264ProfileBaselineMain+9
Fundamentals
·20분 읽기

프레임의 모든 것 — Interlaced / I·P·B-frame / GOP / PLI·FIR까지

"720p의 p가 뭐예요?", "I-frame은 뭐고 P-frame은 뭐예요?" 영상 품질 이슈를 파다 보면 늘 같은 질문에 막힙니다. 이 글은 프레임이라는 개념부터 시작해 인터레이스와 프로그레시브의 차이, I·P·B 프레임이 각각 무엇을 담는지, GOP가 왜 2초인지, 그리고 PLI와 FIR가 어떻게 끊긴 화면을 되살리는지까지 현실 예시로 풀어냅니다. 다 읽고 나면 WebRTC가 왜 B-frame을 피하고 I와 P만 쓰는지, 그 구조적 이유가 손에 잡힐 겁니다.

InterlacedProgressiveI-frameP-frame+8
Media
·22분 읽기

RTMP 라이브 송출의 B-frame이 만든 PTS rollback — WebRTC 변환 경로의 실패 지점 추적

라이브 영상이 주기적으로 멈췄다 복구되고, 수신 로그에는 timestamp rollback이 찍힙니다. 대역폭도 정상이고 연결도 멀쩡한데 왜 그럴까요? RTMP 방송을 Wowza로 받아 Agora Media Gateway로 WebRTC에 중계하던 파이프라인을 추적해보니, 범인은 송출단 인코더의 Main profile과 B-frame 설정이었습니다. B-frame이 DTS와 PTS를 분리하는 데 반해 RTP는 타임스탬프가 하나뿐이라 충돌하는 원리부터, 네 가지 격리 테스트로 책임 경계를 좁히는 과정, 그리고 Baseline이나 bframes=0으로 푸는 해결책까지 정리했습니다.

RTMPWebRTCH.264B-frame+6
Fundamentals
·20분 읽기

오디오 파이프라인 해부 — 마이크부터 스피커까지, 코덱·RTP·Jitter Buffer

마이크에 대고 말한 소리가 상대방 스피커에서 나기까지, 그 사이에는 ADC와 전처리, 코덱 인코딩, RTP 패킷화, UDP 전송, Jitter Buffer, 디코딩이 차례로 일어납니다. 이 글은 각 단계에서 왜 그런 선택을 하는지를 시니어 엔지니어 시선으로 짚습니다. 실시간 통신이 정확성 대신 지연을 줄이려 UDP를 쓰는 이유, Opus와 µ-law와 AAC를 언제 갈라 쓰는지, Jitter Buffer가 끊김을 흡수하는 방식, 그리고 RTMP와 WebRTC를 오가는 변환과 Voice AI의 VAD까지 하나의 흐름으로 연결해 봅니다.

OpusRTPUDPJitter Buffer+7
Fundamentals
·15분 읽기

PCM vs WAV — 44바이트 헤더의 오해, 컨테이너와 코덱의 차이

"WAV는 무조건 44바이트 헤더 다음부터 데이터다", "PCM이면 다 비압축이다" 이런 말을 믿고 코딩하다 소리가 깨진 적 있나요? PCM은 소리를 숫자로 저장한 인코딩 방식이고 WAV는 그 숫자에 설명서를 붙인 컨테이너라는 차이부터, µ-law 같은 압축 PCM의 존재, 그리고 오프셋 44 하드코딩이 왜 위험한지까지 짚습니다. 샘플레이트와 채널, 비트 깊이를 잘못 해석하면 어디서 음성이 망가지는지, 브라우저와 STT 실무에서 무엇을 챙겨야 하는지 정리했습니다.

PCMWAVRIFFMP3+4
Fundamentals
·15분 읽기

소리는 어떻게 숫자가 되는가 — PCM, MP3 압축, 스피커 재생까지

MP3가 어떻게 음질은 거의 그대로 둔 채 용량만 10분의 1로 줄이는지 궁금했던 적 있나요? 비밀은 데이터가 아니라 사람 귀의 한계에 있습니다. 이 글은 공기의 진동이 마이크에서 전기 신호가 되고, 샘플링과 양자화를 거쳐 PCM 숫자로 바뀐 뒤, 심리음향 압축으로 MP3가 되고, 다시 디코딩되어 스피커에서 소리로 돌아오는 전 과정을 그림과 함께 따라갑니다. 읽고 나면 44,100Hz와 16비트가 왜 CD 표준인지, MP3가 왜 손실 압축인지 직관적으로 이해하게 됩니다.

PCMMP3ADCDAC+2
Backend
·10분 읽기

TTS 서버 파이프라인 해부 — Google TTS → R2 캐시 → 브라우저 재생

같은 문장을 100번 읽어줘도 Google TTS 요금이 1회분만 나오게 하려면 어떻게 설계해야 할까? 이 글은 텍스트를 음성으로 바꾸는 서버 API의 내부를 코드와 함께 따라간다. 입력값을 SHA-256 해시로 묶어 중복을 막고, R2 대신 DB로 캐시를 조회해 응답을 50배 빠르게 만들며, await를 떼어내 업로드를 백그라운드로 넘기는 트릭까지 읽고 나면, 작은 오디오 요청 하나가 비용과 속도를 동시에 챙기는 구조가 손에 잡힌다.

TTSR2캐시Base64
Fundamentals
·8분 읽기

Base64 & 바이너리 기초 — JSON이 MP3를 못 담는 이유

Google TTS는 MP3를 JSON 응답에 base64 문자열로 담아 보냅니다. 그냥 바이너리를 넣으면 안 되는 걸까요? JSON 파서가 ff f3 같은 바이트를 만나면 왜 깨지는지, MP3 파일 안에는 실제로 뭐가 들어 있는지, base64가 어떻게 비트를 6개씩 재배치하는지를 바이너리 기초부터 풀어냅니다. 용량이 33% 늘어나는 이유와 패딩 기호의 정체까지 따라가다 보면, base64가 압축도 암호화도 아닌 안전한 표현 방식이라는 점이 분명해집니다.

Base64BinaryMP3Buffer+1
Media
·12분 읽기

Bitrate 완전 정복 — 같은 해상도인데 왜 화질이 다른가

같은 720×1280 영상인데 한쪽은 선명하고 한쪽은 뭉개져 보이는 이유는 무엇일까요? 해상도가 캔버스 크기라면 bitrate는 그 위에 얼마나 세밀하게 그릴지를 정하는 초당 데이터 예산입니다. 이 글에서는 해상도, FPS, bitrate가 얽힌 삼각관계부터 Cloud Recording이 호스트 송출에서 녹화 파일까지 거치며 화질을 깎아먹는 단계, 그리고 화질 문제가 들어왔을 때 해상도와 채널 모드, FPS, bitrate, 방향을 순서대로 짚는 디버깅 방법까지 정리했습니다.

BitrateCloud RecordingHLSffprobe+1
Backend시리즈
·15분 읽기

FFmpeg 실전 파이프라인 — Agora 녹화에서 프로덕션 VOD까지

Individual 모드로 녹화하면 S3에는 유저별로 쪼개진 m3u8과 수백 개의 ts 세그먼트만 쌓일 뿐, 바로 보여줄 VOD는 없습니다. 이 글은 그 원자재를 프로덕션 다시보기로 만드는 전 과정을 따라갑니다. m3u8을 MP4로 무손실 변환하고, 파일명에 박힌 UTC 타임스탬프로 유저들의 입장 시점을 맞추고, 여러 화면을 하나의 그리드로 합성한 뒤 CRF와 2-pass로 품질을 조율하는 FFmpeg 명령을 하나씩 풀어냅니다. 마지막에는 S3에서 받아 CDN으로 올리는 자동화 스크립트와, 언제 Mix 대신 Individual이 경제적인지까지 짚습니다.

FFmpegCloud Recordingfilter_complexCRF+1
Backend시리즈
·14분 읽기

FFmpeg, 미디어의 스위스 아미 나이프 — 컨테이너, 코덱, 스트림

녹화 파일이 만들어진 뒤 사용자에게 닿기까지, TS를 MP4로 바꾸고 트랙을 합치고 구간을 자르는 후처리의 한복판에는 늘 FFmpeg이 있다. 이 글은 컨테이너와 코덱, 스트림이라는 세 개념으로 FFmpeg을 다시 정리하고, 왜 후처리의 대부분이 무손실 remux인 -c copy로 끝나는지, 트랜스코딩은 언제 꺼내야 하는지를 명령어 예시와 함께 풀어낸다. 디코딩부터 인코딩까지 내부 5단계가 어떻게 돌아가는지 알고 나면 에러 메시지도 옵션 조합도 한결 또렷해진다.

FFmpegCodecContainerMuxing+1
Media시리즈
·12분 읽기

M3U8과 TS 파일의 모든 것 — HLS Deep Dive

녹화 파일을 열었더니 MP4가 아니라 m3u8 파일 하나와 잘게 쪼개진 ts 조각들이 나옵니다. 왜 이런 구조일까요? 답은 장애 내성에 있습니다. MP4는 재생에 필요한 메타데이터가 파일 끝에 몰려 있어 서버가 중간에 죽으면 녹화 전체를 잃지만, HLS는 영상을 짧은 세그먼트로 쪼개 저장하므로 이미 완성된 조각은 살아남습니다. 이 글에서는 그 차이가 생기는 원리부터 TS 패킷 구조, M3U8 태그 해석, 세그먼트를 I-frame에서 자르는 이유, Agora의 슬라이싱 규칙까지 실무에서 녹화 파일을 다룰 때 알아야 할 내용을 정리합니다.

HLSM3U8TSI-frame+1
Media시리즈
·12분 읽기

녹화 모드 해부 — Individual, Mix, Web의 내부 파이프라인

같은 채널을 녹화해도 Individual, Mix, Web 중 무엇을 고르느냐에 따라 서버 안에서 벌어지는 일이 완전히 달라집니다. 출력 파일 구조부터 CPU 부하, 비용까지 모두 이 선택 시점에 결정되기 때문입니다. 각 모드가 스트림을 어떻게 처리하는지, 오디오 믹싱과 비디오 합성이 내부적으로 어떤 연산을 거치는지, 그리고 헤드리스 브라우저로 화면을 캡처하는 Web 모드가 왜 가장 무거운지를 짚어 봅니다. 어떤 상황에 어떤 모드를 골라야 하는지 판단 기준까지 정리합니다.

Cloud RecordingIndividualMixWeb+1
Backend시리즈
·8분 읽기

내 서버에서 직접 녹화한다면 — On-Premise vs Cloud Recording

"데이터가 반드시 우리 서버에 있어야 합니다." 이 한 마디가 나오는 순간, 편리한 Cloud Recording은 선택지에서 빠집니다. 규제 산업이나 영상 프레임을 실시간 AI로 분석해야 하는 상황이라면, 녹화 파일이 외부 클라우드를 거치는 구조 자체가 문제가 되기 때문입니다. 이 글은 자체 Linux 서버에 Native SDK를 설치하는 On-Premise Recording이 Cloud와 어떻게 다른지, YUV 프레임과 PCM 샘플에 직접 접근해 실시간 AI 파이프라인을 어떻게 구성하는지, 그리고 운영 부담을 감수하고서라도 On-Premise를 골라야 하는 기준은 무엇인지 정리합니다.

On-Premise RecordingCloud RecordingYUVRaw Data+1
Backend시리즈
·10분 읽기

실시간 통화, 왜 녹화해야 하는가 — Cloud Recording Architecture

통화가 끝나면 대화는 그냥 사라집니다. WebRTC는 본질적으로 일시적이라 미디어가 흐르고 연결이 끊기면 그걸로 끝이죠. 하지만 금융 상담 기록 제출, 과외 수업 다시보기, 원격 진료 기록 연동처럼 통화가 사라지면 안 되는 상황은 점점 많아집니다. 이 글은 왜 브라우저 직접 녹화로는 부족한지, Agora Cloud Recording이 유령 참가자 패턴으로 어떻게 채널에 몰래 들어와 녹화하는지, acquire부터 stop까지 라이프사이클과 두 종류의 인증 키를 어떻게 다루는지 설명합니다.

Cloud RecordingGhost ParticipantSD-RTNREST API
Backend
·8분 읽기

Cloud Recording 녹화 파일은 어떻게 저장되는가? — S3 실시간 업로드, 끊김 복구, 재생까지

상담 통화를 Agora Cloud Recording으로 녹화하면 그 파일은 S3에 정확히 언제, 어떻게 올라갈까요? 녹화 중에 TS 조각이 실시간으로 업로드되는 구조부터, 네트워크가 끊겼을 때 어떤 파일이 살아남고 무엇이 깨지는지, 30분 상담이면 MP4가 왜 하나로 끝나는지까지 짚어봅니다. 마지막에는 S3에 쌓인 녹음을 presigned URL로 안전하게 재생하는 실제 백엔드와 플레이어 코드까지 담았습니다.

Cloud RecordingS3HLSMP4+1
AI
·12분 읽기

Agora 실시간 Agent STT + 번역 구현하기

한국어로 말하는데 화면에는 곧바로 영어 자막이 뜨게 하려면 어떻게 해야 할까요? 클라이언트가 직접 음성을 인식하는 게 아니라, Agora ConvoAI 에이전트가 클라우드에서 RTC 채널에 들어와 음성을 듣고 인식과 번역 결과를 DataStream으로 돌려보내는 구조입니다. 이 글은 UDP 크기 제한 때문에 잘게 쪼개져 오는 청크를 어떻게 재조립하고, turn_id 기반 카드와 세그먼트, 1초 디바운스로 연속 발화를 자연스럽게 묶어 화면에 보여주는지까지 차근차근 짚어줍니다.

IntegrationSTTTranslationDataStream+1
Media
·10분 읽기

Agora의 기업 방화벽 우회 전략 — Cloud Proxy와 Firewall Whitelist

병원이나 은행처럼 방화벽이 빡빡한 기업 망에서도 Agora 화상통화가 왜 끊기지 않을까? 답은 Agora가 직접 운영하는 우회 인프라에 있다. 이 글은 도메인과 포트만 열어주는 Firewall Whitelist와, UDP가 통째로 막힌 환경에서도 TCP 443으로 트래픽을 우회시키는 Cloud Proxy를 비교하고, 어떤 망에서 어느 쪽을 골라야 하는지 정리한다. SD-RTN 백본망이 그 안정성을 어떻게 떠받치는지까지 함께 짚는다.

FirewallCloud ProxyUDP/TCP
Media
·15분 읽기

왜 P2P가 막히는가? — NAT, STUN, TURN 인터넷 구조 이해하기

분명 STUN이 알려준 공인 주소를 상대에게 전달했는데도 P2P 연결이 막히는 경험, 해본 적 있으신가요? 범인은 대개 공유기의 NAT입니다. 이 글은 NAT가 사설 주소와 공인 주소를 어떻게 매핑하는지, 그리고 Symmetric NAT에서 목적지가 바뀔 때마다 포트가 달라져 홀펀칭이 실패하는 과정을 단계별로 풀어 줍니다. 왜 이때 TURN 릴레이가 필요한지, ICE가 host에서 STUN, TURN 순으로 후보를 시도하는 이유까지 자연스럽게 이해하게 됩니다.

NATP2PTURNWebRTC+1
Media
·15분 읽기

WebRTC란? ICE? STUN? NAT? TURN?

서로의 IP만 알면 화상 통화가 바로 연결될 것 같지만, 실제로는 NAT와 방화벽에 막혀 좀처럼 길이 뚫리지 않습니다. 이 글은 브라우저끼리 영상과 데이터를 직접 주고받는 WebRTC가 어떤 기술인지, 그리고 연결의 걸림돌인 NAT를 넘기 위해 STUN으로 내 공인 주소를 찾고 ICE로 최적 경로를 고르며 그래도 안 될 때 TURN 서버가 미디어를 중계하는 흐름을 차근차근 풀어냅니다. 마지막에는 이 복잡한 과정을 Agora Web SDK가 어떻게 대신 처리해 주는지까지 코드로 확인할 수 있습니다.

WebRTCSTUNTURNICE+1
Backend
·6분 읽기

Cloud Recording으로 스트림 자동 녹화하기 (Backend)

사용자가 통화 도중 앱을 닫거나 네트워크가 끊기면 그동안 쌓인 녹화 데이터는 어떻게 될까요? 브라우저에서 직접 녹화하면 클라이언트 부하와 데이터 유실이라는 한계에 부딪힙니다. Agora Cloud Recording은 보이지 않는 가상 유저를 채널에 접속시켜 서버에서 스트림을 믹싱하고 S3 같은 클라우드 스토리지에 직접 저장하는 방식으로 이 문제를 풀어냅니다. acquire에서 start, stop으로 이어지는 REST API 흐름과 mix·individual·web 세 가지 녹화 모드의 쓰임새까지 정리했습니다.

Cloud RecordingREST APICSPAWS S3
Tutorial
·5분 읽기

Agora RTC를 활용한 실시간 화상 통화 구현하기

미디어 서버를 직접 세우지 않고도 브라우저에서 화상 통화를 만들 수 있을까요? Agora Web SDK를 쓰면 클라이언트 생성부터 채널 입장, 마이크와 카메라 트랙 퍼블리시, 원격 사용자 구독까지 한 흐름으로 1:1 또는 그룹 통화를 구현할 수 있습니다. 화면 공유와 음소거 제어, RTM 채팅 연동, 백엔드 토큰 발급, 그리고 미디어가 SD-RTN 릴레이망을 거치는 연결 구조까지 실제 코드로 짚어 드립니다.

AgoraRTCNext.jsWebRTC
Tutorial
·10분 읽기

RTM(Real-time Messaging)으로 실시간 채팅 시스템 구축

화상 통화 화면에 채팅창을 붙이고 싶은데 영상 스트림과 같은 연결로 텍스트까지 보내야 할까요? 답은 아닙니다. Agora는 영상과 음성을 다루는 RTC와, 채팅이나 손들기 같은 데이터를 주고받는 RTM을 별도 SDK와 별도 토큰으로 나눕니다. 이 글에서는 같은 채널명 하나로 두 파이프라인을 나란히 붙여 실시간 채팅을 만드는 법, 그리고 한글 IME 중복 전송 같은 실전 함정을 어떻게 피하는지 코드와 함께 짚어봅니다.

AgoraRTMChatMessaging
Tutorial
·8분 읽기

Agora RTC를 활용한 라이브스트리밍 구현하기 (쇼핑, 이벤트 등 활용)

쇼핑 라이브나 웨비나처럼 한 명이 방송하고 나머지는 보기만 하는 화면, 어떻게 만들까요? 일반 화상 통화는 모두가 영상을 주고받지만, 라이브 스트리밍은 방송하는 호스트와 보기만 하는 시청자로 역할을 나눕니다. 이 글은 Agora RTC를 live 모드로 띄우고 입장 전에 역할을 정하는 법부터, 호스트만 트랙을 퍼블리시하는 분기, 화면 공유, 그리고 채팅과 손들기, 참가자 수를 RTM으로 보완하는 방법까지 데모 코드와 함께 짚어 줍니다.

AgoraRTCLive Streaming호스트+1
AI
·15분 읽기

Conversational AI 통합 가이드

사용자가 말하면 AI가 음성으로 답하는 실시간 에이전트, 막상 만들려고 하면 트랜스크립트가 깨져서 나오는 순간 막막해집니다. 이 글은 Agora Conversational AI로 음성 AI를 구축하는 전 과정을 따라갑니다. LLM과 TTS 키를 서버에만 두는 토큰 설계부터, RTC로 받은 트랜스크립트를 여러 프레임으로 쪼개진 채 도착하는 청크에서 다시 조립하는 방법, RTM 텍스트 전송, 그리고 에이전트 상태 표시와 마이크 권한 타이밍 같은 실전 노하우까지 코드로 정리했습니다.

Conversational AIIntegration

시리즈: 실시간 통화, 어떻게 녹화하는가

포스트 12–17은 연재 글입니다. 순서대로 읽으시면 전체 맥락을 이해할 수 있습니다.

© 2026 Frank Kim. All rights reserved.