How to Implement WebSocket/Real-Time Communication: Claude Code 활용 가이드
implement websocket/real-time communication: Claude Code 활용. 실용적인 코드 예시와 단계별 가이드를 포함합니다.
실시간通信개발で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);
});
정리
Claude Codeを활용すれば、WebSocketやSSE를 사용한실시간通信機能を서버・클라이언트両方一貫して구현할 수 있습니다。プロンプトの書き方次第でコードの質が大きく変わるため、プロンプトテクニックを身につけておくことが중요합니다。個人개발でチャット機能を구현する際は個人개발を爆速にする方法도 참고하세요.
자세한 내용은Anthropic공식 문서やSocket.IO공식 문서를 확인하세요.
무료 PDF: 5분 완성 Claude Code 치트시트
이메일 주소만 등록하시면 A4 한 장짜리 치트시트 PDF를 즉시 보내드립니다.
개인정보는 엄격하게 관리하며 스팸은 보내지 않습니다.
이 글을 작성한 사람
Masa
Claude Code를 적극 활용하는 엔지니어. 10개 언어, 2,000페이지 이상의 테크 미디어 claudecode-lab.com을 운영 중.
관련 글
Claude Code 다국어 글을 매일 발행하기 전에 확인할 7가지
누락된 언어, 깨진 CTA, 반영되지 않은 배포를 막기 위해 다국어 Claude Code 글을 매일 발행하기 전에 확인할 체크리스트입니다.
Codex Automations란? 잠자는 동안 AI가 콘텐츠 운영을 처리하게 하는 방법
Codex Automations로 트래픽 분석, 주제 선정, 글 작성, CTA 개선, 배포까지 자동화하는 실전 가이드.
Claude Code × GCP Cloud Functions 완전 가이드 | 서버리스 함수 초고속 개발
Claude Code로 GCP Cloud Functions를 효율화. HTTP/Pub/Sub/Firestore 트리거 구현부터 로컬 테스트·배포 자동화까지, Masa의 실무 경험을 토대로 실제 코드로 해설.