Socket.io란?
- WebSocket
- Socket.io
📖 Socket IO Reference Server API : https://socket.io/docs/v4/server-api/ Client API : https://socket.io/docs/v4/client-api/
🤔 Socket.io 학습
: Socket.io enables real-time, bidirectional and event-bases communication.
→ 실시간, 양방향, event 기반의 통신을 가능하게 하는 프레임워크
→ Front와 Back이 서로 실시간 통신을 가능하게 하는 프레임워크
- Socket.io는 WebSocket을 실행하는게 아니라는걸 명심하기.
- Socket.io is not a WebSocket implementation.
- Socket.io는 WebSocket에 의존하는 것이 아님. 즉
→ 즉, WebSocket이 지원되지 않는 브라우저도 Socket.io 사용 가능
→ WebSocket을 지원하지 않는 브라우저는 HTTP의 long-polling을 사용.
💡Socket.io 중요 개념

🎈Socket.io 기본 개념
-
Socket : 클라이언트와 서버간의 연결을 뜻함. → Socket을 사용하여 실시간으로 데이터를 주고받을 수 있음.
-
Server : 클라이언트와의 소켓 연결을 설정하고 관리. → 클라이언트로 이벤트를 전달하거나 수신할 수 있다.
-
Client : 서버와의 소켓 연결을 설정하고 관리. → 서버와 반대로, 서버로 이벤트를 전달하거나 수신할 수 있다.
🎈Socket.io 트래픽 격리 구분
-
Event : 소켓 연결을 통해 클라이언트와 서버간에 전송된 메시지를 뜻함. → 이벤트 이름은 서버와 클라이언트 모두 동일하게 선언되어야한다. JSON, 문자열, 이진 등 모든 형식의 데이터 포함 가능
-
Namespace : 클라이언트와 서버의 별도 통신 채널 → 단일서버에서 여러 Namespace 작성 가능. → 클라이언트는 특정 Namespace에 연결하여 해당 Namespace의 다른 클라이언트들에게만 이벤트를 전달 혹은 수신할 수 있음.
-
Room : 결합된 Socket들의 집합(그룹). →Socket은 여러 Room에 합류하거나 떠날 수 있음. → Room은 연결된 모든 Socket에게 방송하는 대신, 특정 그룹에게 메시지를 전달하는데 유용하다.
🎈Socket.io 이벤트 송수신 방식
- Public : 연결된 모든 클라이언트들에게 메세지가 전송되는 경우
- Socketio에서 emit으로 연결된 모든 클라이언트들에게 메시지를 Broadcast(자신의 호스트가 속해 있는 네트워크 전체를 대상으로 패킷을 전송하는 일대다 통신방식)하는 방법
- 채팅 메시지와 같은 일반 메시지를 연결된 모든 클라이언트들에게 보낼때 유용
// 서버
io.on("connection", (socket) => {
socket.on("chat message', (message) => {
io.emit('chat message',message);
// 연결된 모든 클라이언트들에게 메시지 통신(브로드캐스트)
});
});
// 브라우저
socket.on('chat message', (message) => {
console.log(`Received message: ${message}`);
});
- Private : 특정 클라이언트에게 메시지를 보낼 때
- 특정 emit 클라이언트에게 메세지를 보내는 방법
- 알림 또는 알림과 같은 개인 메시지를 특정 클라이언트로 보낼 때 유용
// 서버
io.on('connection' (socket) => {
socket.on('send notification' ,(message, recipientId) => {
io.to(recipientId).emit('notification', message);
// 지정된 클라이언트(수신자)에게 메시지 전달
});
});
// 브라우저
socket.on('notification', (message) => {
console.log(`Received notification: ${message}`);
});
- Broadcasting : 발신자를 제외한 모든 클라이언트들에게 메시지가 전송되는 경우
- socket.broadcast.emit으로 발신한 발신자를 제외한 모든 연결된 클라이언트들에게 메시지를 브로드캐스트하는 방법.
- 발신자를 제외한 모든 연결된 클라이언트들에게 사용자 연결 또는 종료와 같은 알림을 보내는데 유용
// 서버 측
io.on('connection', (socket) => {
socket.on('user join', (userName) => {
socket.broadcast.emit('new user', userName);
// 발신자를 제외한 연결된 모든 클라이언트에게 메시지 통신(브로드 캐스트)
// room을 가리지 않고 모든 socket에게 통신
});
});
// 클라이언트 측
socket.on('new user', (userName) => {
console.log(`New user joined: ${userName}`);
});
🎈Socket.io 이벤트 송수신 개념
- Emit : 클라이언트 ↔서버에서 이벤트를 보내는데 사용한다.
- Event 이름과 전송할 데이터로 구성된 총 2개의 props가 필요하다.
// 이벤트 이름, 전송시킬 데이터
socket.emit('chat message', 'Hello DaeHyeon!');
- To : 특정 Socket이나 Room에 이벤트를 전송시키는데 사용한다.
- 이벤트가 전송될 Socket ID 혹은 Room Name 이라는 prop이 필요하다.
// to method는 event를 보낼 Socket ID를 지정하는데 사용한다.
io.to('00001').emit('chat message', 'Hello DaeHyeon!');
- On : 클라이언트↔서버에서 Event에 대한 listener를 만드는 용도
- Event이름과 Event를 처리하기위한 Callback 함수로 구성된 총 2개의 props가 필요하다.
// 이벤트 이름, 이벤트가 수신될 때 호출되는 Callback 함수
socket.on('chat message', (message) => {
console.log(`Received message: ${message}`);
});
- Of : 자체 Socket 및 Event 세트로 새로운 Namespace를 만드는데 사용한다.
- 생성할 Namespace의 이름을 prop으로 사용한다.
// of <- 새로운 Namespace 생성
const chatNamespace = io.of('/chat');
💡 Socket.io 작동 방식

