๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

javascript/์คŒ ํด๋ก ์ฝ”๋”ฉ

DAY 2 #1.3 ~ 1.9

 

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

 

 

์™ผ : chrome / ์˜ค : microsoft edge

 

์•„์ง๊นŒ์ง€๋Š” ๋ธŒ๋ผ์šฐ์ €์™€ ์„œ๋ฒ„๊ฐ€ ๋‹จ๋…์ ์œผ๋กœ ์†Œํ†ตํ•  ๋ฟ, ๋ธŒ๋ผ์šฐ์ €์™€ ๋ธŒ๋ผ์šฐ์ €๊นŒ์ง€์˜ ์†Œํ†ต์€ ํ•  ์ˆ˜ ์—†๋Š”๋ฐ, ๋•Œ๋ฌธ์— ์•„์ง ์ฑ„ํŒ…์˜ ๊ธฐ๋Šฅ์„ ์ œ๋Œ€๋กœ ํ•˜์ง€ ๋ชปํ•˜๊ณ  ์žˆ๋‹ค.

 

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์ธ ๊ฒƒ๋„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

 

์™ผ์ชฝ : parsed, ์˜ค๋ฅธ์ชฝ : message

 

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

 

์™ผ : ํฌ๋กฌ / ์˜ค : edge

 

์ƒˆ๋กœ์šด ๋‹‰๋„ค์ž„์œผ๋กœ ๊ณ ์ณ์„œ 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