2020년 2월 9일 일요일

Socket.io 요약

socket.io는 브라우저와 서버 간 이벤트 기반으로 양방향 통신을 가능하게 하는 라이브러리다. 내부적인 heartbeat 메커니즘을 통해 자동 재접속과 연결 끊어짐 감지를 해주기 때문에 사용하는 입장에서 라이브러리를 믿고 간편하게 쓸 수 있다.

socket.io는 사용자가 원하는 어떤 형식으로든 이벤트와 데이터 형식을 만들어 쓸 수 있게끔 지원하고 있다. 일반적으론 JSON 포맷을 쓰게 되겠지만 binary 데이터 형식의 송수신도 지원한다.
브라우저와 서버 간 이벤트를 주고받는 방법은 단순하다. 기본적으로 아래 2개의 메서드로 구현된다.
  • emit: 이벤트를 발생시킨다.
  • on: 이벤트를 수신한다.

참조: https://socket.io/docs/


Room

room 기능도 제공한다. 임의의 채널을 정의해서 특정 소켓을 그루핑 시킬 수 있는데 간단하게 생각하면 채팅방과 같은 개념으로 이해할 수 있을 것이다. namespace로 구분되는 room을 한정해서 제한된 데이터 교환이 가능하다. 이는 응용 측면에서만 아니라 설계 측면에서 리소스를 줄여주는 역할도 하기 때문에 유용하다.
기본 namespace 이름은 '/' 이다. namespace를 지정하고 싶으면 io.of() 함수를 이용하면 된다. (클라이언트에선 io()의 파라미터로 namespace 값을 전달.)


Broadcasting

브로드캐스팅의 경우 io객체의 emit() 함수를 이용하면 되는데, 발송자를 제외한 브로드캐스팅이 필요한 경우엔 socket.broadcast.emit() 함수를 이용하여야 한다. namespace를 한정해 이벤트를 발생시킬 수도 있는데 io.to() 함수를 이용하면 된다.

참조: https://socket.io/docs/rooms-and-namespaces/



** 채팅 솔루션이 급하다면 아래 링크를. 코드를 보면 알겠지만 FE가 할 일이 더 많다. 그만큼 편하게 되어있다는 뜻.
https://github.com/socketio/socket.io/tree/master/examples/chat



서버 기본 코드. 아래 꼴에서 크게 달라지지 않는다.

// Express initializes 'app' to be a function handler that you can supply to an HTTP server.
var app = require('express')();
var http = require('http').createServer(app);

var io = require('socket.io')(http);

// define a route handler '/' that gets called when we hit our website home.
app.get('/', function (req, res) {
    res.sendFile(__dirname + '/index.html');
});

// listen on the 'connection' event for incoming sockets.
io.on('connection', function (socket) {
    console.log('a user connected');
    socket.on('disconnect', function() {
        console.log('user disconnected');
    });

    socket.on('chat message', function (msg) {
        io.emit('chat message', msg);
    });
});

// http server listen on port 3000
http.listen(3000, function () {
    console.log('listening on *:3000');
});


위 코드와 대응되는 클라이언트 측 스크립트.

// client
$(function() {
    var socket = io();
    $('form').submit(function (e) {
        e.preventDefault();
        socket.emit('chat message', $('#m').val());
        $('#m').val('');
        return false;
    });

    socket.on('chat message', function (msg) {
        $('#messages').append($('<li>').text(msg));
    });
});


아래는 공식 페이지에서 제공하는 emit cheatsheet.

io.on('connect', onConnect);

function onConnect(socket){

  // sending to the client
  socket.emit('hello', 'can you hear me?', 1, 2, 'abc');

  // sending to all clients except sender
  socket.broadcast.emit('broadcast', 'hello friends!');

  // sending to all clients in 'game' room except sender
  socket.to('game').emit('nice game', "let's play a game");

  // sending to all clients in 'game1' and/or in 'game2' room, except sender
  socket.to('game1').to('game2').emit('nice game', "let's play a game (too)");

  // sending to all clients in 'game' room, including sender
  io.in('game').emit('big-announcement', 'the game will start soon');

  // sending to all clients in namespace 'myNamespace', including sender
  io.of('myNamespace').emit('bigger-announcement', 'the tournament will start soon');

  // sending to a specific room in a specific namespace, including sender
  io.of('myNamespace').to('room').emit('event', 'message');

  // sending to individual socketid (private message)
  io.to(`${socketId}`).emit('hey', 'I just met you');

  // WARNING: `socket.to(socket.id).emit()` will NOT work, as it will send to everyone in the room
  // named `socket.id` but the sender. Please use the classic `socket.emit()` instead.

  // sending with acknowledgement
  socket.emit('question', 'do you think so?', function (answer) {});

  // sending without compression
  socket.compress(false).emit('uncompressed', "that's rough");

  // sending a message that might be dropped if the client is not ready to receive messages
  socket.volatile.emit('maybe', 'do you really need it?');

  // specifying whether the data to send has binary data
  socket.binary(false).emit('what', 'I have no binaries!');

  // sending to all clients on this node (when using multiple nodes)
  io.local.emit('hi', 'my lovely babies');

  // sending to all connected clients
  io.emit('an event sent to all connected clients');

};


댓글 없음:

댓글 쓰기