user A : Room.js
other user 이벤트를 받으면, 상대방 peer의 배열인 userIDs에서 각각의 상대방 클라이언트와 소통할 수 있는 peer를 만든다.
이 때 각 클라이언트 ID와 이에 해당하는 peer는 peerRef와 peers_ 배열에 기록이 된다. peerRef는 useRef를 통해 만들어졌고 peers_는 후에 setPeers를 통해 새로운 state로 업데이트되는 상태 값이다.
즉 user A의 상대방 user B, C, D들에 대한 정보가 peerRef와 peers_에 둘 다 저장이 된다.
socketRef.current.on('other user', userIDs => {
if(userIDs){
const peers_ = [];
userIDs.forEach((userID)=>{
const peer_ = createPeer(userID, socketRef.current.id, stream);
peerRef.current.push({ // 상대방 user 정보 저장(peer와 클라이언트 socket id 매칭)
peerID:userID,
peer_
})
peers_.push({ // 상대방 user 정보 저장(peer와 클라이언트 socket id 매칭)
peerID:userID,
peer_,
})
})
setPeers(peers_) // 상대방 user 정보 저장(peer와 클라이언트 socket id 매칭)
}
});
user A : createPeer()
user A 측에서 상대방 user B와 통신할 수 있는 peer AtoB를 만들어야 한다.
new peer
를 통해 peer AtoB를 만든다. initiator가 true이므로 우선 peer.on(”signal”)
을 바로 실행한다. 이는 peer AtoB가 peer간의 통신을 맨 처음 만들어주는 initiator의 역할을 한다는 뜻이다. 그렇기 때문에 먼저 상대방에게 이 통신에 대한 OFFER를 보내야 한다.
user B의 peer BtoA로 데이터를 보내고 싶을 때의 작업을 peer.on("signal")
에서 해 주고, peer BtoA로부터 데이터를 받은 후 작업을 peer.on("data")
에서 해 준다.
이 peer AtoB가 어떤 user와 연결될 것인지는 userToSignal을 통해 알 수 있다.
function createPeer(userToSignal, callerID, stream) {
// 상대방 peer를 새로 만들어야 한다. 이 peer가 어떤 유저를 가리키는지는
// sending signal 이벤트를 emit하면서 userToSignal에게 보낸다는 것을 넣어주므로 알 수 있다.
const peer = new Peer({
initiator:true,
trickle:false,
stream,
})
// RTC Connection : **OFFER**
peer.on("signal", (signal)=>{ // remote peer에게 연결 시그널 보내기
// 여기 안에서 시그널을 특정 유저한테 보내는 작업을 해야 한다.
socketRef.current.emit("sending signal", { // userToSignal 피어에게 보낸다.
userToSignal,
callerID,
signal,
})
})
// Data Chanel : Recieve data
/* 이 peer로부터 canvas 데이터를 받는다. 받으면 그 데이터를 draw한다. */
peer.on("data", data => {
draw(JSON.parse(data));
})
return peer;
}
server.js
socket.on("sending signal”)
peer AtoB가 remote peer BtoA에게 데이터를 보내고 싶으면 위의 peer.on(”signal”) 안에서 sending signal 이벤트를 서버로 emit한다. 이제 서버에서 remote peer에게 해당 데이터를 보내야 한다.
이 때 서버는 해당 peer BtoA에게 user joined 이벤트를 발생시킨다.
io.on("connection", (socket) => {
...
socket.on("sending signal", (payload) => {
// userToSignal peer에게 signal 데이터를 보낸다.
io.to(payload.userToSignal).emit("user joined", {
signal: payload.signal,
callerID: payload.callerID,
});
});
...
user B : Room.js