はじめに: HTTP だけでは不十分な場合 友人同士のバートとアーニーは、一緒に夢のサイドプロジェクトに取り組んでいます。それは、リモートで働くチームでリアルタイムの会話を可能にするチャットアプリです。フロントエンドのプログラマーであるバートは、バックエンドの専門家である友人に新しい機能を紹介しながら、興奮を抑えきれません。「見て!メッセージを入力すると、サーバーに送信され、ほぼ瞬時に応答がポップアップ表示されます!」バックエンドの第一人者であるアーニーは顔をしかめます。「しかし、2人が同時に会話しようとすると、どうしたら問題を解決できるのでしょうか?アプリは会話を「見る」代わりにページを更新し続けるため、リアルタイムでチャットすることはできません。」 問題は、Bert のアプリが HTTP 上で動作し、クライアントがサーバーからフェッチを要求する必要があることです。Ernie は次のようにまとめています。「友達全員がテキスト メッセージで返信しているのに、突然、新しいメッセージがあるかどうかを確認するために更新するまで返信がまったく表示されなくなるようなものです。更新するまでは最後のメッセージは表示されず、HTTP はこのように動作します。」 ここからが最高の部分です。リアルタイムで動作するフルスタック アプリには、WebSocket があります。この部分は非常に興味深いので、Ernie と Bert と一緒に、WebSocket の機能、実装手順、重要性の理由などについて学びましょう。 WebSocket とは何か? 初心者向け解説 WebSocket は、クライアント (Web ブラウザ) とサーバー間の継続的な電話通話に似ています。これは、「メッセージを送信して、返信を待つ」という方法で機能する HTTP プロトコルとは異なります。WebSocket を使用すると、両者が自由に会話できます。WebSocket の機能は次のとおりです。 全二重: クライアントとサーバーの両方が同時にデータを送信できます。 低レイテンシ: ハンドシェイクが過度に繰り返されることはなく、データは自由に流れます。 軽量: メッセージが小さいため、帯域幅の使用量が減少します。 例: 絶えず更新されるスポーツのスコアボードを想像してください。HTTP では、クライアントは毎秒サーバーに「スコアは変わりましたか?」とスパム送信し続けなければなりません。WebSocket では、サーバーはスコアが変わるとすぐに「ゴール!」とアナウンスします。 WebSocket と HTTP: 何が新しいのか? バートは腰を下ろして頭を掻きます。「でも、HTTP はほとんどのアプリケーションで問題なく動作します。なぜゴールポストを動かすのですか?」アーニーは静かに笑い、マーカーを取り、ホワイトボードに何かを書き始めます。 「まずは最初から始めましょう」と彼は言います。「たとえば、スポーツのライブスコアなどのリアルタイムの最新情報です。クライアントはサーバーに毎秒『何か知りたいことはありますか?』と尋ねる必要があります。これはポーリングなので、30 秒ごとに『会議中ですか?』と尋ねる必要があります。馬鹿げているとは思いませんか? また、帯域幅も大量に消費します。」 WebSocket はこれを逆転させます: リアルタイム更新: サーバー上のデータは変更されるとすぐに送信されるため、ポーリングは必要ありません。 チャット アプリケーション: ページを更新する必要はありません。入力するとすぐにメッセージが届きます。 マルチプレイヤー ビデオ ゲーム: 動きがカクカクすることはありません。アクションは画面にシームレスに表示されます。 「HTTP は、ブログや製品ページなどの静的なものを扱うのにかなり適しています。ただし、ライブ インタラクションの場合は、永続的な接続が必要です。WebSocket です。」 リアルタイムチャットアプリの作成: 楽しいことが始まる アーニーは眼鏡を拭きながら、「それでは、簡単なチャット アプリケーションを作ってみましょう」と声を張り上げます。「バックエンドには Node.js サーバー、フロントエンドには React アプリを用意します。準備はいいですか?」 1. Socket.IOバックエンドを作成する 「Socket.IO の部分で必要になるので、Node.js サーバーを入手してください」と Ernie は急いで次のように入力します。 npm init -y npm install express socket.io サーバーコード (server.js): const express = require('express'); const http = require('http'); const { Server } = require('socket.io'); const app = express(); const server = http.createServer(app); const io = new Server(server); // Serve static files (like React's build folder) app.use(express.static('public')); // Handle WebSocket connections io.on('connection', (socket) => { console.log('New user connected:', socket.id); // Listen for Incoming messages from the socket socket.on('sendMessage', (message) => { console.log('Received:', message); // Broadcast the message to everyone io.emit('receiveMessage', message); }); // Handle user disconnects events socket.on('disconnect', () => { console.log('User left:', socket.id); }); }); server.listen(3000, () => { console.log('Visit http://localhost:3000 on a browser, Server started successful on port 3000'); }); 「Socket.IO の WebSocket 接続処理のおかげで、クライアントとサーバーは相互に通信できます。クライアントが (sendMessage) 関数を呼び出すと、サーバーは (io.emit) を介して接続している全員にメッセージを送信します。とても簡単ですよね。」 2. Reactを使用したフロントエンド 「今度は私の番です。React クライアントに取り掛かりましょう」と Bert は言います。 npx create-react-app chat-client cd chat-client npm install socket.io-client チャットコンポーネント (Chat.js): import { useState, useEffect } from 'react'; import io from 'socket.io-client'; // Connect to the server const socket = io('http://localhost:3000'); function Chat() { const [message, setMessage] = useState(''); const [messages, setMessages] = useState([]); useEffect(() => { // Listen for new messages socket.on('receiveMessage', (newMessage) => { setMessages([...messages, newMessage]); }); }, [messages]); const sendMessage = () => { if (message.trim()) { socket.emit('sendMessage', message); setMessage(''); } }; return ( <div style={{ padding: '20px' }}> <div> {messages.map((msg, index) => ( <p key={index}>{msg}</p> ))} </div> <input value={message} onChange={(e) => setMessage(e.target.value)} onKeyPress={(e) => e.key === 'Enter' && sendMessage()} /> <button onClick={sendMessage}>Send</button> </div> ); } export default Chat; 仕組み: メッセージは、WebSocket を介してサーバーから接続されたすべてのクライアントに送信されます。 React アプリケーションは、ページを再読み込みせずに UI を更新できるシングルページ アプリケーションです。 テストする: サーバーを起動するには、コンソールに node server.js と入力します。 React アプリケーションを起動するには、コンソールに npm start と入力します。 ブラウザで 2 つのタブを開き、一方のタブにメッセージを入力すると、ほぼ瞬時にもう一方のタブに同じメッセージが表示されることがわかります。 実際の使用例 これは Bert がアプリケーションに基づいて構築しようとしたものですが、Ernie は「実際のアプリケーションのほとんどは、多少のエラー処理と開発フレームワークを拡張する方法が必要です」と述べています。考えられる問題をいくつか見てみましょう。 1. 接続ラインが停止する React クライアントに再接続戦略を実装します。 socket.on('disconnect', () => { console.log('Disconnected. Trying to reconnect...'); socket.connect(); // Auto-reconnect }); 2. ユーザーID 認証された JWT トークンを使用して WebSocket を保護します。 // On login, send a token socket.emit('authenticate', { token: 'USER_JWT' }); // Server verifies token socket.on('authenticate', ({ token }) => { if (isValidToken(token)) { socket.authenticated = true; } else { socket.disconnect(); } }); 3. Redis によるスケーリング Redis を使用して、異なるサーバー間でのメッセージングの受け渡しを導入します。 npm install redis サーバーコード: const redis = require('redis'); const subscriber = redis.createClient(); subscriber.subscribe('chat-channel'); subscriber.on('message', (channel, message) => { io.emit('receiveMessage', message); }); チャットを超えて: 共有ドキュメントの編集 これは Bert の次のアイデアです。Google Docs に似たエディターです。Ernie は、「Web ソケットを使用して、さまざまな人が行った変更を監視し、それらをマージすることができます」と述べています。 例えば : ユーザーAは次のように入力します: 「こんにちは」 ユーザーBは「o」を削除し、「, World」を追加します。 サーバーは各キーストロークをリッスンし、それをすべてのクライアントにブロードキャストして、それぞれのクライアントが UPDATED ドキュメントをレンダリングできるようにします。 コードスニペット: // Client sends keystrokes textarea.addEventListener('input', (e) => { socket.emit('textChange', e.target.value); }); // Server broadcasts changes socket.on('textChange', (text) => { io.emit('updateText', text); }); セキュリティ問題 Ernie は次のように警告しています。「HTTPS/WSS なしで WebSocket を絶対に使用しないでください。」 WSS (WebSocket Secure) を使用する: const io = new Server(server, { cors: { origin: "https://yourdomain.com" }, }); XSS 攻撃につながる可能性のあるデータをサニタイズするために、すべての入力を検証します。 スパム行為を行うユーザーに対してレート制限を実装します。 よくある質問 Q: WebSocket の速度は HTTP よりもはるかに優れていますか? A: はい。瞬時のアプリケーションの場合、ポーリングを実行する必要がないため、WebSocket が最適です。 Q: REST API を WebSocket と一緒に利用することは可能ですか? A: はい、もちろんです! ライブ更新には WebSocket を使用し、CRUD 操作を実行するには REST を使用します。 Q: サーバーがクラッシュした場合はどう対処すればよいですか? A: クライアントは自動的に再接続できます (上記の再接続ロジックを参照)。 最後の言葉 Bert のチャット アプリは、リアルタイムの魅力で ping を鳴らすようになり、Ernie は満足そうに微笑んでいます。WebSocket はチャットだけでなく、ライブ ダッシュボード、ゲーム、IoT などの目的にも役立ちます。 あなたの番: さあ、例を試して、破壊して、何か新しいものを作ってみましょう。あなたのリアルタイム アプリが待っています!