
프론트엔드
WebRTC AdvancedWebRTC 심화
WebRTC(Web Real-Time Communication) 심화는 피어-투-피어 미디어 스트리밍, 데이터 채널, NAT 통과 기법을 다룬다. 화상회의(Google Meet, Zoom Web), 라이브 스트리밍, P2P 파일 전송 등에 활용된다.
WebRTC 연결 흐름
1. 시그널링(Signaling): SDP 교환 (WebSocket/HTTP 경유)
2. ICE Candidate 교환: 네트워크 경로 찾기
3. STUN: 공개 IP 확인
4. TURN: NAT 통과 불가 시 릴레이 서버 사용
5. P2P 연결 수립
6. 미디어/데이터 스트리밍기본 P2P 연결
javascript
// 발신자 (Caller)
const pc = new RTCPeerConnection({
iceServers: [
{ urls: 'stun:stun.l.google.com:19302' },
{
urls: 'turn:turn.myserver.com',
username: 'user',
credential: 'password',
},
],
});
// 미디어 스트림 추가
const stream = await navigator.mediaDevices.getUserMedia({
video: { width: 1280, height: 720 },
audio: true,
});
stream.getTracks().forEach(track => pc.addTrack(track, stream));
// Offer 생성
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
signalingChannel.send({ type: 'offer', sdp: offer.sdp });
// ICE candidate 전송
pc.onicecandidate = ({ candidate }) => {
if (candidate) signalingChannel.send({ type: 'candidate', candidate });
};
// 원격 스트림 수신
pc.ontrack = ({ streams: [remoteStream] }) => {
remoteVideo.srcObject = remoteStream;
};데이터 채널 (P2P 파일 전송)
javascript
const channel = pc.createDataChannel('fileTransfer', {
ordered: true, // 순서 보장
maxRetransmits: 3, // 재전송 횟수
});
// 파일 청크 전송
async function sendFile(file) {
const chunkSize = 16384; // 16KB 청크
const reader = file.stream().getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
// 버퍼 관리 (백프레셔)
if (channel.bufferedAmount > chunkSize * 4) {
await new Promise(resolve =>
channel.addEventListener('bufferedamountlow', resolve, { once: true })
);
}
channel.send(value);
}
channel.send(JSON.stringify({ type: 'done', name: file.name }));
}SFU 아키텍처 (다자간 회의)
P2P (소규모): 각 참가자 ↔ 모든 참가자 직접 연결
N명 참가 시 N*(N-1)/2 연결
SFU (Selective Forwarding Unit):
각 참가자 → SFU (1개 업스트림)
SFU → 각 참가자 (N-1 다운스트림)
서버 부하 줄고, 참가자 연결 단순화
예: mediasoup, Janus, LiveKit