자바스크립트/라이브러리

자바스크립트의 Socket.io 라이브러리란? (웹소켓 통신 라이브러리)

Jake Seo 2024. 2. 10. 05:03

개요

picture 0

  • WebSocket 프로토콜을 사용해서 만든 양방향 통신이다.
  • 웹에서 일반적으로 사용하는 HTTP 는 기본적으로 클라이언트가 서버에게 요청하는 관점이라면, WebSocket 은 서로서로 요청하는 양방향이다.
  • low-latency (낮은 지연), bi-directional (양방향), event-based (이벤트 기반) 로 클라이언트와 서버가 통신할 수 있게 해준다.

기본 통신 예제

  • emit() 은 메세지를 보낸다. (연결된 모든 소켓에게 보낸다.)
    • boradcast.emit() 이란 것도 있는데, 이는 나 빼고 모두에게 메세지를 보낸다.
  • on() 은 메세지를 받는다.

서버 코드

import { Server } from "socket.io";
// 웹소켓 서버를 생성
const io = new Server(3000);

io.on("connection", (socket) => {
  // 클라이언트로 메세지 보내기
  socket.emit("hello from server", "hello i am a server");

  // 클라이언트로부터 메세지 받기
  socket.on("hello from client", (...args) => {
    console.log("클라이언트로부터 메세지 받음", args); // args -> hello i am a client
  });
});

클라이언트 코드

import { io } from "socket.io-client";
// 웹소켓 서버에 연결
const socket = io("ws://localhost:3000"); // -> 클라이언트가 일단 연결하면 서로 메세지를 보내거나 받을 수 있다.

// 서버로 메세지 보내기
socket.emit("hello from client", "hello i am a client");

// 서버로부터 메세지 받기
socket.on("hello from server", (...args) => {
  console.log("서버로부터 메세지 받음", args); // args -> hello i am a server
});

Acknowledgement (접수 통지, 승인)

  • 메세지를 받고 서버쪽으로 응답을 전달할 수 있음
socket.emit("channel", "I am fine thank you", (response) => {
  // "and you?"
  console.log(response);
});
socket.on("channel", (message, callback) => {
  console.log(message);
  callback("and you?");
});

Namespace 와 Room

  • Namespace 로 1차로 격리된 공간을 만든다.
  • Room 으로 2차로 격리된 공간을 만든다.
  • Namespace1Room1Namespace2Room1 은 완전히 다른 공간이다.

picture 1

서버에서 namespace 와 room 만들기

  • io.of() 메서드를 통해 namespace 를 만들 수 있다.
  • socket.join() 메서드를 통해 연결된 소켓을 room 에 넣을 수 있다.
const io = require("socket.io")(3000); // Initialize Socket.IO on port 3000

// Create namespace1
const namespace1 = io.of("/namespace1");
namespace1.on("connection", (socket) => {
  console.log("A user connected to namespace1");

  // Join room1
  socket.join("room1");
  // You can emit to room1 in namespace1 like this:
  namespace1
    .to("room1")
    .emit("hello", "Hello to everyone in room1 of namespace1");

  // Join room2
  socket.join("room2");
  // Similarly, emit to room2 in namespace1
  namespace1
    .to("room2")
    .emit("hello", "Hello to everyone in room2 of namespace1");

  socket.on("disconnect", () => {
    console.log("A user disconnected from namespace1");
  });
});

// Create namespace2
const namespace2 = io.of("/namespace2");
namespace2.on("connection", (socket) => {
  console.log("A user connected to namespace2");

  // Join room1
  socket.join("room1");
  // Emit to room1 in namespace2
  namespace2
    .to("room1")
    .emit("hello", "Hello to everyone in room1 of namespace2");

  // Join room2
  socket.join("room2");
  // Emit to room2 in namespace2
  namespace2
    .to("room2")
    .emit("hello", "Hello to everyone in room2 of namespace2");

  socket.on("disconnect", () => {
    console.log("A user disconnected from namespace2");
  });
});

클라이언트에서 각 room 에 연결하기

  • 실제로 클라이언트를 어떤 room 에 보낼지는 서버에서 조작한다.
    • socket.join() 을 실행해 특정 room 에 넣는다.
  • 클라이언트에서는 room 을 정할 수 있는 기능이 없다.
// Connect to namespace1
const namespace1 = io.connect("http://localhost:3000/namespace1");

// Once connected, join room1
namespace1.on("connect", () => {
  console.log("Connected to namespace1");
  // namespace1.emit("join", "room1"); // Assuming the server handles a 'join' event to add the socket to a room

  // Listen for messages from the server
  namespace1.on("hello", (msg) => {
    console.log("Message from room1 in namespace1:", msg);
  });
});
// Connect to namespace2
const namespace2 = io.connect("http://localhost:3000/namespace2");

// Once connected, join room2
namespace2.on("connect", () => {
  console.log("Connected to namespace2");
  // namespace2.emit("join", "room2"); // Similarly, assuming the server handles a 'join' event

  // Listen for messages from the server
  namespace2.on("hello", (msg) => {
    console.log("Message from room2 in namespace2:", msg);
  });
});
반응형