기록하는 공부
[Zoom Clone Coding] Adapter 본문
Adapter
Adapter가 기본적으로 하는 일은 다른 서버들 사이에 실시간 애플리케이션을 동기화하는 것이다.
현재 우리는 서버의 메모리에서 Adapter를 사용하고 있다. 데이터베이스에는 아무것도 저장하고 있지 않다.
우리가 서버를 종료하고 다시 시작할 때 모든 room과 message와 socket은 없어진다.
우리는 이런 것을 원하지 않고 백엔드에 데이터베이스를 가진 형태를 원한다.
그리고 앱 안에 많은 클라이언트가 있을 때, 모든 클라이언트에 대해서 connection을 열어둬야 한다.
(Edge나 Chrome 브라우저를 우리 서버에 연결했던 것처럼)
이러한 연결과 서버 메모리는 있어야 한다.
그렇기 때문에 너의 서버는 이 connection을 오픈된 상태로 유지해야 한다.
브라우저는 서버로 단 한 개의 connection을 열 것이다.
하지만 많은 브라우저들은 하나의 서버에 conncetion들을 열게 된다. 한마디로, 서버에 많은 connection이 들어오게 된다.
그리고 서버는 그 많은 connection들을 메모리에 저장할 것이고 만약 이렇게 되면 서버를 2개 이상을 사용할 수도 있다.
지금 우리는 지금 서버 메모리에서 Adapter를 사용하고 있다.
이 말은 우리가 만든 3개의 서버는 같은 memory pool을 공유하지 않을 거라는 이야기이다.
아래 사진을 보면 이해가 쉽다.
서버 A, B가 존재한다.
만약 Adapter를 사용하지 않는다면 서버 A에 연결된 client는 서버 B에 존재하는 client에게 메시지를 전송하지 못할 것이다.
왜냐하면 두 서버는 분리되어 각각의 다른 메모리를 가지고 있기 때문이다.
따라서 우리는 Adapter를 사용해야 한다.
Adapter는 MongoDB를 사용해서 서버 간의 통신을 하게 해 준다.
MongoDB 어댑터는 MongoDB의 변경 스트림에 의존한다.
그렇기 때문에 복제본 세트 또는 분할된 클러스터가 필요하다.
여러 클라이언트(예: io.to("room1").emit() 또는 socket.broadcast.emit())로 전송되는 모든 패킷은 다음과 같다.
- 현재 서버에 연결된 일치하는 모든 클라이언트에게 전송한다.
- MongoDB 캡 컬렉션에 삽입되고 클러스터의 다른 Socket.IO 서버에서 수신된다.
현재 Adapter는 서버 메모리에 있지만 나중에는 MongoDB나 다른 것으로 교체할 것이다.
여기 콘솔창에 출력된 결과중에 중요한 점 두 가지가 있다.
첫 번째는 애플리케이션에 있는 rooms가 있다. 우리는 어플리케이션에 있는 모든 rooms를 볼 수 있다.
두 번째는 우리는 socket ID를 볼 수 있다.
콘솔창에 출력결과에서 볼 수 있듯이 rooms와 socket ID가 같다.
왜냐하면 socket도 전용 방이 있기 때문이다.
socket은 private room이 있기 때문에 우리가 private message들을 보낼 수 있다.
콘솔에 adapter를 출력해 보자.
console.log(wsServer.sockets.adapter);
아래에서 확인할 수 있듯이 rooms의 정보와 sids(socket ID)의 정보가 같은 것을 확인할 수 있다.
앞으로 우리가 방을 새로 만들게 되면 방에 대한 정보가 추가될 것이다.
<목표>
sids(socket ID)를 가져와 방들을 보고 이 방들이 어떤 socket을 위해서 만들어졌는지 볼 것이다.
그래서 Private 메시지와 모든 사람들과 채팅하기 위해 만든 방이 어떤 건지 확인한다.
왜냐면 나는 서버에 있는 모든 방 리스트를 보여주고 싶기 때문이다.
그리고 Map에 있는 모든 rooms를 확인하고 room의 ID도 확인할 것이다.
만약 room ID를 socket ID에서 찾을 수 있다면 우리가 private room을 찾은 것이다.
반대로 room ID를 socket ID에서 찾을 수 없다면 우리는 public room을 찾은 것이다.
이를 위해 우리는 Map 데이터 구조를 봐야 한다.
Map
Map은 object 같은건데, unique keys가 있다.
콘솔에서 확인해 보자.
const food = new map() //새로운 map 생성
-> undefined
food
-> Map(0) {}
food.set("pizza", 12) //food에 "pizza" 값 입력
-> Map(1) {"pizza" => 12}
food.get("pizza") //food에 저장된 "pizza" 값 가져옴
-> 12
food.get("lalala") //food에 저장되지 않은 값 불러오면 undefined 출력
-> undefined
sids는 백엔드에 연결된 모든 socket들의 map이다.
rooms도 존재한다. socket id와 room id가 같은 경우도 종종 있다.
id가 방제목인 경우 socket은 private room을 가지고 있다.
때문에 우리가 private 메시지를 보낼 수 있다.
sids에는 private room만, rooms에는 private room, public room이 다 있다.
rooms가 sids를 포함하고 있다.
그래서 public room만 얻고 싶은 경우에는 rooms에서 sids를 빼면 된다.
Map을 이용하여 public room과 private room 구별 방법
get과 key를 이용해서 key가 socket ID인지 아니면 방제목인지 알 수 있다.
sids.get(key 값)
-> key 값이 socket ID이면 private room이고 방제목이라면 public room이다.
//rooms에 있는 room들의 key값을 받아 sids에 해당 값이 없으면 public room이다.
rooms.forEach((_, key) => {
if(sids.get(key) === undefined) {
console.log(key)
}
})
Map과 Set에 대해 더 알고 싶다면 ?
아래 포스트를 확인해주세요 !
https://record-study-steadily.tistory.com/7
'Project > Zoom 클론 코딩' 카테고리의 다른 글
[Zoom Clone Coding] Map과 Set (0) | 2023.03.19 |
---|