안녕하세요! 2채널 호환 게시판 시스템 「つゔぁいちゃんねる(2ch.biz)」 개발 기록, 제33회입니다.
지난번(제32회)에는 방주가 잠들어도 안심할 수 있는 「호스트 나스리츠케(관리 권한 이양) 기능」을 구현했습니다.
커뮤니티의 분위기가 좋아질수록 다음으로 활성화된 것이 **「이미지나 스크린샷, 문서, zip 아카이브 등의 파일 공유」**였습니다.
하지만 초기 프로토타입에서 파일을 송수신할 수 있게 되자마자 현장에서 비명이 터져 나왔습니다.
'10명이 있는 방에서 누군가 100MB짜리 동영상 파일을 던진 순간, 전송자의 PC가 멈추고, 수신자 전원의 스마트폰 기가(통신량)가 순식간에 바닥났어!'
'관심 없는 무거운 zip 파일을 멋대로 보내서 브라우저 탭이 충돌했어!'
본고에서는 이러한 WebRTC 풀메시(full mesh) P2P 특유의 「대역폭 폭발 문제」를 해결하기 위해 진행한, 푸시형에서 「온디맨드 풀형(수동 승인)」으로의 대전환에 대해 설명합니다!
채팅 앱에서 파일 전송이라고 하면, 전송자가 파일을 드래그 앤 드롭하면 수신자의 화면에 이미지가 '뿅'하고 나타나는 것이 일반적입니다.
하지만 중앙 서버가 없고 모든 참여자가 직접 메시(mesh) 형태로 연결된 P2P 환경에서, 기존의 「모두에게 강제 전송(Push형)」을 수행할 경우, 다음과 같은 대역폭 및 메모리의 이중 지옥이 발생합니다.
- 전송자의 업로드 회선 마비: 방에 10명의 참여자가 있을 경우, 100MB 파일을 보내려면 전송자는
100MB × 9명 = 900MB의 업로드를 수행해야 하므로, 가정용 회선에서는 확실히 버퍼가 막혀 프리징합니다.
- 수신자의 불필요한 패킷/메모리 낭비: 스마트폰(4G/5G)으로 참여하는 사람에게는 보고 싶지도 않은 거대한 파일을 멋대로 다운로드하게 하는 것은 '기가 강탈'에 다름 아닙니다.
이 문제를 근본적으로 해결하기 위해, 우리는 파일 전송 프로토콜을 완전히 **「풀형(필요한 사람만 다운로드하는 방식)」**으로 재구축했습니다.
- 실제 데이터는 요청될 때까지 1바이트도 흐르지 않음: 최초 공유 시에는 파일명・크기・MIME・고유한 FileId 등의 메타데이터만을 암호화 패킷(
file_offer) 형태로 통지합니다.
- 1대1 다이렉트 스트리밍: 「다운로드」 버튼을 누른 상대와만 1대1로 DataChannel을 사용하며, 16KB 단위의 청크(chunk)로 분할하여 전송합니다.
- 무관심한 참여자에게 미치는 영향은 제로: 다운로드 버튼을 누르지 않은 참여자에게는 바이너리 데이터가 전혀 흐르지 않기 때문에, 스마트폰 통신량이나 브라우저 메모리가 전혀 소모되지 않습니다.
대용량 파일을 WebRTC DataChannel로 고속 전송할 때, 단순한 for 루프로 dataChannel.send(chunk)를 반복하면, 브라우저 내부의 전송 버퍼(bufferedAmount)가 순식간에 넘쳐흘러 패킷 손실이나 브라우저 충돌을 일으킵니다.
이를 방지하기 위해, Backpressure(백프레셔/역압) 제어를 엄격하게 결합했습니다.
/**
* 전송 버퍼의 막힘을 감지하고 안전하게 청크를 보내는 스트리밍 송신기
*/
...
채팅 로그에 표시되는 파일 공유 화면도 사용 편의성을 극대화했습니다.
채팅 로그 내에, 파일명, 파일 크기(KB/MB 표기), P2P 전송 배지, 그리고 눈에 띄는 파란색 「📥 다운로드 (P2P)」 버튼을 배치합니다.
다운로드 버튼을 누르면, 버튼 자체가 프로그레스 바로 부드럽게 변형되며 실시간으로 **「⏳ 45% 수신 중 (12.4MB / 27.5MB)」**와 같은 진행 상황을 표시합니다.
모든 청크가 모이는 순간, 브라우저 표준 다운로드 다이얼로그가 발동되어 파일이 디스크에 저장됩니다. 카드 버튼은 「💾 저장 (85MB)」 링크로 전환되어 언제든지 재저장이 가능합니다.
여러 단말을 연결한 테스트 환경에서 50MB 아카이브 파일을 공유했을 때의 네트워크 부하를 측정했습니다.
| 항목 | 기존의 Push 방식 (전원 강제 전송) | 이번 Pull 방식 (온디맨드) | 개선 효과 |
|---|
| 참가자 수 | 5명 (송신자 1, 다운로드 희망자 1, 미희망자 3) | 5명 (좌측과 동일) | - |
| 송신자의 총 전송량 | 200 MB (50MB × 4명) | 50.01 MB (메타데이터 + 1인분) | 75% 감소 |
| 미희망자의 수신량 | 50 MB (전원 강제 수신) | 1.2 KB (메타데이터 통지만) | 99.99% 감소! |
| 브라우저 안정성 | 전송 중 일시적 프리즈 발생 | 전원 끊김 없이 매우 쾌적함 | 극적인 개선 |
다운로드를 원하는 1명에게만 확실하게 데이터가 전달되며, 다른 참가자의 회선과 단말기 리소스는 완전히 무사히 보호되는 것이 입증되었습니다.
WebRTC에서의 파일 공유 최대 난관이었던 '대역폭 폭발 문제'를 온디맨드 Pull 방식 프로토콜과 Backpressure 제어를 통해 극복했습니다.
하지만, 파일 전송이 누구나 손쉽게 가능해지면서 다음으로 직면한 것은 '보안 및 가용성의 벽' 이었습니다.
-
변조/바이러스 혼입 위협: 악의적인 사용자가 '편리한 도구야'라며 내용물을 바이러스나 트로이 목마로 바꿔서 전송해 온다면 어떻게 방어할 수 있을까?
-
송신자가 접속 끊길 경우 다운로드 불가 문제: 거대한 파일을 다운로드하는 도중에 원래 송신자(Alice)가 브라우저를 닫아버리면, 다운로드는 영원히 실패하게 되는 걸까?
이 두 가지 난제를 동시에 해결한 것이 BitTorrent의 사상을 도입한 'SHA-256 해시 검증' 과 '시더 분산 재배포' 입니다.
실제 서비스: https://2ch.biz/