초보 개발자

Room chat 2 본문

Zoom 클론

Room chat 2

taehyeki 2021. 10. 8. 12:19

Adapter는 기본적으로 다른 서버들 사이에 실시간 어플리케이션을 동기화 해준다.

우리는 서버의 메모리에서 Adapter를 사용하고 있다. 우리가 서버를 종료하고 다시 시작할 때 모든 room과 message와 socket은 사라진다. 지금 많은 client로부터의 connection들을 메모리에 저장하고 있다. 만약 서버를 2개 3개만들어도 같은 memory pool을 공유하지 않는다. 같은 대화창을 보고 있더라도 실제로는 다른 서버에서 연결되어 있을 수 있다.

만약 우리가 Adapter를 쓰지 않는다면 서버 A에 있는 client가 서버B에 있는 client에게 메시지를 보내고싶다면 불가능하다 서버가 분리되어 있기 때문에 따라서 Adapter를 써줘야한다.

서버A client -> 서버A -> 서버A Adapter -> 데이터베이스 -> 서버B Adapter -> 서버B -> 서버B client

와 같은 방식이다. 어플리케이션으로 통하는 창문과 같은 역할을 Adapter가 해준다.  먼저 메모리 Adapter를 사용하여

현재 누가 접속해 있는지, 어떤 방이 존재하는지 확인할 수 있다.

 

먼저 어떤 방이 존재하는지 확인해보자. wsServer.sockets.adapter를 통해 adapter를 확인할 수 있다.

그럼 sids라는 모든 socket들에 대한 정보와 rooms라는 모든 방에 대한 정보도 함께 담겨있다. 이것들은 Map()으로 이루어져있다.

 

map은 key와 value값으로 이루어져있다. 

key 를 사용해서 value 를 get, set 할 수 있다.

key 들은 중복될 수 없다.

하나의 key 에는 하나의 value 만들어갈 수 있다.

 

socket은 처음 만들어질 때 자동으로 방을 한 개씩 생성하는데 그 방의 제목은 자신의 socket id이다. 

따라서 rooms들 중에 sid와 겹치지 않는 room이 있다면 새로 만든 방임(public)을 알 수 있다. 이 방을 추출하여 처음 입장할 때 현재 열려있는 방이 있는 지 없는지를 나타낼 수 있다. 

rooms의 key값에는 방이름 적혀있고 value에는 현재 그 방에 접속해있는 사람의 socket id가 적혀있다.

sids는 key값에는 socket id가 적혀있고 value에는 그 socket id가 접속해 있는 방의 이름이 적혀있다.

socketIO는 만약 방에 남아있는 인원이 0이 되면 방도 자동으로 없애버린다.

처음 접속했을때, 방에 들어 갔을 때, 방에서 나왔을 때 현재 개설된 방을 업데이트 해주려고한다.

따라서 wsServer.sockets.adapter.sids, wsServer.sockets.adapter.rooms의 정보를 각각 sids, rooms로 받아온 후

 

rooms 안에 있는 key값( 방 이름 )이 sids의 key값으로 존재한다면 -> 자기 자신의 방 

rooms 안에 있는 key값( 방 이름 )이 sids의 key값으로 존재하지 않는다면(undefined) -> 새로 만든 방이기에

undefined인 값만 따로 배열에 저장해준다. 그리고 이 배열을 return해주는 함수를 만들었다.

즉, 이 함수의 역할은 개설된 방을 return해주는 것이다.

 

home.pug

welcome div안에 ul#list를 하나 만들어 주었다.

여기에 현재 개설된 방이 있다면 띄워줄 것이다.

 

 server.js

front-end에서 방에 입장을하면 enter_room event를 back-end로 보낸다. 그러면 방에 입장을하고 닉네임을 설정하고 그 방에 있는 사람들에게 자신이 입장했다고 알린다. 여기까지는 저번시간까지 다 했던 것이고 추가된 부분은

wsServer(웹서버의).sockets(지금 연결된 모든 소켓들에게).emit('room_change',publicRoom())(개설되어있는 방과 함께 room_change이벤트를 보낸다. )

front-end에 room_change event가 오면 먼저 아까 설정해둔 ul을 찾고 공백으로 초기화해준다( 이 이유는 나중에 나옴 )

rooms에 아무것도 없다면 그냥 끝날 것이고 하나라도 있다면 ul 밑 li에 방 이름을 하나씩 추가할 것이다.

우리는 wsServer.sockets.emit으로 했기에 모~~든 socket에게 보낼 수 있었다. 

disconnect에도 똑같이 해주자.

처음 socket이 연결되었을 때는 아무 정보가 뜨지 않기때문에 처음 connection이 될때도 해주자.

아까 ul을 계속 초기화 해주었는데 초기화 해주지 않으면 예를들어 '감자' 라는 방이 있다고 치고 방에 입장하고 퇴장하면 감자가 사라지지 않고 다시 입장하면 감자가 2개가 있는 것을 확인할 수 있다.

이번에는 방에 입장했을 때 사람이 몇명 있는지, 퇴장하면 몇명 남게 되는지 알려주는 것도 만들자.

rooms에 내가 현재 속해있는 방의 정보가 나온다고 했다. 

rooms.get('key')를 하면 내가 검색하려는 방에 존재하는 socketid 들을 확인할 수 있고, size를 통해 그 방의 인원을 알 수 있다.

또 전에 welcome event로 자기 자신외 나머지 사람들에게 입장했다고 알린 적이 있다. 

따라서 유저의 숫자도 같이 보내주면 된다. 또 여기서 살짝 생각해보아야 할 것이 있다.

 

1) socket.to(title).emit("welcome")
-> 방에서 자신을 제외한 모두에게 브로드캐스팅하여 메시지를 전달
2) wsServer.to(title).emit("welcome")
-> 방에서 자신을 포함한 모든 유저에게 메시지를 전달한다.

 

단지 userCount(title)만 보내버리면 내가 들어갈 때 방은 유저 숫자가 나오지 않는다 왜? socket.to로 했으니까..

그래서 내 socket에서도(내 브라우저) 나타나도록 콜백함수에 유저 숫자를 같이 딸려 보냈다. 

count는 userCounting으로 가게 되어

현재 내 브라우저의 화면에도 유저수가 잘 나타나도록 하였다.

그리고 유저가 퇴장할 때도 생각해야 한다. 유저가 입장할 때는 입장하는 방만 생각해주면 되었지만, 퇴장할 때는 유저가 들어있던 모든 방에서 퇴장을 해야한다. 

disconnecting은 아직 연결이 되어있따. 연결이 되기 직전에 실행하는 것이다. 따라서 room을 쓸 수 있다. 반면 disconnect에선 room을 쓸 수 없다. 왜냐면 연결이 끊긴 상태이니까

 

socket.rooms를 통해 현재 내가 접속해 있는 방들 하나하나에게 bye event를 보내면서 userCount를 딸려보낸다 여기서 -1을 해주는 이유가 아직 연결되어있기에 나도 세어지는 것이다. 따라서 나는 곧 끊기니까 - 1을 해줘야지 실제로 반영이 될 것이다.

 

 

'Zoom 클론' 카테고리의 다른 글

webRTC  (0) 2021.10.10
Camera  (0) 2021.10.09
Room chat 1  (0) 2021.10.07
socket IO  (0) 2021.10.06
socket의 기본 chat원리  (0) 2021.10.06