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

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

DAY 1 #0.2 ~ #1.2

 

ํ”„๋ก ํŠธ, ๋ฐฑ์—”๋“œ ์ค€๋น„๋ฅผ ์œ„ํ•ด ๋ฏธ๋ฆฌ 0.0~0.4๋ฅผ ๋“ค์–ด์•ผํ•œ๋‹ค...

์•ˆ๋“ค์—ˆ๋‹ค๊ฐ€ ์ง€๊ธˆ 1์‹œ๊ฐ„์งธ ํ—›ํƒ•์ณค๋‹ค... 

https://ssocoit.tistory.com/188 ์ฐธ๊ณ 

 

 

 

#0.2 server Setup

 

https://www.npmjs.com/package/ws

 

๋จผ์ € node, ws, express, pug ์„ค์น˜

๋‚˜๋Š” ์ด๋ฏธ ๋…ธ๋“œ๋Š” ์„ค์น˜๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ ๋‚˜๋จธ์ง€ ์„ธ๊ฐœ๋งŒ ์ถ”๊ฐ€๋กœ ์„ค์น˜ํ•จ.. 

npm i ws
npm i express
npm i pug

 

github์— ์˜ฌ๋ฆฐ๋‹ค๋ฉด readme ํŒŒ์ผ๋„ ์ถ”๊ฐ€๋กœ ์ƒ์„ฑํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค. 

ํ„ฐ๋ฏธ๋„์— npm init-y ๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ๋ญ”๊ฐ€ ์žˆ์–ด๋ณด์ด๋Š” ๊ธฐ๋ณธ package.json ํŒŒ์ผ์„ ์ž‘์—…ํ•ด์ค€๋‹ค. ๊ฑฐ๊ธฐ์— ์ถ”๊ฐ€๋กœ ๋ง๋ถ™์ด๊ณ  ์‹ถ์€ ๋‚ด์šฉ์„ ์ž‘์„ฑํ•˜๋ฉด ๋œ๋‹ค.

nodemon๊ณผ babel์„ ์‚ฌ์šฉํ• ๊ฒƒ์ด๋‹ˆ ํ„ฐ๋ฏธ๋„์— ์„ค์น˜ ๋ช…๋ น์„ ์ž…๋ ฅํ•œ๋‹ค.

npm i @babel/core @babel/cli @babel/node -D
npm i nodemon -D 
npm i @babel/preset-env -D

 

๊ทธ๋ฆฌ๊ณ  babel.config.json, nodemon.json์ด๋ผ๋Š” ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด์ค€๋‹ค.

 

nodemon.json

ignore์€ ํ•ด๋‹น ํด๋”์™€ ๊ทธ ์•ˆ์— ์žˆ๋Š” ๋ชจ๋“  ํŒŒ์ผ์„ ๋ฌด์‹œํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค. public ํด๋” ๋‚ด์˜ ํŒŒ์ผ์ด ์ˆ˜์ •๋˜์–ด๋„ nodemon์ด ์žฌ์‹œ์ž‘๋˜์ง€ ์•Š๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

{
  "ignore": ["src/public/*"],
  "exec": "babel-node src/server.js"
}

 

babel.config.json

{
  "presets": ["@babel/preset-env"]
}

 

 

src ํด๋”๋ฅผ ๋”ฐ๋กœ ๋งŒ๋“ค์–ด ์—ฌ๊ธฐ์— server.js ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด์ค€๋‹ค.

 

์™„์„ฑ๋œ package.json

{
  "dependencies": {
    "express": "^4.18.2",
    "node": "^19.6.0",
    "pug": "^3.0.2",
    "ws": "^8.12.1"
  },
  "scripts": {
    "dev": "nodemon",
    "start": "node server.js"
  },
  "name": "zoom_clonecoding",
  "version": "1.0.0",
  "main": "server.js",
  "devDependencies": {
    "@babel/cli": "^7.21.0",
    "@babel/core": "^7.21.0",
    "@babel/node": "^7.20.7",
    "@babel/preset-env": "^7.20.2",
    "nodemon": "^2.0.20"
  },
  "keywords": [],
  "author": "",
  "license": "hykim",
  "description": "zoom cloneCoding using NodeJS, WebRTC and WebSockets"
}

 

server.js์—์„œ ์„œ๋ฒ„ ํ…Œ์ŠคํŠธ

import express from "express";

const app = express();
console.log("hello");
app.listen(3000);

 

์„œ๋ฒ„ ์‹คํ–‰๋ฌธ

npm run dev

 

localhost:3000 ์— ์ ‘์†ํ–ˆ์„ ๋•Œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋œฌ๋‹ค๋ฉด ์ ‘์† ์„ฑ๊ณต!

 

 

#0.3 Frontend Setup

 

๋‚˜๋Š” ๊ทธ๋ž˜๋„ ์•„์ง๊นŒ์ง€ html์— ๋งŽ์ด ๊ธธ๋“ค์—ฌ์ ธ์žˆ์–ด์„œ pug๋Š” ์ •๋ง ์ ์‘์ด ์•ˆ๋˜๋Š”๋ฐ... ์“ด๋‹ค๋‹ˆ ๋ญ ์จ๋ด์•ผ์ง€

