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);