ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Chat with socketIO
    Project using node.js/Cloning Catch-Mind 2020. 12. 15. 09:51

    구현할 채팅 기능은 누가 보냈는지도 알려줘야 한다. 예를 들어 나의 아이디가 clown 이고 "Hello"를 치면 상대방에게 clown : Hello가 보여야 한다. 나에게는 시스템이 clown 대신 You라고 보여줄 것이다. 각자의 아이디는 브라우저의 localStorage에 저장할 것이다.

    Server 측 통신

    // globalController.js
    
    export const notifyLogin = async (req, res) => {
      const {
        user: { id },
      } = req;
      const newUser = await User.findById(id);
      const username = newUser.username;
      io.once("connection", (socket) => {
        io.to(socket.id).emit(events.login, { username }); // 수정된 부분
        socket.broadcast.emit(events.newUser, { username }); // 추가된 부분
      });
    
      res.redirect(routes.home);
    };

      기존에는 superBroadcast로 서버에 접속한 모든 client에게 event를 보냈지만 그렇게 되면 가장 마지막에 로그인을 한 client의 username이 모든 client의 localStorage에 저장된다. 이것을 막기 위해서 로그인을 한 client에게는 io.to()와 events.login 이벤트를 이용해서 해당 client의 username만 자신의 localStorage에 저장하게 하고, 다른 client에게는 socket.broadcast.emit()을 이용해서 다른 참가자가 로그인을 했다는 것을 알린다.

    Client 측 수신

    // sockets.js
    
    export const initSocket = (aSocket) => {
      const { events } = window;
      socket = aSocket;
      socket.on(events.login, handleLogin); // 추가된 코드
      socket.on(events.newUser, handleNewuser);
      socket.on(events.newMsg, handleNewMsg);
    };

     

    // notifications.js
    
    const userNoti = (username) => {
      const text = `${username} just joined!`;
      const color = "rgb(0, 122, 255)";
    
      fireNotification(text, color);
    };
    
    export const handleNewuser = ({ username }) => {
      userNoti(username);
    };
    
    export const handleLogin = ({ username }) => {
      localStorage.setItem(USERANME, username);
      userNoti(username);
    };

      handleNewuser의 코드를 userNoti로 옮겼다. 그리고 handleLogin을 만들었다. handleLogin과 handleNewuser의 차이는 localStorage.setItem의 유무다. 즉, 로그인을 했을 때, 그 username은 사용자 보인에 localStorage에만 저장이 되고 다른 이들에게는 notification만 날라간다.

    채팅 기능

    client

    // home.pug
    
    .chat
        ul.chat__messages#jsMessages
        form.chat__form#jsSendMsg
        	input(placeholder="Write a message", type="text") 
    // chat.js
    
    import { getSocket } from "./sockets";
    
    const messages = document.getElementById("jsMessages");
    const sendMsg = document.getElementById("jsSendMsg");
    const USERNAME = "username";
    
    const appendMsg = (message, username) => {
      const li = document.createElement("li");
      li.innerHTML = `
      <span class="author ${username ? "other" : "self"}">${
        username ? username : "You"
      }:</span> ${message}
      `;
      messages.appendChild(li);
    };
    
    const handleSendMsg = (e) => {
      e.preventDefault();
      const input = sendMsg.querySelector("input");
      const { value } = input;
      let username = localStorage.getItem(USERNAME);
      getSocket().emit(window.events.sendMsg, {
        message: value,
        username,
      });
      input.value = "";
      appendMsg(value);
    };
    
    export const handleNewMsg = ({ message, username }) => {
      appendMsg(message, username);
    };
    
    if (sendMsg) {
      sendMsg.addEventListener("submit", handleSendMsg);
    }

      message를 입력하고 전송하였을 때, 바로 자신의 화면에 메시지를 생성하고, 상대방에게도 전송한다. handleSendMsg가 message를 process하고 appendMsg를 통해서 메시지를 생성한다. 그리고 getSocket().emt()을 이용해서 서버를 통해서 다른 client들에게 메시지를 보낸다. 서버가 메시지를 전송한 client로부터 메시지를 수신하면 나머지 client 들에게 메시지를 전송하는데 이를 처리하는 함수가 handleNewMsg()다.

    server

    // socketController.js
    
    import events from "./events";
    
    export const socketController = (socket, io) => {
      const broadcast = (event, data) => socket.broadcast.emit(event, data);
      socket.on(events.sendMsg, ({ message, username }) => {
        broadcast(events.newMsg, { message, username });
      });
    };

    Client로부터 events.sendMsg 이벤트를 수신하면 메시지를 전송한 client를 제외한 clients에게 메시지를 전송한다.

    소스 코드

    github.com/zpskek/guessMind-v3/commit/a136c452b5fcd978b3b85c26428ecbb3f5407ede

    CSS : github.com/zpskek/guessMind-v3/commit/8a3fcb5ff3297c6e1a179e0e07d0abc30dc57a7a

    'Project using node.js > Cloning Catch-Mind' 카테고리의 다른 글

    Fill the canvas with socketIO  (0) 2020.12.17
    Drawing canvas with socketIO  (0) 2020.12.15
    socket.io로 로그인 알리기  (0) 2020.12.14
    Client가 서버의 변수 공유하기  (0) 2020.12.14
    gulp  (0) 2020.12.14

    댓글

Designed by Tistory.