- 네트워크에서 두 컴퓨터 간의 ‘실시간 양방향 통신’을 제공하는 기술을 의미합니다. 양방향 통신은 송신자 측이 데이터를 수신할 수도 있으며, 수신자 측이 데이터를 송신할 수 있는 구조를 가집니다.
-두 컴퓨터 간에는 '특정 IP 주소와 포트번호'의 조합으로 네트워크 간의 연결을 수행하며, 수신자(클라이언트)는 데이터를 요청하면 송신자(서버)에서는 요청에 대한 응답을 제공해 주는 '클라이언트-서버' 모델을 사용하여 데이터를 송수신할 수 있습니다. - 소켓 통신은 'TCP'와 'UDP'라는 두 가지 주요 프로토콜을 사용할 수 있습니다. - 이러한 프로토콜을 통해 웹 서버, 이메일 서버, 데이터베이스 서버 등 다양한 응용 프로그램에서 사용되며, 실시간 통신, 스트리밍, 온라인 게임 등에서도 사용됩니다.
- 서버-클라이언트 간의 실시간 양방향 통신을 가능하게 하는 라이브러리입니다. 주로 웹 애플리케이션에서 클라이언트와 서버 간의 실시간 데이터 전송을 위해 사용이 됩니다.
- 이는 WebSocket 프로토콜을 사용하지만, 브라우저 호환성을 위해 필요한 경우에는 풀백(fallback) 메커니즘을 사용합니다.
https://socket.io/
[ 더 알아보기 ] 💡 풀백 메커니즘
- 주어진 기술이나 프로토콜이 작동하지 않을 경우, 대체할 수 있는 다른 방법을 사용하는 것을 의미합니다. - 예를 들어, Socket.io는 WebSocket을 기본적으로 사용하지만, 만약 클라이언트의 브라우저가 WebSocket을 지원하지 않는다면, HTTP 롱 폴링 등 다른 통신 방식을 사용하여 여전히 실시간 통신을 가능하게 합니다.
💡 Room - Socket.io에서 클라이언트들을 그룹으로 묶는 기능을 제공합니다. 이 클라이언트는 여러 Room에 참여할 수 있으며, 서버는 특정 Room에 속한 클라이언트들에게만 메시지를 전송할 수 있습니다. - 이를 통해 메시지를 특정 그룹의 클라이언트에게만 효율적으로 전달할 수 있습니다.
1. 클라이언트 A와 B는 소켓이 연결된 이후 "myroom"이라는 Room에 참여합니다(Join).
2. 따라서 클라이언트 A와 B는 "myroom"이라는 그룹에 속하게 됩니다.
3. 이제 서버에서 "myroom" 그룹으로 특정 메시지 이벤트와 메시지를 전송합니다.
4. 해당 "myroom"에 속한 클라이언트 A와 B에게 메시지가 ‘일괄적’으로 전송됩니다.
https://socket.io/docs/v3/rooms/
io.on("connection", socket => {
// 클라이언트를 특정 Room에 참여시키기
socket.join('myroom');
}
// 특정 Room에 있는 모든 클라이언트(클라이언트 A, B)에게 메시지 전송
io.to('myroom').emit('message', 'Hello My Room');
// or// 여러 room1, room2, room3에 속해 있는 클라이언트 들에게 모두 메시지 전송
io.to("room1").to("room2").to("room3").emit("some event");
💡 Room 방 나가기 예시 : 방 나가기 및 메시지 전달
- 소켓 서버와 클라이언트 A, B, C 간의 관계에서 사용됩니다. 이전 관계에서는 클라이언트 A, B가 myroom이라는 그룹에 소속되어 있었고, 클라이언트 A는 해당 그룹을 나가게 됩니다.
1. 기존의 클라이언트 A와 B는 “myroom”이라는 Room에 참여했었습니다. 그런데, 클라이언트 A가 그룹을 나갑니다.
2. 서버는 “myroom” 그룹으로 특정 메시지와 이벤트를 전송합니다.
3. 해당 “myroom” 그룹에 속한 클라이언트 B에게만 메시지가 전송됩니다.
https://socket.io/docs/v3/rooms/
io.on("connection", socket => {
// 클라이언트를 특정 Room에서 나가게 하기socket.leave('myroom');
}
// 특정 Room에 있는 모든 클라이언트(클라이언트 A, B)에게 메시지 전송io.to('myroom').emit('message', 'Hello My Room');
4.2. Namespace
💡 Namespace
- Socket.io에서 기본 네임스페이스(/) 외에 추가적인 네임스페이스를 생성하여 클라이언트 연결을 분리하는 기능을 제공합니다. 이를 통해 서로 다른 네임스페이스 간에 독립적인 이벤트 처리가 가능합니다.
- 예를 들어, 채팅 애플리케이션에서 일반 채팅과 관리자 채팅을 분리할 때 이용합니다. 또는 게임에서 로비와 게임 플레이 구역을 분리할 때 이용됩니다.
https://socket.io/docs/v4/namespaces/
💡 Socket.io 네임스페이스 - “admin”이라는 네임스페이스를 생성하고, 해당 네임 스페이스에 이벤트 리스너를 설정하는 예시입니다
1. 기존 default namespace가 아닌 별도 구성한 “admin”이라는 네임스페이스로 연결을 합니다.
2. 연결이 완료되어 발생하는 소켓을 기반으로 message라는 이벤트를 등록(수신) 설정합니다.
3. 클라이언트로부터 “admin” 네임스페이스의 “message” 이벤트가 발생하면 해당 이벤트에 데이터 로그가 출력됩니다.
// 새로운 네임스페이스 생성const adminNamespace = io.of('/admin');
// 네임스페이스 내에서 이벤트 리스너 설정
adminNamespace.on('connection', (socket) => {
console.log('Admin connected');
socket.on('message', (data) => {
console.log('Admin message:', data);
});
});
- socket 통신을 위한 라이브러리로 socket.io를 설치하며 이외에 라이브러리를 추가해 줍니다.
💡cors 라이브러리
- 웹 애플리케이션이 서로 다른 출처(domain, protocol, port)에서 리소스를 요청할 때 보안 상의 이유로 브라우저는 기본적으로 이러한 요청을 차단합니다. - CORS는 이러한 제한을 우회하여 특정 출처에서의 요청을 허용하도록 설정할 수 있는 메커니즘을 제공합니다. - Socket.io와 같은 라이브러리를 사용할 때, 클라이언트와 서버가 서로 다른 출처에 있을 경우 CORS 설정이 필요합니다. 이를 통해 클라이언트가 서버에 안전하게 접근할 수 있습니다.
💡 express 라이브러리
- HTTP 서버를 손쉽게 구축할 수 있도록 도와주는 웹 프레임워크입니다. - Socket.io와 결합하여, 클라이언트가 실시간 통신을 시작하기 전에 HTTP 요청을 통해 초기 연결을 설정하고, 이후 WebSocket으로 업그레이드하여 실시간 통신을 이어나갈 수 있습니다.
# socket.io install
$ npm i socket.io cors express
- 해당 서버로 접속할 포트를 지정하고, cors()를 통해서 다른 도메인에서의 모든 요청에 대해서 허용합니다.
2. WebSocket Server 설정 값 및 socket.io 구성
- HTTP 서버를 생성하고 지정된 포트로 접근 가능하도록 설정합니다. - 생성된 HTTP 서버를 기반으로 소켓 서버를 설정하고 socket.io에 대한 cors에 대해 모두 허용을 설정합니다.
3. 루트 엔드포인트로 접속 시 health Check 수행
- 루트 경로(”/”)로 접근시 “Hello world!” 메시지를 출력하고 로그를 출력합니다.
4. 소켓 연결 시작 - io.on("connection") : 클라이언트가 소켓 서버에 연결되었을 때 실행됩니다.
- socket.on("disconnect"): 클라이언트가 연결 해제되었을 때 실행됩니다.
// import libraryconst app = require("express")(); // 외부 라이브러리 사용const cors = require("cors"); // 외부 라이브러리 사용const http = require("http"); // Node 제공 모듈 사용/*
* 1. WebSocket Server 설정 : port, cors 지정
*/const port = 5001;
app.set("port", port); // 웹 소켓 포트를 지정합니다
app.use(cors({ origin: "*" }));
// cors를 지정해줍니다./*
* 2. WebSocket Server 설정값 및 socket.io 구성
*/const server = http.createServer(app).listen(port); // 설정 값에 따르는 서버 정보 구축const io = require("socket.io")(server, {
cors: {
origin: "*",
methods: ["*"], // 모든 메서드 허용
},
}); // 설정 값에 따라 socket.io 구축/*
* 3. 루트 엔드포인트로 접속 시 health Check 수행
*/
app.get("/", (req, res, next) => {
res.send("Hello world!"); // 화면상으로 출력console.log("====== Health Check ======="); // 로그 출력
});
/*
* 4. 소켓 연결 시작
*/
io.on("connection", (socket) => {
socket.on("message", (msg) => {
io.emit("message", msg);
});
console.log("a user connected");
socket.on("disconnect", () => {
console.log("user disconnected");
});
});
[ 더 알아보기 ] 💡 WebSocket Server 설정에서 cors()를 허용하는데 socket.io 설정에서 cors를 허용하는 이유는?
1. app.use(cors({ origin: "*" }))
- Express.js 서버에서 HTTP 요청에 대한 CORS 설정을 허용합니다. 이는 웹 소켓 연결을 설정하기 전에 초기 HTTP 요청을 허용하는 역할을 합니다.