WebSocket temps réel avec Claude Code
Découvrez webSocket temps réel avec Claude Code. Conseils pratiques et exemples de code inclus.
リアルタイム通信開発でClaude Codeを活用する
チャット、通知、共同Editなど、リアルタイム通信が必要なアプリケーションは増えています。Claude Codeはサーバーサイドとクライアントサイドの両方を理解した上で、一貫した実装を支援します。
Socket.IOによるチャット機能の実装
> Socket.IOを使ったリアルタイムチャットのサーバーを作成して。
> ルーム機能、タイピングインジケーター、既読機能を実装して。
サーバーサイド
import express from 'express';
import { createServer } from 'http';
import { Server, Socket } from 'socket.io';
const app = express();
const server = createServer(app);
const io = new Server(server, {
cors: { origin: 'http://localhost:5173' },
});
interface ChatMessage {
id: string;
roomId: string;
userId: string;
content: string;
timestamp: Date;
}
const rooms = new Map<string, Set<string>>();
io.on('connection', (socket: Socket) => {
const userId = socket.handshake.auth.userId;
console.log(`User connected: ${userId}`);
socket.on('join-room', (roomId: string) => {
socket.join(roomId);
if (!rooms.has(roomId)) rooms.set(roomId, new Set());
rooms.get(roomId)!.add(userId);
socket.to(roomId).emit('user-joined', {
userId,
members: Array.from(rooms.get(roomId)!),
});
});
socket.on('send-message', async (data: { roomId: string; content: string }) => {
const message: ChatMessage = {
id: crypto.randomUUID(),
roomId: data.roomId,
userId,
content: data.content,
timestamp: new Date(),
};
// Save to DB
await saveMessage(message);
io.to(data.roomId).emit('new-message', message);
});
socket.on('typing-start', (roomId: string) => {
socket.to(roomId).emit('user-typing', { userId, isTyping: true });
});
socket.on('typing-stop', (roomId: string) => {
socket.to(roomId).emit('user-typing', { userId, isTyping: false });
});
socket.on('mark-read', (data: { roomId: string; messageId: string }) => {
socket.to(data.roomId).emit('message-read', {
userId,
messageId: data.messageId,
});
});
socket.on('disconnect', () => {
rooms.forEach((members, roomId) => {
if (members.delete(userId)) {
io.to(roomId).emit('user-left', { userId });
}
});
});
});
server.listen(3000, () => console.log('Server running on port 3000'));
クライアントサイド(React)
import { useEffect, useState, useCallback } from 'react';
import { io, Socket } from 'socket.io-client';
let socket: Socket;
export function useChat(roomId: string, userId: string) {
const [messages, setMessages] = useState<ChatMessage[]>([]);
const [typingUsers, setTypingUsers] = useState<Set<string>>(new Set());
useEffect(() => {
socket = io('http://localhost:3000', { auth: { userId } });
socket.emit('join-room', roomId);
socket.on('new-message', (message: ChatMessage) => {
setMessages(prev => [...prev, message]);
});
socket.on('user-typing', ({ userId: uid, isTyping }) => {
setTypingUsers(prev => {
const next = new Set(prev);
isTyping ? next.add(uid) : next.delete(uid);
return next;
});
});
return () => { socket.disconnect(); };
}, [roomId, userId]);
const sendMessage = useCallback((content: string) => {
socket.emit('send-message', { roomId, content });
}, [roomId]);
const startTyping = useCallback(() => {
socket.emit('typing-start', roomId);
}, [roomId]);
const stopTyping = useCallback(() => {
socket.emit('typing-stop', roomId);
}, [roomId]);
return { messages, typingUsers, sendMessage, startTyping, stopTyping };
}
Server-Sent Events(SSE)による通知
WebSocketほどの双方向性が不要な場合、SSEが軽量な選択肢です。
// server
app.get('/api/notifications/stream', (req, res) => {
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
Connection: 'keep-alive',
});
const userId = req.query.userId as string;
const sendEvent = (data: object) => {
res.write(`data: ${JSON.stringify(data)}\n\n`);
};
// 新しい通知があれば送信
const unsubscribe = notificationBus.subscribe(userId, sendEvent);
req.on('close', () => {
unsubscribe();
res.end();
});
});
// client
function useNotifications(userId: string) {
const [notifications, setNotifications] = useState<Notification[]>([]);
useEffect(() => {
const eventSource = new EventSource(
`/api/notifications/stream?userId=${userId}`
);
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
setNotifications(prev => [data, ...prev]);
};
return () => eventSource.close();
}, [userId]);
return notifications;
}
接続の安定性を高める
本番環境では、再接続ロジックやハートビートの実装が重要です。
const socket = io('http://localhost:3000', {
auth: { userId },
reconnection: true,
reconnectionAttempts: 10,
reconnectionDelay: 1000,
reconnectionDelayMax: 5000,
timeout: 20000,
});
socket.on('connect_error', (err) => {
console.error('Connection error:', err.message);
});
socket.on('reconnect', (attempt) => {
console.log(`Reconnected after ${attempt} attempts`);
// Reconnect後にルームに再参加
socket.emit('join-room', currentRoomId);
});
Summary
Claude Codeを活用すれば、WebSocketやSSEを使ったリアルタイム通信機能をサーバー・クライアント両方一貫して実装できます。プロンプトの書き方次第でコードの質が大きく変わるため、プロンプトテクニックを身につけておくことが重要です。個人開発でチャット機能を実装する際は個人開発を爆速にする方法も参考にしてください。
詳しくはAnthropic公式ドキュメントやSocket.IO公式ドキュメントをご覧ください。
PDF gratuit : aide-mémoire Claude Code en 5 minutes
Laissez simplement votre e-mail et nous vous enverrons immédiatement l'aide-mémoire A4 en PDF.
Nous traitons vos données avec soin et n'envoyons jamais de spam.
À propos de l'auteur
Masa
Ingénieur passionné par Claude Code. Il gère claudecode-lab.com, un média tech en 10 langues avec plus de 2 000 pages.
Articles similaires
7 vérifications avant de publier chaque jour un article multilingue sur Claude Code
Une checklist pratique pour publier des articles multilingues sur Claude Code chaque jour sans oublier une langue, casser les CTA ou laisser l’ancien contenu en production.
Codex Automations : confier l'analyse, les articles et le deploiement a l'IA
Guide pratique pour utiliser Codex Automations dans une operation de contenu orientee monetisation.
Claude Code × GCP Cloud Functions Guide Complet | Développement Serverless Ultra-Rapide
Optimisez GCP Cloud Functions avec Claude Code. Implémentez des triggers HTTP/Pub/Sub/Firestore, des tests locaux et l'automatisation des déploiements avec des exemples de code réels de l'expérience de Masa.