๊ทธ๋ฆฌ๊ณ  pug ํŒŒ์ผ์„ ์˜ˆ์˜๊ฒŒ ๊พธ๋ฉฐ์ค„ ์ˆ˜ ์žˆ๋„๋ก mvp.css๋ฅผ ์ด์šฉํ•œ๋‹ค.

 

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 
            h2 Welcome to Noom
        script(src="/public/js/app.js")

 

server.js

import express from "express";

// <---- express ์„œ๋ฒ„ ์ค€๋น„

const app = express();

// pug ํŽ˜์ด์ง€๋ฅผ rendering ํ•˜๊ธฐ ์œ„ํ•จ
app.set('view engine', 'pug');
// views directory๊ฐ€ src ์•ˆ์— ์žˆ์œผ๋ฏ€๋กœ
app.set('views', __dirname + "/views");
// public ํด๋” ๋‚ด์˜ jsํŒŒ์ผ์ด๋‚˜ cssํŒŒ์ผ์— ์ ‘๊ทผํ•˜๋„๋ก
app.use("/public", express.static(__dirname + "/public"));
// home์œผ๋กœ ๊ฐ€๋ฉด req, res๋ฅผ ๋ฐ›๊ณ  res.render (์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“  home์„ render)ํ•˜๋Š” route
app.get("/", (req, res) => res.render("home"));

// ---->

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

 

์ด๋ ‡๊ฒŒ ๋œจ๋ฉด ์„ฑ๊ณต,

 

 

 

#1.0 Introduction

 

๋งŒ๋“ค ํ”„๋กœ๊ทธ๋žจ

- ์ต๋ช…์œผ๋กœ ์ฑ„ํŒ… ๋‚ด์šฉ์„ ์ฃผ๊ณ  ๋ฐ›์„ ์ˆ˜ ์žˆ์Œ

- ๋‹‰๋„ค์ž„์„ ์ถ”๊ฐ€ํ•ด ๋ˆ„๊ตฌ๋ž‘ ๋Œ€ํ™”ํ•˜๋Š”์ง€ ์•Œ์ˆ˜ ์žˆ์Œ

- ์ฑ„ํŒ…๋ฐฉ์˜ ์ปจ์…‰์„ ์ •ํ•จ.

- ์ž…์žฅ, ํ‡ด์žฅ ์ด๋ฒคํŠธ ์ถ”๊ฐ€

- ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฐฉ์— ๋ช‡ ๋ช…์ด ์ ‘์† ์ค‘์ธ์ง€ ํ™•์ธ

- ์„œ๋ฒ„์— ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฐฉ์ด ๋ช‡ ๊ฐœ์ธ์ง€ ํ™•์ธ

 

 

#1.1 HTTP vs WebSockets

 

- http, webSocket ๋‘˜๋‹ค protocol

- http : user๊ฐ€ requestํ•˜๋ฉด server๊ฐ€ responseํ•˜๋Š” ๋ฐฉ์‹

- server๋Š” user์—๊ฒŒ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ผ ์ˆ˜ ์—†์Œ.

- request - response ๊ณผ์ • ๋’ค์—๋Š” server๊ฐ€ user๋ฅผ ์žŠ๊ฒŒ ๋จ => ์ด๋ฅผ stateless๋ผ๊ณ  ํ•จ.

// user๊ฐ€ home์— GET request๋ฅผ ๋ณด๋‚ด๋ฉด template๋กœ ๋ฐ˜์‘
app.get("/", (_, res) => res.render("home"));
// user๊ฐ€ ์–ด๋–ค ํŽ˜์ด์ง€์— GET request๋ฅผ ๋ณด๋‚ด๋„ redirect๋กœ ๋ฐ˜์‘
app.get("/*", (_, res) => res.redirect("/"));

WebSocket : server์™€ ์•„์˜ˆ ์—ฐ๊ฒฐ๋˜๋Š” ๊ฒƒ, server์™€ browser๊ฐ€ ์–‘๋ฐฉํ–ฅ ์—ฐ๊ฒฐ์ด๋ฉฐ, server์™€ browser๋Š” ์–ธ์ œ๋“  ์„œ๋กœ์—๊ฒŒ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Œ. disconnectํ•˜์ง€ ์•Š๋Š” ์ด์ƒ ๊ณ„์† ์—ฐ๊ฒฐ๋˜์–ด์žˆ์Œ

ex. wifi, ์ „ํ™”

=> ์‹ค์‹œ๊ฐ„ chat, notifictaion ๊ฐ™์€ ๊ธฐ๋Šฅ ๊ตฌํ˜„์ด ๊ฐ€๋Šฅ 

 

 

#1.2 WebSockets in NodeJS

 

https://ssocoit.tistory.com/189 ๋ถ„์ด ์„ค๋ช…์„ ์ž˜ ์จ๋†“์œผ์…”์„œ ์ฃผ์„์„ ๊ธ์–ด์™”๋‹ค,,, 

 

