はじめに
はじめまして。東海大学 情報通信学部に所属している、3年生のMohamed Fuadです。
私は昔からのiPhoneユーザーなのですが、ずっと不満だったことがあります。AndroidとiPhoneの間で、AirDropのように手軽にファイルを送れないことです。最近はGoogleがQuick Share(旧Nearby Share)で近い体験を実現していますが、依然としてOSの壁は残っています。
そんな中、大学のモバイルアプリケーション開発の授業でチーム開発の課題が出ました。「これはチャンスだ」と思い、ブラウザだけで動くクロスプラットフォームなファイル転送アプリ「WebDropを提案・開発しました。
この記事では、その仕組みと、開発中に一番ハマった「Vercelにデプロイしたら数秒で接続が切れる問題」、そしてどう解決したかを書きます。
- ライブデモ: https://web-drop-lyart.vercel.app
- ポートフォリオ: https://mohamedfuad.com
- GitHub: https://github.com/MohamedFuad16
WebDropとは
WebDropは、インストール不要・ブラウザだけで動作する近接ファイル転送アプリです。
使い方はシンプルです。
- 送りたい相手と自分、両方のデバイスでWebDropを開く
- 「Connect」をタップして、デバイス同士を近づける(タッチする)
- 超音波によって近接が確認され、自動でペアリング完了
- あとはファイルを選ぶだけ。P2Pで直接転送される
AirDropの「近くのデバイスと繋がる」体験を、アプリのインストールなしで、iPhone・Android・PCの垣根なく再現することを目指しました。
開発の背景と制約
授業課題としての条件は次の通りでした。
- フロントエンドは HTML / CSS / JS のみ
- Monaca プラットフォーム上でビルドすること
- バックエンドは自由
チームリーダーとして、企画・設計・アーキテクチャの策定を担当し、ClaudeやCodexなどのAIコーディングツールを活用しながら実装を進めました。チームメンバーにはQAテストとフィードバックを担当してもらい、品質向上に貢献してもらいました。
全体アーキテクチャ
1. ペアリング : 超音波で近接デバイスを確認し、セッションを確立
2. シグナリング : WebSocketサーバー経由でWebRTCの接続情報(SDP/ICE)を交換
3. P2P転送 : RTCDataChannelでファイルを直接転送
なぜ超音波ペアリングなのか
AirDropはBLE(Bluetooth Low Energy)で周囲のデバイスを発見しますが、ブラウザからBLEで常時デバイス発見を行うのは制約が多く現実的ではありません。
そこでWebDropでは、スピーカーとマイクを使った超音波通信でペアリングを行っています。近接超音波帯(約18.6〜19.4kHz)の符号化チャープを送受信し、「物理的にデバイスを近づけないと聞こえない音」を使うことで、近くにいるデバイスとしか繋がらないというAirDrop的な体験を実現しています。
ポイントは、検出が「音量」ではなく相関ベースであることです。録音の中に「自分たちに割り当てられた特定の符号化スイープ」が背景ノイズより明確に含まれているかを判定するため、騒がしい環境でも誤検出しにくくなっています。また、複数のペアが同じ部屋で同時にペアリングすると音が衝突するため、サーバーが各デバイスに送信タイムスロットを事前割当する予約型TDMA方式を採用しています。この超音波まわりの仕組みは長くなるので、別記事で詳しく書く予定です。
セキュリティについて
ファイル本体はWebRTCのDataChannelで転送され、DTLSでエンドツーエンド暗号化されています。直接のP2P経路が確立できないネットワーク環境では、暗号化されたままCloudflare TURN経由で中継されますが、中継サーバーがファイルの中身を読むことはできません。
シグナリングサーバーはメタデータ(在席情報・SDP/ICEなど)のみを扱い、ファイルのバイトには一切触れない設計です。超音波による近接確認と組み合わせることで、意図しない相手への誤送信や傍受のリスクを抑えています。
一番ハマった話: Vercelにデプロイしたら数秒で接続が切れる
開発中、最も頭を抱えたのがこの問題です。
ローカルでは完璧に動いていたのに、Vercelにデプロイした途端、ペアリング後、数秒でデバイス間の接続が切断されるようになりました。
原因を調査した結果、たどり着いた答えは……Vercelがサーバーレスアーキテクチャだからでした。
WebRTCのシグナリングにはWebSocketで常時接続を維持するサーバーが必要です。しかしVercelのサーバーレス関数はリクエストごとに起動し、処理が終わると短時間で終了します。つまり、常駐が前提のWebSocketシグナリングサーバーとは根本的に相性が悪いのです。ローカル開発では普通のNodeプロセスとして動いていたため、この問題に気づけませんでした。
解決策: シグナリングサーバーをAzure VMへ移行
授業課題という期限の中で「動いているコードを書き換えない」ことを優先し、Azure VM(Japan East)を選びました。
シグナリングは小さなJSONメッセージしか扱わないため、最小クラスの安価なVMで十分です。nginxがTLSを終端し、Nodeプロセスはローカルループバック(127.0.0.1)にのみバインドすることで、外部から直接Nodeに触れられない構成にしています。
以前AWSでプロジェクトを構築した経験があったため、クラウドが変わっても「TLS終端・リバースプロキシ・プロセス常駐」といったやるべきことの勘所は共通しており、移行自体はスムーズでした。クラウドの基礎を一度きちんと押さえておくと、プラットフォームをまたいでも応用が利くというのは大きな学びでした。
現在はAzureへの移行により接続は安定しています。同時接続の上限は約50ペアで、これは単なる目安ではなく、ペアリングセレモニーの同時参加者100人を6人ずつのコホートに分割する設計(100 ÷ 6 ≒ 17コホート ≒ 50ペア)に基づいています。ただし、現在は単一ノードで動作しているため、同時接続時のペアリング処理には改善すべき課題が残っており、その修正を進めています。将来的には、Redisによる状態共有と複数ノード構成を導入し、より高いスケーラビリティと耐障害性を実現する予定です。
現在の状況と今後
現在、複数のデバイスが同時に接続を開始した場合にペアリングが失敗することがあるため、その問題の修正を進めています。一方で、1対1のペアリング(数秒間隔で接続する場合を含む)やQRコードを利用した接続は、PC・モバイル間ともに高速かつ安定して動作しています。今後はこの課題を解消したうえで、大学で本プロジェクトを発表する予定です。
ぜひスマホ2台、あるいはスマホとPCで下記リンクを開いて試してみてください。「Connect」を押してデバイスを近づけるだけです。
率直なフィードバックや「ここはこうした方がいい」という指摘を、コメント欄でいただけると嬉しいです。
おわりに
「ブラウザだけでどこまでネイティブの体験に近づけるか」というテーマは、WebRTC・Web Audio・クラウドインフラを横断的に学べる非常に良い題材でした。特に、ローカルと本番環境の違い(サーバーレスの制約)に実際にぶつかり、選択肢を比較して解決した経験は、教科書では得られないものだったと思います。
現在、クラウド・AI分野を中心にインターンシップを探しています。この記事やプロジェクトに興味を持っていただけた方は、ポートフォリオからお気軽にご連絡ください。
- ポートフォリオ: https://mohamedfuad.com
- GitHub: https://github.com/MohamedFuad16
- LinkedIn: https://www.linkedin.com/in/mohamed-fuad-6b8483278/











