통신, 게임 또는 파일 전송을 위해 두 브라우저 간에 데이터를 전송하는 것은 다소 복잡한 프로세스일 수 있습니다. 데이터를 중계하는 서버를 설정하고 비용을 지불해야 하며, 이를 여러 데이터 센터로 확장해야 할 수도 있습니다. 이 시나리오에서는 지연 시간이 길어질 수 있으며 데이터를 비공개로 유지하기가 어렵습니다.
이러한 문제는 WebRTC의 RTCDataChannel API를 사용하여 한 피어에서 다른 피어로 직접 데이터를 전송하여 완화할 수 있습니다. 이 도움말에서는 데이터 채널을 설정하고 사용하는 방법의 기본사항과 오늘날 웹에서 흔히 사용되는 사용 사례를 다룹니다.
다른 데이터 채널이 필요한 이유는 무엇인가요?
WebSocket, AJAX, Server Sent Events가 있습니다. 다른 커뮤니케이션 채널이 필요한 이유는 무엇인가요? WebSocket은 양방향이지만 이러한 기술은 모두 서버와의 통신을 위해 설계되었습니다.
RTCDataChannel는 다른 접근 방식을 취합니다.
- 피어 투 피어 연결을 지원하는
RTCPeerConnectionAPI와 함께 작동합니다. 이렇게 하면 중간 서버가 없고 '홉'이 적어지므로 지연 시간이 단축될 수 있습니다. RTCDataChannel는 스트림 제어 전송 프로토콜(SCTP)을 사용하여 구성 가능한 전송 시맨틱(순서가 지정되지 않은 전송 및 재전송 구성)을 허용합니다.
RTCDataChannel는 현재 Google Chrome, Opera, Firefox의 데스크톱 및 Android에서 SCTP 지원과 함께 사용할 수 있습니다.
주의사항: 시그널링, STUN, TURN
WebRTC는 P2P 통신을 지원하지만 피어 연결을 부트스트랩하기 위해 미디어 및 네트워크 메타데이터를 교환하는 신호를 위해서는 서버가 필요합니다.
WebRTC는 다음을 사용하여 NAT 및 방화벽에 대처합니다.
- ICE 프레임워크를 사용하여 피어 간에 최적의 네트워크 경로를 설정합니다.
- STUN 서버를 사용하여 각 피어의 공개적으로 액세스 가능한 IP와 포트를 확인합니다.
- 직접 연결이 실패하고 데이터 중계가 필요한 경우 TURN 서버
신호 및 네트워킹을 위해 WebRTC가 서버와 작동하는 방식에 관한 자세한 내용은 실제 WebRTC: STUN, TURN, 신호를 참고하세요.
기능
RTCDataChannel API는 유연한 데이터 유형 세트를 지원합니다. 이 API는 WebSocket을 정확하게 모방하도록 설계되었으며 RTCDataChannel는 문자열뿐만 아니라 JavaScript의 일부 바이너리 유형(예: Blob, ArrayBuffer, ArrayBufferView)도 지원합니다. 이러한 유형은 파일 전송 및 멀티플레이어 게임을 사용할 때 유용할 수 있습니다.
RTCDataChannel은 신뢰할 수 없고 순서가 지정되지 않은 모드 (사용자 데이터그램 프로토콜 또는 UDP와 유사), 신뢰할 수 있고 순서가 지정된 모드 (전송 제어 프로토콜 또는 TCP와 유사), 부분적으로 신뢰할 수 있는 모드에서 작동할 수 있습니다.
- 신뢰할 수 있는 순서 지정 모드는 메시지 전송과 메시지 전송 순서를 보장합니다. 이 경우 오버헤드가 추가되어 이 모드가 느려질 수 있습니다.
- 신뢰할 수 없고 순서가 지정되지 않은 모드는 모든 메시지가 상대방에게 전송되는지 또는 어떤 순서로 전송되는지 보장하지 않습니다. 이렇게 하면 오버헤드가 제거되어 이 모드가 훨씬 더 빠르게 작동할 수 있습니다.
- 부분 신뢰 모드는 재전송 제한 시간 또는 최대 재전송 횟수와 같은 특정 조건에서 메시지 전송을 보장합니다. 메시지 순서도 구성할 수 있습니다.
패킷 손실이 없는 경우 처음 두 모드의 성능은 거의 동일합니다. 하지만 안정적이고 순서가 지정된 모드에서는 손실된 패킷으로 인해 다른 패킷이 그 뒤에서 차단되고 손실된 패킷이 재전송되어 도착할 때쯤이면 오래되었을 수 있습니다. 물론 동일한 앱 내에서 여러 데이터 채널을 사용할 수 있으며 각 채널에는 자체의 신뢰할 수 있는 또는 신뢰할 수 없는 시맨틱이 있습니다.
Ilya Grigorik의 High Performance Browser Networking에 유용한 표가 있습니다.
| TCP | UDP | SCTP | |
| 안정성 | 안정성 | 신뢰할 수 없음 | 구성 가능 |
| 배달 | Ordered | 순서가 지정되지 않음 | 구성 가능 |
| 변속기 | 바이트 중심 | 메시지 중심 | 메시지 중심 |
| 흐름 관리 | 예 | 아니요 | 예 |
| 혼잡 제어 | 예 | 아니요 | 예 |
다음으로, 안정적이고 순서가 지정된 모드 또는 불안정하고 순서가 지정되지 않은 모드를 사용하도록 RTCDataChannel를 구성하는 방법을 알아봅니다.
데이터 채널 구성
온라인에서 RTCDataChannel의 간단한 데모를 몇 가지 확인할 수 있습니다.
이 예에서 브라우저는 자체적으로 피어 연결을 만든 다음 데이터 채널을 만들고 피어 연결을 통해 메시지를 전송합니다. 그런 다음 데이터 채널을 만들고 피어 연결을 따라 메시지를 전송합니다. 마지막으로 페이지의 다른 쪽에 있는 상자에 메시지가 표시됩니다.
이 기능을 시작하는 코드는 짧습니다.
const peerConnection = new RTCPeerConnection();
// Establish your peer connection using your signaling channel here
const dataChannel =
peerConnection.createDataChannel("myLabel", dataChannelOptions);
dataChannel.onerror = (error) => {
console.log("Data Channel Error:", error);
};
dataChannel.onmessage = (event) => {
console.log("Got Data Channel Message:", event.data);
};
dataChannel.onopen = () => {
dataChannel.send("Hello World!");
};
dataChannel.onclose = () => {
console.log("The Data Channel is Closed");
};
dataChannel 객체는 이미 설정된 피어 연결에서 생성됩니다. 시그널링이 발생하기 전이나 후에 만들 수 있습니다. 그런 다음 이 채널을 다른 채널과 구분하는 라벨과 선택적 구성 설정 집합을 전달합니다.
const dataChannelOptions = {
ordered: false, // do not guarantee order
maxPacketLifeTime: 3000, // in milliseconds
};
maxRetransmits 옵션 (실패하기 전에 시도할 횟수)을 추가할 수도 있지만 maxRetransmits 또는 maxPacketLifeTime만 지정할 수 있으며 둘 다 지정할 수는 없습니다. UDP 시맨틱의 경우 maxRetransmits를 0로, ordered를 false로 설정합니다. 자세한 내용은 스트림 제어 전송 프로토콜 및 스트림 제어 전송 프로토콜 부분 신뢰성 확장에 관한 IETF RFC를 참고하세요.
ordered: 데이터 채널에서 순서를 보장해야 하는지 여부입니다.maxPacketLifeTime: 실패한 메시지를 재전송하려고 시도하는 최대 시간maxRetransmits: 실패한 메시지를 다시 전송하려고 시도하는 최대 횟수입니다.protocol: 앱에 대한 메타 정보를 제공하는 하위 프로토콜을 사용할 수 있습니다.negotiated: true로 설정하면 다른 피어에서 데이터 채널의 자동 설정이 삭제되어 다른 쪽에서 동일한 ID로 데이터 채널을 만드는 자체 방법을 제공합니다.id:negotiated이true로 설정된 경우에만 사용할 수 있는 채널의 자체 ID를 제공할 수 있습니다.
대부분의 사용자가 사용해야 하는 옵션은 ordered, maxPacketLifeTime, maxRetransmits의 처음 세 가지뿐입니다. SCTP (현재 WebRTC를 지원하는 모든 브라우저에서 사용)를 사용하면 안정적이고 순서가 지정된 것이 기본적으로 true입니다. 앱 레이어에서 완전히 제어하려면 신뢰할 수 없고 순서가 지정되지 않은 것을 사용하는 것이 좋지만 대부분의 경우 부분적 신뢰성이 유용합니다.
WebSocket과 마찬가지로 RTCDataChannel는 연결이 설정되거나 닫히거나 오류가 발생할 때, 다른 피어로부터 메시지를 수신할 때 이벤트를 발생시킵니다.
안전할까?
암호화는 모든 WebRTC 구성요소에 필수입니다. RTCDataChannel를 사용하면 모든 데이터가 데이터그램 전송 계층 보안 (DTLS)으로 보호됩니다. DTLS는 SSL의 파생 상품이므로 표준 SSL 기반 연결을 사용하는 것만큼 데이터가 안전합니다. DTLS는 표준화되어 있으며 WebRTC를 지원하는 모든 브라우저에 내장되어 있습니다. 자세한 내용은 Wireshark 위키를 참고하세요.
데이터에 대한 생각 바꾸기
JavaScript에서 대량의 데이터를 처리하는 것은 어려운 일일 수 있습니다. Sharefest 개발자가 지적한 것처럼 이렇게 하려면 데이터를 새로운 방식으로 생각해야 했습니다. 사용 가능한 메모리보다 큰 파일을 전송하는 경우 이 정보를 저장할 새로운 방법을 생각해 봐야 합니다. 다음과 같이 FileSystem API와 같은 기술이 사용됩니다.
파일 공유 앱 빌드
이제 RTCDataChannel를 사용하여 브라우저에서 파일을 공유할 수 있는 웹 앱을 만들 수 있습니다. RTCDataChannel를 기반으로 빌드하면 전송된 파일 데이터가 암호화되고 앱 제공업체의 서버에 영향을 주지 않습니다. 이 기능은 더 빠른 공유를 위해 여러 클라이언트에 연결할 수 있는 가능성과 결합되어 WebRTC 파일 공유를 웹의 강력한 후보로 만듭니다.
성공적으로 전송하려면 다음 단계를 따라야 합니다.
- File API를 사용하여 JavaScript에서 파일을 읽습니다.
RTCPeerConnection를 사용하여 클라이언트 간에 피어 연결을 만듭니다.RTCDataChannel를 사용하여 클라이언트 간에 데이터 채널을 만듭니다.
RTCDataChannel를 통해 파일을 전송할 때는 몇 가지 사항을 고려해야 합니다.
- 파일 크기: 파일 크기가 적당히 작고 하나의 Blob으로 저장하고 로드할 수 있는 경우 File API를 사용하여 메모리에 로드한 다음 안정적인 채널을 통해 파일을 그대로 전송할 수 있습니다 (단, 브라우저에서 최대 전송 크기에 제한을 적용함). 파일 크기가 커지면 문제가 더 복잡해집니다. 청크 메커니즘이 필요한 경우 파일 청크가 로드되어 다른 피어에게 전송되며, 피어가 이를 인식할 수 있도록
chunkID메타데이터가 함께 전송됩니다. 이 경우 먼저 청크를 오프라인 저장소에 저장하고 (예: FileSystem API 사용) 파일이 완전히 준비된 경우에만 사용자의 디스크에 저장해야 합니다. - 청크 크기: 앱의 가장 작은 데이터 '원자'입니다. 현재 전송 크기 제한이 있으므로 청크가 필요합니다 (향후 버전의 데이터 채널에서 수정될 예정). 현재 권장되는 최대 청크 크기는 64KiB입니다.
파일이 완전히 전송되면 앵커 태그를 사용하여 다운로드할 수 있습니다.
function saveFile(blob) {
const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = 'File Name';
link.click();
};
PubShare 및 GitHub의 이러한 파일 공유 앱은 이 기법을 사용합니다. 둘 다 오픈소스이며 RTCDataChannel 기반 파일 공유 앱을 위한 좋은 기반을 제공합니다.
그렇다면 어떻게 해야 할까요?
RTCDataChannel는 파일 공유, 멀티플레이어 게임, 콘텐츠 전송을 위한 앱을 빌드하는 새로운 방법을 제공합니다.
- 앞서 설명한 P2P 파일 공유
- Mozilla의 BananaBread에서 볼 수 있듯이 WebGL과 같은 다른 기술과 결합된 멀티플레이어 게임
- 피어 투 피어 데이터 통신을 통해 웹 애셋을 제공하는 프레임워크인 PeerCDN에 의해 재창조된 콘텐츠 전송
앱 빌드 방식 변경
이제 RTCDataChannel를 통해 고성능의 짧은 지연 시간 연결을 사용하여 더 몰입도 높은 앱을 제공할 수 있습니다. PeerJS 및 PubNub WebRTC SDK와 같은 프레임워크를 사용하면 RTCDataChannel를 더 쉽게 구현할 수 있으며 이제 API가 여러 플랫폼에서 널리 지원됩니다.
RTCDataChannel의 등장으로 브라우저에서 데이터 전송에 대해 생각하는 방식이 달라질 수 있습니다.