Socket.IO 완벽 가이드 | 실시간 통신·WebSocket·Room·Broadcasting·실전 활용
이 글의 핵심
Socket.IO로 실시간 통신을 구현하는 완벽 가이드. WebSocket, Room, Broadcasting, Namespace, 인증까지 실전 예제로 정리. Socket.IO·WebSocket·Realtime 중심으로 설명합니다.
이 글의 핵심
Socket.IO로 실시간 통신을 구현하는 완벽 가이드입니다. WebSocket, Room, Broadcasting, Namespace, 인증까지 실전 예제로 정리했습니다.
실무 경험 공유: 폴링 방식을 Socket.IO로 전환하면서, 서버 부하가 80% 감소하고 실시간성이 크게 향상된 경험을 공유합니다.
들어가며: “실시간 통신이 필요해요”
실무에서 마주치는 문제들
폴링이 비효율적이에요
반복 요청은 서버 부하가 높습니다. Socket.IO는 실시간 연결을 제공합니다. WebSocket이 복잡해요
Native WebSocket은 어렵습니다. Socket.IO는 간단합니다. Room 관리가 필요해요
직접 구현이 어렵습니다. Socket.IO는 Room을 기본 제공합니다.
1. Socket.IO란?
핵심 특징
Socket.IO는 실시간 양방향 통신 라이브러리입니다. 주요 장점
- 자동 재연결: 연결 끊김 처리
- Room: 그룹 통신
- Broadcasting: 다중 전송
- Fallback: WebSocket 불가 시 폴링
- 간단한 API: 직관적인 문법
2. 설치 및 기본 사용
설치
npm install socket.io socket.io-client
서버
// server.ts
import { createServer } from 'http';
import { Server } from 'socket.io';
const httpServer = createServer();
const io = new Server(httpServer, {
cors: {
origin: 'http://localhost:3000',
},
});
io.on('connection', (socket) => {
console.log('User connected:', socket.id);
socket.on('message', (data) => {
console.log('Message:', data);
socket.emit('message', `Echo: ${data}`);
});
socket.on('disconnect', () => {
console.log('User disconnected:', socket.id);
});
});
httpServer.listen(3001, () => {
console.log('Socket.IO server running on :3001');
});
클라이언트
// client.ts
// 필요한 모듈 import
import { io } from 'socket.io-client';
const socket = io('http://localhost:3001');
socket.on('connect', () => {
console.log('Connected:', socket.id);
});
socket.emit('message', 'Hello Server!');
socket.on('message', (data) => {
console.log('Received:', data);
});
socket.on('disconnect', () => {
console.log('Disconnected');
});
3. Room
서버
io.on('connection', (socket) => {
// Room 참가
socket.on('join-room', (roomId) => {
socket.join(roomId);
console.log(`${socket.id} joined room ${roomId}`);
// Room에 메시지 전송
io.to(roomId).emit('user-joined', socket.id);
});
// Room에 메시지 전송
socket.on('room-message', ({ roomId, message }) => {
io.to(roomId).emit('message', {
userId: socket.id,
message,
});
});
// Room 나가기
socket.on('leave-room', (roomId) => {
socket.leave(roomId);
io.to(roomId).emit('user-left', socket.id);
});
});
4. Broadcasting
TypeScript/JavaScript 예제 코드입니다.
// 모든 클라이언트에게
io.emit('broadcast', 'Hello everyone!');
// 자신 제외 모든 클라이언트에게
socket.broadcast.emit('broadcast', 'Hello others!');
// 특정 Room에게
io.to('room1').emit('message', 'Hello room1!');
// 여러 Room에게
io.to('room1').to('room2').emit('message', 'Hello!');
// 자신 제외 Room에게
socket.to('room1').emit('message', 'Hello room1!');
5. Namespace
TypeScript/JavaScript 예제 코드입니다.
// 서버
const chatNamespace = io.of('/chat');
const adminNamespace = io.of('/admin');
chatNamespace.on('connection', (socket) => {
console.log('Chat connected:', socket.id);
});
adminNamespace.on('connection', (socket) => {
console.log('Admin connected:', socket.id);
});
// 클라이언트
const chatSocket = io('http://localhost:3001/chat');
const adminSocket = io('http://localhost:3001/admin');
6. 인증
서버
// 실행 예제
io.use((socket, next) => {
const token = socket.handshake.auth.token;
if (verifyToken(token)) {
next();
} else {
next(new Error('Authentication error'));
}
});
io.on('connection', (socket) => {
console.log('Authenticated user:', socket.id);
});
클라이언트
const socket = io('http://localhost:3001', {
auth: {
token: 'your-jwt-token',
},
});
socket.on('connect_error', (error) => {
console.error('Connection error:', error.message);
});
7. React 통합
// hooks/useSocket.ts
import { useEffect, useState } from 'react';
import { io, Socket } from 'socket.io-client';
export function useSocket() {
const [socket, setSocket] = useState<Socket | null>(null);
useEffect(() => {
const newSocket = io('http://localhost:3001');
setSocket(newSocket);
return () => {
newSocket.close();
};
}, []);
return socket;
}
// components/Chat.tsx
export default function Chat() {
const socket = useSocket();
const [messages, setMessages] = useState<string[]>([]);
const [input, setInput] = useState(');
useEffect(() => {
if (!socket) return;
socket.on('message', (message) => {
setMessages((prev) => [...prev, message]);
});
return () => {
socket.off('message');
};
}, [socket]);
const sendMessage = () => {
socket?.emit('message', input);
setInput(');
};
return (
<div>
<div>
{messages.map((msg, i) => (
<div key={i}>{msg}</div>
))}
</div>
<input value={input} onChange={(e) => setInput(e.target.value)} />
<button onClick={sendMessage}>Send</button>
</div>
);
}
8. Redis Adapter (확장성)
import { createAdapter } from '@socket.io/redis-adapter';
import { createClient } from 'redis';
const pubClient = createClient({ url: 'redis://localhost:6379' });
const subClient = pubClient.duplicate();
await Promise.all([pubClient.connect(), subClient.connect()]);
io.adapter(createAdapter(pubClient, subClient));
정리 및 체크리스트
핵심 요약
- Socket.IO: 실시간 양방향 통신
- Room: 그룹 통신
- Broadcasting: 다중 전송
- Namespace: 논리적 분리
- 인증: 토큰 기반
- Redis Adapter: 확장성
구현 체크리스트
- Socket.IO 설치
- 서버 구현
- 클라이언트 구현
- Room 구현
- Broadcasting 구현
- 인증 구현
- React 통합
같이 보면 좋은 글
이 글에서 다루는 키워드
Socket.IO, WebSocket, Realtime, Chat, Node.js, Backend, Communication
자주 묻는 질문 (FAQ)
Q. WebSocket과 비교하면 어떤가요?
A. Socket.IO가 더 많은 기능을 제공하고 사용이 편리합니다. WebSocket은 표준이고 가볍습니다.
Q. 확장성은 어떤가요?
A. Redis Adapter를 사용하면 여러 서버에서 확장 가능합니다.
Q. 모바일 앱에서도 사용할 수 있나요?
A. 네, React Native, Flutter 등에서 사용할 수 있습니다.
Q. 프로덕션에서 사용해도 되나요?
A. 네, Slack, Trello 등 많은 서비스에서 사용합니다.