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