#1.3 WebSocket Events
https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/WebSocket
app.js
// ์ด socket์ ์ด์ฉํด์ frontend์์ backend๋ก ๋ฉ์ธ์ง ์ ์ก ๊ฐ๋ฅ
// ์ฌ๊ธฐ socket์ ์๋ฒ๋ก์ ์ฐ๊ฒฐ๋ก, window.location.host๋ pc๋ฟ๋ง ์๋ ๋ชจ๋ฐ์ผ์์๋ ์ ์์ด ๊ฐ๋ฅํ๊ฒ๋ ํด์ค
// (http://localhost:3000์ด ์๋, ์์ ๊ธฐ๊ธฐ์ host์ location์ผ๋ก ์ ์)
const socket = new WebSocket(`ws://${window.location.host}`);
webSocket ์ฌ์ฉ
- server : node.js ํ๊ฒฝ์์ ws์ ๊ฐ์ ๋ชจ๋์ ์ด์ฉํด webSocket server๋ฅผ ์์ฑ (server.js)
=> server.js์์๋ {WebsocketServer} ๋ฅผ ws๋ชจ๋๋ก๋ถํฐ import
- client(browser) : browser์ ๋ด์ฅ๋ api๋ฅผ ์ด์ฉํด webSocet ๊ฐ์ฒด ์ฐ์ ์์ฑ (app.js)
=> app.js ์์๋ node.js์ ๋ด์ฅ๋ Websocket instance๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ฏ๋ก import ํ์ X
* server.js์ socket = ์ฐ๊ฒฐ๋ browser
* app.js์ socket = server๋ก์ ์ฐ๊ฒฐ
#1.4 WebSocket Messages
webSocket๋ js์ฒ๋ผ function๊ณผ event๊ฐ ์์ผ๋ฉฐ, browser์์์ event๋ click, submit, wifi on/off ๋ฑ์ด ์๋ค.
server.js
wss.on("connection", (socket)=>{
console.log("Connected to Browser");
socket.send("hello");
});
app.js
const socket = new WebSocket(`ws://${window.location.host}`);
// ---- ํน์ ์ด๋ฒคํธ ๋ฐ์ ์ ์คํ๋๋ ์ฝ๋ฐฑ ํจ์ ----
// ์๋ฒ๊ฐ open(์ฐ๊ฒฐ๋จ)์ผ ๋
socket.addEventListener("open", ()=>{
console.log("Connected to Server");
})
// ๋ฉ์์ง๊ฐ ๋์ฐฉํ๋ฉด ๋ฉ์์ง๋ฅผ console์ ์ถ๋ ฅ
socket.addEventListener("message", (message)=>{
console.log("Just got this : ", message.data, " from the server");
})
// ์๋ฒ๊ฐ close(ํด์ )์ผ ๋
socket.addEventListener("close", () =>{
console.log("Disconnected from server");
})
// 10์ด ๋ค backend๋ก message ๋ณด๋
setTimeout(() => {
socket.send("hello from the browser.");
}, 10000);
server.js์ socket.send(); ์ app.js์ socket.addEventListener("message"~~~ ๊ฐ ์ฐ๊ฒฐ๋์ด socket์ message ์ด๋ฒคํธ๋ฅผ ์ถ๊ฐํ ์ ์๋ค.
server.js ์ถ๊ฐ ์์
// on method์์๋ event๊ฐ ๋ฐ๋๋๋ ๊ฒ์ ๊ธฐ๋ค๋ฆฐ๋ค
// event๊ฐ connection / ๋ค์ ์ค๋ ํจ์๋ event๊ฐ ์ผ์ด๋๋ฉด ์๋
// ๊ทธ๋ฆฌ๊ณ on method๋ backend์ ์ฐ๊ฒฐ๋ ์ฌ๋์ ์ ๋ณด๋ฅผ ์ ๊ณต - ๊ทธ๊ฒ socket์์ ์ด
// ์ต๋ช
ํจ์๋ก ๋ฐ๊พธ๊ธฐ
wss.on("connection", socket => { // ์ฌ๊ธฐ์ socket์ด๋ผ๋ ๋งค๊ฐ๋ณ์๋ ์๋ก์ด ๋ธ๋ผ์ฐ์ (wss๋ ์ ์ฒด ์๋ฒ, socket์ ํ๋์ ์ฐ๊ฒฐ
console.log("Connected to Browser โ
");
socket.on("close", () => console.log("Disconnected to Server โ")); // ์๋ฒ๋ฅผ ๋๋ฉด ๋์
socket.on("message", message => {
const messageString = message.toString("utf8"); // ๋ฒํผ ํํ๋ก ์ ๋ฌ๋๊ธฐ ๋๋ฌธ์ toString ๋ฉ์๋๋ฅผ ์ด์ฉํด์ utf8๋ก ๋ณํ ํ์
console.log(messageString);
}); // ํ๋ก ํธ์๋๋ก๋ถํฐ ๋ฉ์์ง๊ฐ ์ค๋ฉด ์ฝ์์ ์ถ๋ ฅ
socket.send("hello!!!"); // hello ๋ฉ์์ง ๋ณด๋ด๊ธฐ - send๋ socket์ ์ ์ก์ฉ ๋ฉ์๋
}) // socket์ callback์ผ๋ก ๋ฐ๋๋ค! webSocket์ ์๋ฒ์ ๋ธ๋ผ์ฐ์ ์ฌ์ด์ ์ฐ๊ฒฐ
#1.6 Chat Completed
home.pug
main
//- ul : message list(js๋ฅผ ์ด์ฉํด ์ฑ์์ง ์์ ..)
ul
form
input(type="text", placeholder="write a msg", required)
button Send
form : ๋ฉ์์ง๋ฅผ ๋ณด๋ด๋ ํผ
ul : ๋ฉ์์ง ๋ฆฌ์คํธ
app.js
const messageList = document.querySelector("ul");
const messageForm = document.querySelector("form");
function handleSumbit(event){
event.preventDefault();
const input = messageForm.querySelector("input");
// input์ value์ ๊ฐ์ front-end์ form์์ back-end๋ก ๋ณด๋
socket.send(input.value);
// input ๊ฐ ์ด๊ธฐํ
input.value = "";
}
messageForm.addEventListener("submit", handleSumbit);
์์ง๊น์ง๋ ๋ธ๋ผ์ฐ์ ์ ์๋ฒ๊ฐ ๋จ๋ ์ ์ผ๋ก ์ํตํ ๋ฟ, ๋ธ๋ผ์ฐ์ ์ ๋ธ๋ผ์ฐ์ ๊น์ง์ ์ํต์ ํ ์ ์๋๋ฐ, ๋๋ฌธ์ ์์ง ์ฑํ ์ ๊ธฐ๋ฅ์ ์ ๋๋ก ํ์ง ๋ชปํ๊ณ ์๋ค.
server.js
function onSocketClose() {
console.log("Disconnected from the Browser โ");
}
// ๋๊ตฐ๊ฐ ์ฐ๋ฆฌ ์๋ฒ์ ์ฐ๊ฒฐ๋์์ ๋ connection์ ๋ด์ ๋ณ์.
const sockets = [];
wss.on("connection", (socket) => {
sockets.push(socket);
socket.on("close", onSocketClose);
socket.on("message", (message) => {
const messageString = message.toString("utf8");
// ์ฐ๊ฒฐ๋ ๋ชจ๋ socket์ message๋ฅผ ์ ๋ฌํ๋ค.
sockets.forEach((aSocket) => aSocket.send(messageString));
});
});
socket์ ๋ธ๋ผ์ฐ์ ์ ๋งค๊ฐ๋ณ์์ด๋ฉฐ ๋ง์ฝ chrome์ผ๋ก ์ ์ํ๋ค๋ฉด sockets์ chrome์ด push๋ ๊ฒ์ด๊ณ , ์ด์ ๋ฉ์์ง๋ฅผ ๋ณด๋ธ๋ค๋ฉด ๋ชจ๋ socket์ ๋ฉ์์ง๊ฐ ์ ๋ฌ ๋ ๊ฒ์ด๋ค.
#1.7~1.8 Nicknames
app.js
// browser์ li ํ๊ทธ๋ฅผ ๋ง๋ค์ด ๊ทธ ์์ ๋ฉ์์ง๋ฅผ ๋ฃ๊ณ , ๊ทธ liํ๊ทธ๋ฅผ ul์ ์์์ผ๋ก ๋ฃ๋๋ค.
socket.addEventListener("message", (message) => {
const li = document.createElement("li");
li.innerText = message.data;
messageList.append(li);
});
์ง๊ธ์ ์ฝ๋๋ ๋ธ๋ผ์ฐ์ ๋ผ๋ฆฌ ์๋ก ์ฐ๊ฒฐ๋ ์ํ๋ผ๋ ์ฑํ ์ผ๋ก ์ด๋ ๋ธ๋ผ์ฐ์ ์์ ์ด๋ค ์ฑํ ์ ๋ณด๋๋์ง๋ ์ ์ ์๋ ์ํ๋ค. ๋๋ฌธ์ ๋๋ค์ form์ ํ๋ ๋ง๋ค๊ณ , ๋๋ค์ ๋ฑ๋ก์ ํ ๊ฒ์ด๋ค.
๊ทธ๋ฌ๋ back-end๋ ์ด message๋ค์ ๊ตฌ๋ณํ ์ ์๋ค. ์ด๊ฒ ๋๋ค์์ ๋ฑ๋กํ๊ธฐ ์ํ message์ธ์ง chat์ ํ๋ message์ธ์ง ๊ตฌ๋ณํ๊ธฐ ์ํด message type์ ๋ง๋ค์ด ์ค ๊ฒ์ด๊ณ , ๊ทธ๋์ form ํ๊ทธ์ id๋ฅผ ๋ถ์ฌํด์ค๋ค.
home.pug
main
form#nick
input(type="text", placeholder="choose a nickname", required)
button Save
ul
form#message
input(type="text", placeholder="write a msg", required)
button Send
๊ทธ๋ฆฌ๊ณ ์๋ฒ๊ฐ ๊ฐ message์ type์ ๊ตฌ๋ถํ ์ ์๋๋ก JSON ํ์์ ์ฌ์ฉํ ๊ฑด๋ฐ, ์๋ฒ๋ String ๊ฐ๋ง ๋ฐ์๋ค์ด๋ฏ๋ก JSON.stringfy๋ฅผ ์ฌ์ฉํด string ๊ฐ์ผ๋ก ๋ฐ๊ฟ์ค๋ค.
๋ณํํ์ง ์์ผ๋ฉด javascript object ํํ๋ก ์ถ๋ ฅ๋๋๋ฐ, ์ด๋ฅผ string ๊ฐ์ผ๋ก ๋ณํํ๋ ์ด์ ์ค ๋ค๋ฅธ ํ๋๋
์ง๊ธ ์ค์ต์์๋ js๋ฅผ ์ด์ฉํ์ง๋ง ์ ์ํ ๋๊ตฐ๊ฐ๋ go๋ฅผ ์ด์ฉํ ์๋ ์๊ณ , java๋ฅผ ์ด์ฉํ ์๋ ์๊ธฐ ๋๋ฌธ์ string ํํ๋ก ๋ณํํด ๋ชจ๋ ์ธ์ด์ ๋๋นํ๊ธฐ ์ํด์์ด๊ธฐ๋ ํ๋ค.
app.js
const messageList = document.querySelector("ul");
const messageForm = document.querySelector("#message");
const nickForm = document.querySelector("#nick");
const socket = new WebSocket(`ws://${window.location.host}`);
// --- ์๋ต ---
// JSON์ string์ผ๋ก ๋ฐ๊ฟ์ฃผ๋ ํจ์
function makeMessage(type, payload) {
const msg = { type, payload };
return JSON.stringify(msg);
}
function handleNickSubmit(event){
event.preventDefault();
const input = nickForm.querySelector("input");
socket.send(input.value);
input.value = "";
}
messageForm.addEventListener("submit", handleSumbit);
nickForm.addEventListener("submit", handleNickSubmit);
์ด์ ์๋ฒ๋ก ๋์์์,
์๋ฒ์์๋ ๋ฐ์์จ String ํํ์ ๋ฉ์์ง๋ฅผ ๋ค์ JSON ํํ๋ก ๋ฐ๊พธ๊ณ , ํค ๊ฐ์ ๋ฐ๋ผ ๋ค๋ฅด๊ฒ ๋์ํ๋๋ก ๋ง๋ค์ด์ผ ํ๋ค.
server.js
wss.on("connection", (socket) => {
// --- ์๋ต ---
socket.on("message", (message) => {
const messageString = message.toString("utf8");
const parsed = JSON.parse(messageString);
console.log(parsed, messageString)
sockets.forEach((aSocket) => aSocket.send(messageString));
});
});
์ค์ ๋ก ์ ์ฝ๋๋๋ก parsedํ message์ ์ํ message๋ฅผ ๋น๊ตํ์ ๋, ์๋์ ๊ฐ์ ์ฐจ์ด๋ฅผ ๋ฐ๊ฒฌํ ์ ์๋ค. ๊ฒ๋ค๊ฐ ์ค์ ๋ก ์ฐ๋ฆฌ๊ฐ ํ๋ฉด์ ๋ณด์ฌ์ฃผ๊ณ ์ถ์ ๊ฒ์ parsed.payload์ธ ๊ฒ๋ ํ์ธํ ์ ์์๋ค.
wss.on("connection", (socket) => {
sockets.push(socket);
socket["nickname"] = "Anonymous"; // ์ต๋ช
์์ผ์ธ ๊ฒฝ์ฐ ์ฒ๋ฆฌ - ๋งจ ์ฒ์ ๋๋ค์์ Anonymous
console.log("Connected to Browser โ
");
socket.on("close", onSocketClose);
socket.on("message", (msg) => {
// parse ํ ๊ฒฝ์ฐ ๊ธ์๊ฐ ์ ๋๋ก ์ ๋์์ ์๋์ ๊ณผ์ ์ด ํ์ ์๊ฒ ๋จ...
// const msgString = msg.toString("utf8");
// const message = JSON.parse(msgString);
const message = JSON.parse(msg);
// new_message์ผ ๋ ๋ชจ๋ ๋ธ๋ผ์ฐ์ ์ payload๋ฅผ ์ ์ก
// ๋ฐ์์จ String ํํ์ ๋ฉ์์ง๋ฅผ parse๋ก ํ์ฑํ ํ ๊ตฌ๋ถํด์ ์ถ๋ ฅ
switch(message.type){
case "new_message":
sockets.forEach((aSocket) => aSocket.send(`${socket.nickname}: ${message.payload}`));
break;
case "nickname":
// socket์ ๊ธฐ๋ณธ์ ์ผ๋ก ๊ฐ์ฒด๋ผ ์๋ก์ด ์์ดํ
์ถ๊ฐ ๊ฐ๋ฅ.
// ๋๋ค์์ socket ํ๋กํผํฐ์ ์ ์ฅํ๋ค.
socket["nickname"] = message.payload;
break;
}
});
});
์๋ก์ด ๋๋ค์์ผ๋ก ๊ณ ์ณ์ save๋ฅผ ๋๋ฅด๋ฉด, ๋๋ค์๋ ๋ณ๊ฒฝํ ์ ์๊ฒ ๋๋ค.
์์ฑ๋ ์ฝ๋
server.js
import http from "http";
import WebSocket from "ws";
import express from "express";
const app = express();
app.set("view engine", "pug");
app.set("views", __dirname + "/views");
app.use("/public", express.static(__dirname + "/public"));
app.get("/", (_, res) => res.render("home"));
app.get("/*", (_, res) => res.redirect("/"));
const handleListen = () => console.log(`Listening on http://localhost:3000`);
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });
function onSocketClose() {
console.log("Disconnected from the Browser โ");
}
// ๋๊ตฐ๊ฐ ์ฐ๋ฆฌ ์๋ฒ์ ์ฐ๊ฒฐ ๋์ ๋, sockets์ ๋ด๊ฒจ์ง๋ค.
const sockets = [];
wss.on("connection", (socket) => {
sockets.push(socket);
socket["nickname"] = "Anon"; // ๋๋ค์์ ์ ํ์ง ์์ ์ฌ๋๋ค์ ์ํจ
console.log("Connected to Browser โ
");
socket.on("close", onSocketClose);
socket.on("message", (msg) => {
const message = JSON.parse(msg);
switch (message.type) {
case "new_message":
sockets.forEach((aSocket) =>
aSocket.send(`${socket.nickname}: ${message.payload}`)
);
break;
case "nickname":
socket["nickname"] = message.payload;
}
});
});
server.listen(3000, handleListen);
app.js
const messageList = document.querySelector("ul");
const messageForm = document.querySelector("#message");
const nickForm = document.querySelector("#nick");
const socket = new WebSocket(`ws://${window.location.host}`);
function makeMessage(type, payload) {
const msg = { type, payload };
return JSON.stringify(msg);
}
socket.addEventListener("open", () => {
console.log("Connected to Server");
});
socket.addEventListener("message", (message) => {
const li = document.createElement("li");
li.innerText = message.data;
messageList.append(li);
});
socket.addEventListener("close", () => {
console.log("Disconnected from server");
});
function handleSubmit(event) {
event.preventDefault();
const input = messageForm.querySelector("input");
socket.send(makeMessage("new_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", handleSubmit);
nickForm.addEventListener("submit", handleNickSubmit);
home.pug
doctype html
html(lang="en")
head
meta(charset="UTF-8")
meta(http-equiv="X-UA-Compatible", content="IE=edge")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
title Noom
//- mvp.css ์ฌ์ฉ
link(rel="stylesheet", href="https://unpkg.com/mvp.css")
body
header
h1 Noom
main
form#nick
input(type="text", placeholder="choose a nickname", required)
button Save
ul
form#message
input(type="text", placeholder="write a msg", required)
button Send
script(src="/public/js/app.js")
'javascript > ์ค ํด๋ก ์ฝ๋ฉ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
DAY 3 #2.0 ~ #2.3 (0) | 2023.02.24 |
---|---|
DAY 1 #0.2 ~ #1.2 (0) | 2023.02.21 |