Illie

Nomad. Zoom Clone Coding (1) - 셋팅 / 웹소켓 본문

Clone Something/Zoom -Nomad

Nomad. Zoom Clone Coding (1) - 셋팅 / 웹소켓

(*ᴗ͈ˬᴗ͈)ꕤ*.゚ 2022. 6. 29. 16:21

1. 서버 셋팅

1) npm init yarn으로 package.json 파일 생성 (버전 관리 편리)

- "script" : 패키지의 생명주기에서 다양한 타이밍에 자주 사용할 commend를 alias(별칭)을 통해 지정해 둘 수 있는 dictionary

- "dependencies" : 필드에 자동으로 install한 '패키지 이름과 '버전'

- "devDependencies" : 개발시에만 필요한 의존 패키지

 

2) npm i nodemon -D 

- nodemon : 서버 코드를 변경할 때마다 자동으로 시작해 줌

 

3) npm i @babel/core @babel/cli @babel/node -D

@babel/core : 핵심적인 동작이 담겨있는 바벨 코어

@babel/cli : 커멘드라인 명령어를 지원하기 위한 바벨 CLI

@babel/node : 개발 및 테스트 단계에서만 사용하는 것을 권장

 

4) server.js

import express from "express"; //서버 만들어 줌

const app = express(); //app이라는 변수 가져와서 만들어줌

console.log("hello");

app.listen(3000); // 3000번 포트와 연결

 

5) nodemon.json

{
  "exec": "babel-node src/server.js"
}

 

2. 프론트엔드 셋팅

server.js

app.set("view engine", "pug");
app.set("views", __dirname + "/src/views");
app.use("/public", express.static(__dirname + "/public"));
app.get("/", (req, res) => res.render("home"));
app.get("/*", (req, res) => res.redirect("/"));

- app.set("view engine", "pug"): 뷰 엔진을 pug로 하겠다

- app.set("views", __dirname + "/src/views"): 디렉토리 설정(dirname: 절대경로 <-> filename: 상대경로)

- app.use("/public", express.static(__dirname + "/public"): public 폴더를 유저에게 공개

- app.get("/", (req, res) => res.render("home")): 홈페이지로 이동할 때 사용될 템플릿을 렌더링

- app.get("/*", (req, res) => res.redirect("/)): 도메인 뒤에 뭐를 치던간에 다시 /로 돌아 오게 함

 

3. 웹소켓

1-1) 웹소켓 연결하기 - backend

// server.js

const app = express();

const server = http.createServer(app);
const wss = new WebsocketServer({ server });
// http, ws 모두 같은 포트 번호로 돌린다!

wss.on("connection", () => {console.log(socket)}); 연결되면 소켓으로 정보가 올 예정

1-2) 웹소켓 연결하기 - frontend

// app.js

const socket = new Websocket(`ws://${window.location.host}`)

 

2-1) 메시지 주고받기 ( send : 나(크롬), receive: 나(크롬))

// server.js

wss.on("connection", (socket) => {
  console.log("Connected to Browswer ✔");
  socket.on("close", () => console.log("Disconnected from the Browser ❌"));
  socket.on("message", (message) => {
    console.log(message.toString("utf8"));
  });
  socket.send("hello?");
});
// app.js

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

socket.addEventListener("message", (message) => {
  console.log("New message: ", message.data);
});

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

setTimeout(() => {
  socket.send("hello from the browser!");
}, 10000);

 

input에 넣은 value를 보냄, 그리고 input.value 초기화

// app.js

const messageList = document.querySelector("ul");
const messageForm = document.querySelector("form");

function handelSubmit(event) {
  event.preventDefault();
  const input = messageForm.querySelector("input");
  socket.send(input.value);
  input.value = "";
}

messageForm.addEventListener("submit", handelSubmit);

 

2-2) 메시지 주고받기 ( send : 나(크롬 브로우저), receive: 나(사파리 브라우저))

// app.js


const sockets = [];

wss.on("connection", (socket) => {
  sockets.push(socket);
  socket.on("message", (message, isBinary) => {
    const messageString = isBinary ? message : message.toString("utf8");
    sockets.forEach((aSocket) => aSocket.send(messageString));
  });
});

 

2-3) 닉네임 추가(백엔드는 다양한 언어를 사용하기 때문에, 클라이언트에서 string으로 보내야 함)

// app.js

const nickForm = document.querySelector("#nick");
const messageForm = document.querySelector("#message");

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

function handelSubmit(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", handelSubmit);
nickForm.addEventListener("submit", handleNickSubmit);
// server.js

const sockets = [];

wss.on("connection", (socket) => {
  sockets.push(socket);
  socket["nickname"] = "Anon"; // 익명으로 우선 설정
  socket.on("message", (message1, isBinary) => {
    const messageString = isBinary ? message1 : message1.toString("utf8");
    const message = JSON.parse(messageString);
    // const message -> string으로 변경
    
    switch (message.type) {
      case "new_message":
        sockets.forEach((aSocket) =>
          aSocket.send(`${socket.nickname}: ${message.payload}`)
        );
        break;
      case "nickname":
        socket["nickname"] = message.payload;
        break;
    }
  });
});

 

 

Comments