# 2.8 - 2.9 Room Count

이원규·2022년 6월 16일

Zoom clone coding

목록 보기
12/18
post-thumbnail

1. (mongoDB) Adapter

1.1 Adapter

Adapter Document

  • 기본적으로 하는 일은 다른 서버들 사이에 실시간 어플리케이션을 동기화하는 일을 함.
    -> 현재 우리는 서버의 메모리에서 Adapter를 사용하고 있음. 데이터 베이스에는 아무
    것도 저장하지 않고 있음. 서버를 종료하고 다시 시작할 때, 모든 room과
    message와 socket이 없어짐. 재시작해도 그대로 냅두고 싶음(백엔드에 데이터
    베이스를 가지고 싶어함.)
    -> 보이는 화면은 같지만 서버가 달라서 클라이언트(유저)끼리 통신하지 못함. 이 때,
    서버 간의 통신을 해줘서 다른 서버의 두 클라이언트가 통신하도록 하게끔 도와주는
    것이 Adapter이다.
    -> 대형 어플리케이션은 여러 서버를 가지므로 Adapter가 반드시 필요함. 왜냐하면
    Adapter가 어플리케이션으로 통하는 창문이기 때문임. 내가 진짜 database를 쓴 다면, Adapter가 필요함.
    -> Adapter는 우리에게 누가 연결되었는지, 현재 애플리케이션에 room이 얼마나 있
    는지 알려줄 것임.

    -> 현재 우리 Zoom clone coding은 memory에서 진행중임. memory내에도 adapter가 있음. 이 adapter를 보려면, 다음 코드 추가
backSocket.onAny((event) => {
        console.log(ioServer.sockets.adapter);//adapter추가
        console.log(`Socket Event: ${event}`);
    });

-> object와 map의 차이점

-> 어플리케이션에 있는 모든 room(모든rooms)과 socket id들(sockets), 개인방(sids- socket id로 방이 이루어짐)가 있는 것을 볼 수 있음.
-> 요약: sids에는 개인방, rooms에는 개인방,공개방 다있음. rooms가 sids를 포함한다 보면됨.
그래서 공개방만 얻고 싶을때는 rooms에서 sids를 빼면 됨.

즉, rooms에서 sids를 뺀 나머지 방은 public방이 됨.

1.2 JS Map

map 정보 1
map 정보 2
-> map은 object같은 건데, unique key가 있음.
-> 객체를 키로 사용할 수 있다는 점은 맵의 가장 중요한 기능 중 하나입니다. 객체에는 문자열 키를 사용할 수 있습니다. 하지만 객체 키는 사용할 수 없습니다.

let john = { name: "John" };

// 고객의 가게 방문 횟수를 세본다고 가정해 봅시다.
let visitsCountMap = new Map();

// john을 맵의 키로 사용하겠습니다.
visitsCountMap.set(john, 123);

alert( visitsCountMap.get(john) ); // 123

-> 기본적인 사용법 by nico

const food = new Map(); //undefined

food.set("pizza",12)//Map(1) {"pizza" => 12}  // Key:"pizza", value: 12 즉, {key => value}
food.get("pizza")// 12 -> get(key)
food.get("lalal")// undefined

sids//Map(2) {"-oZuTz_R0PtXJbHJAAAB"=>"-oZuTz_R0PtXJbHJAAAB", "XZIGLP-3n-RsgDUmAAAD"=>"XZIGLP-3n-RsgDUmAAAD"}
sids.forEach((value, key) => console.log(value, key))
/*결과값:
"-oZuTz_R0PtXJbHJAAAB" "-oZuTz_R0PtXJbHJAAAB"
"XZIGLP-3n-RsgDUmAAAD" "XZIGLP-3n-RsgDUmAAAD"
*/

rooms/*Map(4) {
    '-oZuTz_R0PtXJbHJAAAB' => Set(1) { '-oZuTz_R0PtXJbHJAAAB' },
    'XZIGLP-3n-RsgDUmAAAD' => Set(1) { 'XZIGLP-3n-RsgDUmAAAD' },
    '123' => Set(1) { '-oZuTz_R0PtXJbHJAAAB' },
    '125' => Set(1) { 'XZIGLP-3n-RsgDUmAAAD' }
  }*/

