소켓

socket 튜토리얼 - Emitting events

코줍 2024. 5. 2. 21:54

메소드 참고 링크
https://socket.io/docs/v4/emitting-events/

 

Emitting events | Socket.IO

There are several ways to send events between the server and the client.

socket.io

1. io객체와 socket객체를 혼동하지 말자

클라이언트

const socket = io();
socket.on("이벤트이름", (msg) => { 로직 }

 

서버

const io = new Server(server)

...중략...

io.on("connection", (socket) => {
    socket.on("이벤트이름", (msg) => {
        io.emit("chatMsg", msg)
    })
})

 

io객체는 new Server(server)라는 대목에서도 알 수 있지만, 클라 - 서버간의 양방향 연결을 위한 가장 위에있는 객체라고 보면 될 것 같다.

 

따라서 클라에선 socket이라는 변수에 io()객체를 초기화 함으로서 서버와의 통신을 하도록 준비하는 것이다.

 

socket객체는 서버에선 io객체에서 데이터 송수신을 위한 socket객체를 callback 인자로 보내는 것을 위 코드를 통해 알 수 있다.
이 callback 함수 내에서 지지고 복고 하여 클라쪽에서 메세지 수신을 할 수 있는 것을 알 수 있다.

 

2. Emit

emit(=방출하다)
클라-서버 간의 데이터를 전송할 때 사용되는 메소드.

 

클라이언트 -> 서버

// 클라이언트
socket.emit('hello', 1, '2', { 3: '4', 5: Uint8Array.from([6]) });

// 서버
io.on('connection', (socket) => {
  socket.on('hello', (arg1, arg2, arg3) => {
    console.log(arg1); // 1
    console.log(arg2); // '2'
    console.log(arg3); // { 3: '4', 5: <Buffer 06> }
  });
});

 

서버 -> 클라이언트

//서버
io.on("connection", (socket) => {
	socket.emit("hello", "world")
})
// 클라이언트
socket.on("hello", (arg) => {
	console.log(arg) // "world"
})

 

Note..

  • Date 객체는 문자열 표현으로 변환된다. ( 1970-01-01T00:00:00.000Z )
  • Map이나 Set으로 시리엉화 해주는 것이 반드시 필요하다.
const serializedMap = [...myMap.entries()];
const serializedSet = [...mySet.keys()];

  • toJSON메소드로 객체의 직렬화를 하는 것을 권장한다.
class Hero {
  #hp;

  constructor() {
    this.#hp = 42;
  }

  toJSON() {
    return { hp: this.#hp };
  }
}

socket.emit("here's a hero", new Hero());

 

3. Acknowledgements

3.1 emit() 메소드의 마지막 인자로, 콜백을 추가할 수 있다.

// 클라이언트
socket.timeout(5000).emit("request", {foo, "bar"}, (err, response) => {
	if(err){
    	// 지연시간 동안(5000밀리초) 이벤트가 확인되지 않았을 때의 로직
    }
   	else{
    	console.log(response)
    }
})
// 서버
io.on("connection", (socket) => {
	socket.on("request", (arg1, callback) => {
    	cosole.log(arg1) // {foo, "bar"}
        callback({
        	status : "ok"
        })
    })
})

 

3.2 emitWithAck() 메소드는 상대방이 이벤트를 승인하면 해결되는 Promise를 반환한다.

// 클라이언트
try {
	const response = await socket.timeout(5000).emitWithAct("request", {foo : "bar"})
    console.log(response.status) // "ok"
}
catch(e){

}

// 서버
io.on("connection", (socket) => {
	socket.on("request", (arg1, callback) => {
    	cosole.log(arg1) // {foo, "bar"}
        callback({
        	status : "ok"
        })
    })
})

 

두 메소드 모두 같은 이벤트를 전송한다는 공통점이 있다..
그러면 이 두 메소드를 적재적소에 맞게 사용하려면 어떻게 해야할까?

그에 대한 해답💡 ↗️

 

4. Volatile events ( 휘발성 이벤트 )

아직 데이터 송수신이 준비되지 않았을 때, 버퍼링 시간같은 거 카운트하기 유용하다.

//서버
io.on("connection", (socket) => {
  console.log("connect");

  socket.on("ping", (count) => {
    console.log(count);
  });
});

//클라이언트
let count = 0;
setInterval(() => {
  socket.volatile.emit("ping", ++count);
}, 1000);

 

1. volatile 메소드를 사용했을 때 출력결과

connect
1
2
3
4
# the server is restarted, the client automatically reconnects
connect
9
10
11

 

2. volatile 메소드를 사용하지 않았을 때 출력결과

connect
1
2
3
4
# the server is restarted, the client automatically reconnects and sends its buffered events
connect
5
6
7
8
9
10
11