내배캠 63일차

·2023년 1월 16일
0

내일배움캠프

목록 보기
67/142
post-thumbnail

노마드코더 줌 클론 코딩 주소
사용한 github주소

2.4-Rooms

socket.id/rooms

src/server.js

=>결과

  • 첫번째 console.log(socket.rooms)의 결과값은 socket.id
    유저는 기본적으로 자기 id와 같은 방에 혼자 입장해있음!(user와 server사이의 private room)

enter room

  • 방에 입장하면 방 입력하는 폼을 숨기고 채팅 폼을 보여주도록
  • 방에 입장했을때 방 이름을 보여주도록
  1. home.pug에 room div를 생성해준다.
div#room 
  h3 
  ul 
  form 
    input(placeholder="message", required, type="text")
    button Send 
  1. app.js에서 만들어준 room div를 불러와서 방에 입장전에는 숨겨둔다. roomName도!
const room = document.getElementById("room");

// 방에 입장 전엔 숨겨주기
room.hidden = true;
// 입장 전엔 roomName empty
let roomName;
  1. app.js에 room을 입력한 후에 입력폼을 숨기고 채팅폼을 보여주고, 만들어둔 h3태그에 방이름을 넣어주는 function을 만들고 back(server.js)에서 실행시켜준다.

app.js

//app.js
function showRoom() {
  welcome.hidden = true;
  room.hidden = false;
  // 방 이름 보여주기
  const h3 = room.querySelector("h3");
  h3.innerText = `Room ${roomName}`;
}

function handleRoomSubmit(event) {
  event.preventDefault();
  const input = form.querySelector("input");
  //socket.send와 같은 역할
  socket.emit("enter_room", input.value, showRoom);
  roomName = input.value;
  input.value = "";
}

server.js

//server.js
socket.on("enter_room", (roomName, done) => {
  socket.join(roomName);
  //showRoom()
  done();
});

2.5-room message

enter message

들어간 방에 있는 나를 제외한 모든 사람들에게 입장했다는 메시지를 보내고 싶음!

  1. server.js에서 방에 입장했을때 welcome이벤트를 나를 제외한 방의 모든 사람들에게 emit해준다.
socket.on("enter_room", (roomName, done) => {
  socket.join(roomName);
  done();
  // 입장메시지 보내기
  socket.to(roomName).emit("welcome");
  });
  1. app.js에서 화면에 메시지 리스트를 추가해줄 함수를 만들어준다.
    서버에서 welcome이벤트를 받을때 addMessage함수를 사용해서 나를 제외한 모든 이에게 메시지를 보여준다.
function addMessage(message) {
  const ul = room.querySelector("ul");
  const li = document.createElement("li");
  li.innerText = message;
  ul.appendChild(li);
}

//welcome이벤트를 받으면 함수실행
socket.on("welcome", () => {
  // 나를 제외한 모든 이에게
  addMessage("Someone Joined!");
});

left message

방을 떠날때 메시지를 주고 나가고 싶음 => disconnecting

  1. server.js에서 socketIO의 이벤트 중 하나인 disconnecting을 이용해서 방을 떠날때 bye이벤트를 보낸다
  // 연결 끊을때 - 모든 방에 bye 이벤트 보내기
  socket.on("disconnecting", () => {
    socket.rooms.forEach((room) => socket.to(room).emit("bye"));
  });
  1. app.js에서 bye이벤트를 받았을때 누군가 떠났다는 메시지를 추가한다.
socket.on("bye", () => {
  addMessage("Someone Left ㅠㅠ");
});

2.6-Room Notification

서로에게 메시지를 보내고 싶음. 내가 보낼 때는 you:를 붙여서 보여주고싶음!

  1. app.js에서 #room안의 form이 보내질때 submit event를 발생시키고 실행할 함수도 넣어준다.
function showRoom() {
  welcome.hidden = true;
  room.hidden = false;
  // 방 이름 보여주기
  const h3 = room.querySelector("h3");
  h3.innerText = `Room ${roomName}`;
  // submit이벤트가 발생하면 handleMessageSubmit실행
  const form = room.querySelector("form");
  form.addEventListener("submit", handleMessageSubmit);
}
  1. app.js에서 실행할 함수를 만들어 준다.
    입력받은 값을 가져와서 new_message이벤트와 받은 값, 방이름을 서버로 보내준다.
    이때 입력하는 사람에게 자신이 입력한 메시지를 보여주는 함수도 같이 보내준다.
function handleMessageSubmit(event) {
  event.preventDefault();
  const input = room.querySelector("input");
  const value = input.value;
  socket.emit("new_message", input.value, roomName, () => {
    addMessage(`You: ${value}`);
  });
  input.value = "";
}
  1. server.js에서 내가 보낸 메세지를 다른 사람들도 볼 수 있도록 나를 제외한 모두에게 이벤트를 발생시켜준다.
socket.on("new_message", (msg, room, done) => {
  socket.to(room).emit("new_message", msg);
  done();
});
  1. app.js에서 이벤트를 받으면 메세지가 프론트에 뜨는 함수를 실행시켜준다.
socket.on("new_message", addMessage);

2.7-nickname

nickname입력폼을 추가해야해서 id값도 넣어주고 eventListener도 추가해주고,

  1. home.pug에 form추가
form#name 
  input(placeholder="nickname", required, type="text")
  button Save 
form#msg
  input(placeholder="message", required, type="text")
  button Send 
  1. app.js에 있던 msg관련 수정과 nickname추가
