백엔드단 코드


nodejs + express 조합으로 만든 웹소켓 백엔드단 코드다.

아래에 보면 wss를 통해 http에 ws 프로토콜을 사용할 수 있게 하고

wss.on(’connection, (socket) ⇒ {}) 를 통해 웹소켓에 연결된 이후 코드들을 작성했다.

// BackEnd code

const express = require("express");
const http = require("http");
const webSocket = require("ws");
const app = express();

// view engine setup
app.set("view engine", "pug");
app.set("views", __dirname + "/views");
app.use("/public", express.static(__dirname + "/public"));

app.get("/", (req, res) => res.render("home"));

const handleListen = () =>
  console.log("Listening on <http://localhost:3000> or ws://localhost:3000");
// app.listen(3000, handleListen);

const server = http.createServer(app); // http server
const wss = new webSocket.Server({ server }); // http 서버, webSocket서버 둘 다 돌릴 수 있다.

function onSocketClose() {
  socket.on("close", () => console.log("Disconnected to Browser 🚫"));
}

function onSocketMessage(message) {
  console.log(message.toString("utf8"));
}

const sockets = []; // fake database

// websocket 연결 (백엔드)
wss.on("connection", (socket) => {
  // chrome과 연결 될 때 작동 , firefox에 연결될 때 작동 => 총 2번 작동함
  sockets.push(socket);
  // chrome이 연결되면, chrome을 sockets 배열에 넣어준다.
  // firefox가 연결되면, firefox를 sockets 배열에 넣어준다.
  socket["nickname"] = "anonymous";
  console.log("Connected to Browser ✅");
  socket.on("close", onSocketClose);
  socket.on("message", (msg) => {
    const message = JSON.parse(msg);
    switch (message.type) {
      // 받은 message type이 'message'만 브라우저에 payload를 보낸다.(li태그에 붙여넣는다)
      case "message":
        sockets.forEach((aSocket) =>
          aSocket.send(`${socket.nickname}: ${message.payload.toString()}`)
        ); // 누군가 메세지를 보내면, 모든 socket을 거치기 때문에 중복이 생김
        break;
      case "nickname":
        socket["nickname"] = message.payload; // socket nickname
    }
    // socket.send(message.toString("utf8")); // firefox 브라우저에서 보낸 메세지가 chrome에서는 보이지 않음
  });
  socket.send("Hello from the server");
});

server.listen(3000, handleListen);

프론트엔드단 코드


클라이언트가 브라우저에서 사용할 코드다. new WebSocket을 통해 ws 프로토콜의 websocket서버와 연결하고 socket에 addEventListener 로 이벤트리스너를 넣어서 사용자의 행동에 따라 서버에 어떤 요청을 보내는지 결정된다. message를 보낸다면 socket.addEventListener("message",(message) ⇒ {}){}안에 있는 코드들이 실행될 것 이다.

// FrontEnd code

const socket = new WebSocket(`ws://${window.location.host}`); // websocket 연결(프론트엔드)
const messageList = document.querySelector("ul");
const messageForm = document.querySelector("#message");
const nickForm = document.querySelector("#nick");

function makeMessage(type, payload) {
  const msg = { type, payload };
  return JSON.stringify(msg);
}

socket.addEventListener("open", () => {
  console.log("Connected to Server ✅");
});

socket.addEventListener("message", (message) => {
  //   console.log("Server Say : ", message.data);
  const li = document.createElement("li"); // li태그 생성
  li.innerText = message.data; // li 태그에 내용 넣기 <li>{message.data}</li>
  messageList.append(li); // ul태그 하위에 위에서 만든 li엘리먼트 붙이기
});

socket.addEventListener("close", () => {
  console.log("Disconnected to Server 🚫");
});

// setTimeout(() => {
//   socket.send("Hello from the browser");
// }, 1000);

function handleMessageSubmit(event) {
  event.preventDefault();
  const input = messageForm.querySelector("input");
  socket.send(makeMessage("message", input.value));
  input.value = "";
}

function handleNickSubmit(event) {
  event.preventDefault();
  const input = nickForm.querySelector("input");
  socket.send(makeMessage("nickname", input.value));
  input.value = "";
}

messageForm.addEventListener("submit", handleMessageSubmit);
nickForm.addEventListener("submit", handleNickSubmit);