//rooms의 변수(인수) -> rooms(value, key) 이 순서임
rooms.forEach((value, key) => console.log(value, key))
/*결과값: 
"-oZuTz_R0PtXJbHJAAAB" "-oZuTz_R0PtXJbHJAAAB"
"XZIGLP-3n-RsgDUmAAAD" "XZIGLP-3n-RsgDUmAAAD"
"-oZuTz_R0PtXJbHJAAAB" "123"
"XZIGLP-3n-RsgDUmAAAD" "125"
-> value값은 겹칠 수가 있음.(최초의 방을 만든 사람의 id가 map에선 그 방의 value값이 됨.)*/

-> sids: 우리 백엔드에 연결된 sockets들의 map임.
-> value값은 id로 겹치므로 key값을 이용하여 rooms에서 sids(private room)를 걸러내야함

1.3 (backend) map을 활용하여 rooms의 public방[array] 형태로 구하기.

function publicRooms(){
    const {sockets : {adapter: {sids, rooms}}} = ioServer;
    /* 위의 콘드는 밑의 두 줄을 풀어쓴 거. 	
	const sids = ioServer.sockets.adapter.sids; 
    const rooms = ioServer.sockets.adapter.rooms;*/
    const publicRooms = [];
    rooms.forEach((_/*value자리임*/, key) => {
        if(sids.get(key) === undefined){
            publicRooms.push(key);
        }
    });
    return publicRooms;//결과값: ["125", "123"]
};

-> rooms(map)은 forEach를 쓸 때, 첫번째 자리로는 value, 두번째 자리로는 key를 인수로 받음

1.4 (back -> front)public rooms의 array를 보내주는 함수를 실행.

server.sockets.emit

  • publicRoom의 array를 방에 입장할 때, 방에서 나갈 때 알려줄 것임.
  • server.sockets.emit: 서버에 연결된 모든 sockets에게 message를 보낼 때 활용.
  • 다음의 코드를 이벤트 리스너에 추가해줌.
//방에 입장할 때, 서버와 접속이 끊길 때 다음과 같은 코드를 추가해줄 것임.
ioServer.sockets.emit("room_change", publicRooms());

//추가 후 코드
//1. 방에 입장할 때
backSocket.on("enter_room", (roomName, done) => {
        backSocket.join(roomName);
        done();
        backSocket.to(roomName).emit("welcome", backSocket.nickname);
        ioServer.sockets.emit("room_change", publicRooms());
    });

//2. 방에서 나갈 때
backSocket.on("disconnect", () => {
        ioServer.sockets.emit("room_change", publicRooms());
    });

-> publicRooms() : ["125", "123"]

1.5 (frontend) back에서 받은 public rooms의 array를 처리해줌.

1.5 -1(home.pug)

-> welcome div에 방 리스트 나타내줄 것임.

div#welcome
        form
            input(placeholder="room name", required, type="text")
            button Enter Room
        h4 Open Rooms: 
        ul
1.5 -2(app.js)

-> backend에서 받은 publicRooms array를 html에 보이도록 처리할 것임.

frontSocket.on("room_change", (publicRooms) => {
  	const roomList = welcome.querySelector("ul");
  	roomList.innerHTML = "";//방이 여러개 생김에 따라, publicRoom이 겹쳐서 화면에 나오는 걸 막기 위해
    if(publicRooms.length === 0){
        return;
    };
    publicRooms.forEach((room) => {
        const li = document.createElement("li");
        li.innerText = room;
        roomList.append(li);
    });
});

-> publicRooms가 0일 때 처리해준 이유: 처음 방 리스트를 paint했다가, 다시 한 번 실행할 때 목록이 비어있으면 아무것도 실행 안하기 때문. 즉, room이 없어졌는데도 ul에는 방 list가 남아있으므로, room이 없어짐에 따라 ul에서도 room이 없어지도록 해주려고!

-> roomList.innerHTML = "": 방이 여러개 생김에 따라, publicRoom이 겹쳐서 화면에 나오는 걸 막기 위해. 즉, 처음에 [1번방] 이었다가 새로 방이 생김에 따라 publicRooms가 [1번방, 2번방] 이렇게 되면, 화면에 1번방이 2번 나타나게 됨. 이러한 경우를 방지하기 위해 이 코드를 넣어줬음.

  • safari 새로고침 후(방에서 나간 후) 아래 사진.
profile
github: https://github.com/WKlee0607

0개의 댓글