function handleMessageSubmit(event) {
  event.preventDefault();
  const input = room.querySelector("#msg input");
  const value = input.value;
  socket.emit("new_message", input.value, roomName, () => {
    addMessage(`You: ${value}`);
  });
  input.value = "";
}

function handleNicknameSubmit(event) {
  event.preventDefault();
  const input = room.querySelector("#name input");
  socket.emit("nickname", input.value);
}

function showRoom() {
  welcome.hidden = true;
  room.hidden = false;
  // 방 이름 보여주기
  const h3 = room.querySelector("h3");
  h3.innerText = `Room ${roomName}`;

  const msgForm = room.querySelector("#msg");
  const nameForm = room.querySelector("#name");
  msgForm.addEventListener("submit", handleMessageSubmit);
  nameForm.addEventListener("submit", handleNicknameSubmit);
}
  1. 들어올 때, 나갈 때, 메시지 보낼 때 nickname을 이제 넣어줄 수 있게 됨.

server.js

wsServer.on("connection", (socket) => {
  socket["nickname"] = "unknown";
  // onAny : middleware같은거, 어떤 event에서든지 console.log가능
  socket.onAny((event) => {
    console.log(`Socket Event:${event}`);
  });
  //socket.on("message")사용안함. 우리가 원하는 이벤트로 사용가능
  socket.on("enter_room", (roomName, done) => {
    socket.join(roomName);
    //showRoom()호출
    done();
    // 입장메시지 보내기(welcome이벤트를 나를 제외한 방의 모든 사람들에게 emit)
    socket.to(roomName).emit("welcome", socket.nickname);
  });
  // 연결 끊을때 - 모든 방에 bye 이벤트 보내기
  socket.on("disconnecting", () => {
    socket.rooms.forEach((room) =>
      socket.to(room).emit("bye", socket.nickname)
    );
  });
  socket.on("new_message", (msg, room, done) => {
    socket.to(room).emit("new_message", `${socket.nickname}: ${msg}`);
    done();
  });
  socket.on("nickname", (nickname) => (socket["nickname"] = nickname));
});

app.js

socket.on("welcome", (user) => {
  addMessage(`${user} Joined!`);
});

socket.on("bye", (left) => {
  addMessage(`${left} Left ㅠㅠ`);
});


  • wsServer.socketJoin("announcement");
    : socket이 연결되었을때 모든 socket이 anonouncement 방에 입장!

2.8-Count User1

adapter : 다른 서버들 사이에 실시간 어플리케이션을 동기화

console.log(wsServer.sockets.adapter);

public room

server.js

function publicRooms() {
  const sids = wsServer.sockets.adapter.sids;
  const rooms = wsServer.sockets.adapter.rooms;
  const publicRooms = [];
  rooms.forEach((_, key) => {
    if (sids.get(key) === undefined) {
      publicRooms.push(key);
    }
  });
  return publicRooms;
}

이렇게도 가능 =>

2.9-Count User2

server.sockets.emit을 사용해서 message(방 목록)를 모두에게 보내줄 것

server.js

socket.on("enter_room", (roomName, done) => {
    socket.join(roomName);
    //showRoom()호출
    done();
    // 입장메시지 보내기(welcome이벤트를 나를 제외한 방의 모든 사람들에게 emit)
    socket.to(roomName).emit("welcome", socket.nickname); // 하나의 소켓에
    wsServer.sockets.emit("room_change", publicRooms()); // 모든 소켓에
  });
socket.on("disconnect", () => {
    wsServer.sockets.emit("room_change", publicRooms());
  });

home.pug

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

app.js

socket.on("room_change", (rooms) => {
  const roomList = welcome.querySelector("ul");
  //방목록을 항상 비워주기! 그래야 전에 것이 또 추가가 안됨!
  roomList.innerHTML = "";
  if (rooms.length === 0) {
    return;
  }
  rooms.forEach((room) => {
    const li = document.createElement("li");
    li.innerText = room;
    roomList.append(li);
  });
});

+두 개가 같음 =>

2.10-User count

set.size를 이용해서 유저 수를 가져올것

server.js

// count room user
function countRoom(roomName) {
  // roomName을 찾지 않을 수도 있어서 ?
  return wsServer.sockets.adapter.rooms.get(roomName)?.size;
}

...

socket.on("enter_room", (roomName, done) => {
    socket.join(roomName);
    //showRoom()호출
    done();
    // 입장메시지 보내기(welcome이벤트를 나를 제외한 방의 모든 사람들에게 emit)
    socket.to(roomName).emit("welcome", socket.nickname, countRoom(roomName)); // 하나의 소켓에
    wsServer.sockets.emit("room_change", publicRooms()); // 모든 소켓에
  });
  // 연결 끊을때 - 모든 방에 bye 이벤트 보내기
  socket.on("disconnecting", () => {
    socket.rooms.forEach((room) =>
      socket.to(room).emit("bye", socket.nickname, countRoom(room) - 1) // 아직 확실하게 떠나기 전이라서
    );
  });

app.js

socket.on("welcome", (user, newCount) => {
  const h3 = room.querySelector("h3");
  h3.innerText = `Room ${roomName} (${newCount})`;
  addMessage(`${user} Joined!`);
});

socket.on("bye", (left, newCount) => {
  const h3 = room.querySelector("h3");
  h3.innerText = `Room ${roomName} (${newCount})`;
  addMessage(`${left} Left ㅠㅠ`);
});

profile
개발자 꿈나무

0개의 댓글