- 서버는 들어오는 연결을 확인하여 클라이언트가 수신하는 이벤트를 처리한다.
- 클라이언트는 서버에 연결하고 이벤트를 수신하거나 전달받은 데이터를 확인할 수 있다.
- 클라이언트가 이벤트를 전달하면 서버는 이벤트를 수신받아 클라이언트로 응답을 다시 보낼 수 있다.
- 클라이언트가 이벤트를 전달하면 서버는 동일한 네임스페이스 또는 Room에 있는 다른 클라이언트로 이벤트를 브로드캐스트 할 수 있다.
🎈 Adapter란?
An Adapter is a server-side component which is responsible for broadcasting events to all or a subset of clients.
When scaling to multiple Socket.IO servers, you will need to replace the default in-memory adapter by another implementation, so the events are properly routed to all clients.
Adapter는 모든 클라이언트나 일부 클라이언트에 이벤트를 중계해주는 서버측 컴포넌트입니다.
Socket서버가 여러개로 늘어날 때, 기본 메모리 Adapter를 다른 Adapter로 교체해야하며, 그래야 이벤트들이 모든 클라이언트에서 적절하게 라우팅될 수 있습니다.
- socket.io에서 Adapter는 다른 서버들 사이에 실시간 어플리케이션을 동기화 하는 역할을 수행
- 본래 서버의 메모리에서 기본 Adapter를 사용한다. (socket.io의 adapter가 아닌, 서버에서 기본 제공 되는 것.)
- 서버는 클라이언트와의 커넥션들을 메모리에 저장한다.
→ 이때, DB에는 아무것도 저장하지 않는다.
-
서버는 모든 클라이언트에 커넥션을 오픈해야하기에 수많은 클아이언트에게 커넥션이 요청되면 개발자는 해당 연결을 유지하기 위해 서버를 두 세개, 혹은 더 많이 증가시킨다.
-
그렇게 늘어난 서버는 같은 메모리 폴을 사용하지 않기에 각 서버는 다른 메모리를 사용하게 된다.
-
즉, 두 명의 사용자가 똑같은 클라이언트를 이용하지만 다른 서버에 연결되어 실시간 데이터 스트리밍이 불가능하게 된다.
-
이런 경우에 socket io의 adapter를 사용하며, adapter는 만약 서버 A에 있는 클라이언트를 이용하는 유저가 서버 B에 있는 유저에게 데이터를 전송하고 싶을 때 동기적으로 보낼 수 있도록 한다.
-
Adapter는 누가 연결되었는지, 현재 어플리케이션에 room이 얼마나 있는지 알 수 있다.
rooms: Map(2) { // ... 현재 어플리케이션에 있는 모든 room } sids: Map(2) { // ...socket id들 확인 가능 } -
socket은 그 자체로 room 하나를 가지고 있다.
-
socket id (=sids)는 클라이언트 식별자, 즉 사용자 ID이며 동시에 socket의 private한 room id.
-
즉, socket id = private room id
-
객체 rooms는 socket.id이자 private room과 join을 통해 만들어진 public room의 집합 객체
-
객체 rooms은 sids를 포함한다.
-
만약, 객체 rooms에 sids를 찾을 수 없다면 해당 room은 Public Room.
→ 🎇 최종 요약
→ sids는 private room이자 사용자 ID(socket id)
→ rooms는 private room, public room 모두 존재.
- 이때, rooms는 sids값을 포함한다.
- 즉, rooms에서 sids값을 제외한 나머지는 Public room.
💡 Admin Panel
-
Socket.io는 Admin UI를 제공한다.
-
서비스중인 Socket.io 배포 상태에 대한 개요를 확인할 수 있다.
-
현재 연결된 서버 및 클라이언트 정보
-
각 Socket 인스턴스의 세부 정보 (active transport, handshake, room 등등..)
-
각 room에 대한 정보
-
서버(Server-side)에서 emit시키는 모든 Event에 대한 세부 정보
-
Socket 관리 작업 (join, leave, disconnect 등등..)
-
🤔 설치 방법
npm install @socket.io/admin-ui // server-side (server.js) const { createServer } = require("http"); const { Server } = require("socket.io"); const { instrument } = require("@socket.io/admin-ui"); const httpServer = createServer(); const io = new Server(httpServer, { cors: { origin: ["https://admin.socket.io"], credentials: true } }); instrument(io, { auth: false, mode: "development", }); httpServer.listen(3000);