import http from "http"; 
import WebSocket from "ws"; 
import express from "express"; 

// app์ด๋ผ๋Š” ๋ณ€์ˆ˜์— ๊ฐ€์ ธ์™€์„œ ์‚ฌ์šฉ
const app = express(); 

// ๋ทฐ ์—”์ง„์„ pug๋กœ ํ•˜๊ฒ ๋‹ค
app.set("view engine", "pug"); 
// ๋””๋ ‰ํ† ๋ฆฌ ์„ค์ •
app.set("views", __dirname + "/views"); 
// public ํด๋”๋ฅผ ์œ ์ €์—๊ฒŒ ๊ณต๊ฐœ (์œ ์ €๊ฐ€ ๋ณผ ์ˆ˜ ์žˆ๋Š” ํด๋” ์ง€์ •)
app.use("/public", express.static(__dirname + "/public"));
// ํ™ˆํŽ˜์ด์ง€๋กœ ์ด๋™ํ•  ๋•Œ ์‚ฌ์šฉ๋  ํ…œํ”Œ๋ฆฟ์„ ๋ Œ๋”
app.get("/", (req, res) => res.render("home")); 
// ํ™ˆํŽ˜์ด์ง€ ๋‚ด ์–ด๋А ํŽ˜์ด์ง€์— ์ ‘๊ทผํ•ด๋„ ํ™ˆ์œผ๋กœ ์—ฐ๊ฒฐ๋˜๋„๋ก ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ (๋‹ค๋ฅธ url ์‚ฌ์šฉ ์•ˆํ• ๊ฑฐ๋ผ)
app.get("/*", (req, res) => res.redirect("/")) 

const handleListen = () => console.log(`Listening on http://localhost:3000`)
// app.listen(3000, handleListen); // 3000๋ฒˆ ํฌํŠธ์™€ ์—ฐ๊ฒฐ

// app์€ requestlistener ๊ฒฝ๋กœ - express application์œผ๋กœ๋ถ€ํ„ฐ ์„œ๋ฒ„ ์ƒ์„ฑ
const server = http.createServer(app); 

// http ์„œ๋ฒ„ ์œ„์— webSocket์„œ๋ฒ„ ์ƒ์„ฑ, ์œ„์˜ http๋กœ ๋งŒ๋“  server๋Š” ํ•„์ˆ˜ X - ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด http / ws ์„œ๋ฒ„ ๋ชจ๋‘ ๊ฐ™์€ 3000๋ฒˆ ํฌํŠธ๋ฅผ ์ด์šฉํ•ด์„œ ๋Œ๋ฆด ์ˆ˜ ์žˆ๋‹ค!
const wss = new WebSocket.Server({ server }); 

// ์ž„์‹œ๋กœ ๋งŒ๋“  ํ•จ์ˆ˜
function handleConnection(socket) { // ์—ฌ๊ธฐ์„œ socket์€ ์—ฐ๊ฒฐ๋œ ๋ธŒ๋ผ์šฐ์ €
    console.log(socket) // ์—ฌ๊ธฐ ์žˆ๋Š” ์†Œ์ผ“์ด frontend์™€ real-time์œผ๋กœ ์†Œํ†ตํ•  ์ˆ˜ ์žˆ๋‹ค
};

// on method์—์„œ๋Š” event๊ฐ€ ๋ฐœ๋™๋˜๋Š” ๊ฒƒ์„ ๊ธฐ๋‹ค๋ฆฐ๋‹ค
// event๊ฐ€ connection / ๋’ค์— ์˜ค๋Š” ํ•จ์ˆ˜๋Š” event๊ฐ€ ์ผ์–ด๋‚˜๋ฉด ์ž‘๋™
// ๊ทธ๋ฆฌ๊ณ  on method๋Š” backend์— ์—ฐ๊ฒฐ๋œ ์‚ฌ๋žŒ์˜ ์ •๋ณด๋ฅผ ์ œ๊ณต - ๊ทธ๊ฒŒ socket์—์„œ ์˜ด
// socket์„ callback์œผ๋กœ ๋ฐ›๋Š”๋‹ค. webSocket์€ ์„œ๋ฒ„์™€ ๋ธŒ๋ผ์šฐ์ € ์‚ฌ์ด์˜ ์—ฐ๊ฒฐ
wss.on("connection", handleConnection) 

// ์„œ๋ฒ„๋Š” ws, http ํ”„๋กœํ† ์ฝœ ๋ชจ๋‘ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค
server.listen(3000, handleListen);

 

 

๋‚ด์ผ ์•„์นจ 6์‹œ๊นŒ์ง„๋”” ํฐ์ผ๋‚ฌ๋„ค... ์˜ค๋Š˜ ์˜ค์ „์— ์ข€ ํ•ด๋‘˜๊ฑธ... 

'javascript > ์คŒ ํด๋ก ์ฝ”๋”ฉ' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

DAY 3 #2.0 ~ #2.3  (0) 2023.02.24
DAY 2 #1.3 ~ 1.9  (0) 2023.02.22