# 1.7-9 Chat Nicknames

이원규·2022년 6월 14일

Zoom clone coding

목록 보기
5/18

chat을 화면에 나타나게 하기.

  1. app.js ㄱ ㄱ, messageListener 수정하기.
frontSocket.addEventListener("message", (message) => {
    const li = document.createElement("li");
    li.innerText = message.data;
    messageList.append(li);
});

nickname 만들기.

1. html setup - home.pug ㄱ ㄱ

  • nickname form을 하나 만듦.
main 
    form#nick
        input(type="text", placeholder="Choose a nickname", required)
        button Save
    ul 
    form#message
        input(type="text", placeholder="Write a message", required)
        button Send Message
script(src="/public/js/app.js") 

app.js

  • nick form 가져오기 & nick form 이벤트 리스너
  • 이전 폼 수정
const nickForm = document.querySelector("#nick");
const messageForm = document.querySelector("#message");

nickForm.addEventListener("submit",handleNickSubmit);

-> frontend에서 nickform과 messageform 둘 다에서 message를 보내는데, backend는 이 메시지를 구분하지 못함. 그래서 우리는 {type:"message", message:"input.value"} 와 같이 type으로 구분할 수 있게 JSON형태로 보내줄 것임.

2. message(nick, message)구분해주기

frontend에서 보내는 메시지들 JSON.stringfy형태로 변환하기

  • app.js에서 ㄱ ㄱ.
    object를 JSON형태(string형태)로 보내는 이유:
    backend가 JS 서버가 아닐 수도 있어서. 즉, frontend와 backend(server)의 프로그래밍
    언어가 다를 수도 있기 때문이다. 이러한 이유로 backend에는 반드시 string형식으로 보내줘야
    한다.
    또한 Websocket(new WebSocket)이 브라우저에 있는 API이기 때문임. 백엔드에서는 어떠한
    프로그래밍 언어를 사용할 지 모르기 때문에 API는 어떠한 판단도 하면 안됨. 이러한 이유로 우린
    String만 보내는 거임.
function makeMessage(type, payload){
    const msg = {type, payload};
    return JSON.stringify(msg);
}; //JSON형태로 {type:"message", payload:"input.value"} 이런 식으로 보내주는 것.

function handleSubmit(event){
    event.preventDefault();
    const input = messageForm.querySelector("input");
    frontSocket.send(makeMessage("new_message", input.value));//chat message를 JSON형태로 object로 backend에 보내기
    input.value="";
};

function handleNickSubmit(event){
    event.preventDefault();
    const input = nickForm.querySelector("input");
    frontSocket.send(makeMessage("nickname",input.value));//niname message를 JSON형태로 object로 backend에 보내기
  	input.value="";
};

frontend에서 JSON.string 형태로 보내준 msg를 backend에서 JS object형태로 바꾸어 사용하기.

  • server.js ㄱㄱ, JSON.parse사용할 것임.({type:"message", payload:"input.value"} <- 이거를 string형태에서 JS object형태로 바
    꾸기 위해
  • switch를 이용해 nickname과 new_message를 구분해줄 것임.
  • backSocket자체에 닉네임을 넣어줄 것임. -> socket안에 정보를 저장할 수 있음!!!!!!!!!!!!!!!!!!!!!!
wss.on("connection",(backSocket) => {
    sockets.push(backSocket);
    backSocket["nickname"] = "Anonymous"; //아직 닉네임 정하지 않은 사람.
    console.log("Connected to Browser ✅");
    backSocket.on("close", () => console.log("Disconnected to the Brower ❌"));
    backSocket.on("message",(msg) =>{
        const message = JSON.parse(msg);
        switch (message.type){
            case "new_message":
                sockets.forEach((aSocket) => {aSocket.send(`${backSocket.nickname}: ${(message.payload).toString()}`)});
            case "nickname":
                backSocket["nickname"] = message.payload;//backSocket에 닉네임 넣어주기
        };
    });
});

codes

  • app.js
const messageList = document.querySelector("ul");
const nickForm = document.querySelector("#nick");
const messageForm = document.querySelector("#message");
const frontSocket = new WebSocket(`ws://${window.location.host}`);//frontend의 socket등록.

function makeMessage(type, payload){
    const msg = {type, payload};
    return JSON.stringify(msg);
}; //JSON형태로 {type:"message", payload:"input.value"} 이런 식으로 보내주는 것.

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

frontSocket.addEventListener("message", (message) => {
    const li = document.createElement("li");
    li.innerText = message.data;
    messageList.append(li);
});

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


function handleSubmit(event){
    event.preventDefault();
    const input = messageForm.querySelector("input");
    frontSocket.send(makeMessage("new_message", input.value));
    input.value="";
};

function handleNickSubmit(event){
    event.preventDefault();
    const input = nickForm.querySelector("input");
    frontSocket.send(makeMessage("nickname",input.value));
    input.value="";
};

messageForm.addEventListener("submit",handleSubmit);
nickForm.addEventListener("submit",handleNickSubmit);
  • server.js
import http from "http";
import WebSocket from "ws";
import express from "express";
import { Socket } from "dgram";

const app = express();

app.set("view engine", "pug");
app.set("views", __dirname + "/views"); // 현재 실행중인 폴더 경로 = process.cwd()와 같다고 볼 수 있음. __dirname : returns the directory name of the directory containing the JavaScript source code file// process.cwd(): returns the current working directory, 즉, node명령을 호출한 디렉토리입니다.
app.use("/public", express.static(__dirname + "/public"));//이미지, CSS 파일 및 JavaScript 파일과 같은 정적 파일을 제공하려면 Express의 기본 제공 미들웨어 함수인 express.static을 사용하십시오. -> app.use('/static', express.static(__dirname + '/public')); 이제 /static 경로 접두부를 통해 public 디렉토리에 포함된 파일을 로드할 수 있습니다.// 정적 파일이란, 직접 값에 변화를 주지 않는 이상 변하지 않는 파일을 의미합니다. 예를 들면, image, css 파일, js 파일 등을 의미합니다. -> static: 정적 파일만을 제공////보안상 유저는 서버 내 모든 폴더를 전부 들여다볼 수 없음(보안상의 이유 때문에) 그래서 유저가 볼 수 있는 폴더를 따로 지정해야댐. 즉, 이건 Front-end폴더임.
app.get("/", (_, res) => res.render("home"));
app.get("/*", (_, res) => res.redirect("/"));// -> catchall : 어떤 url을 가든 "/"로 돌아오게 만들어 home.pug만 볼 수 있도록 하기. 이번 프로젝트에서는 하나의 url만 사용할 것이기 때문에 이렇게 처리해줌.


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

const server = http.createServer(app);//server에 접근하도록 만들어 준 것임.
const wss = new WebSocket.Server({ server });//ws 서버 만들기, wss가 서버가 된 것이라 보면 편함.

const sockets = [];//fakeDB

wss.on("connection",(backSocket) => {// on: backend(server)의 eventListener임 -> 브라우저의 event에 귀 기울임
    sockets.push(backSocket);//fakeDB에 연결된 socket(브라우저 혹은 유저) 넣어주기
    backSocket["nickname"] = "Anonymous"; //아직 닉네임 정하지 않은 사람.
    console.log("Connected to Browser ✅");
    backSocket.on("close", () => console.log("Disconnected to the Brower ❌"));//Browser 연결이 끊기면 알려주는 콘솔창
    
    backSocket.on("message",(msg) =>{
        const message = JSON.parse(msg);
        switch (message.type){
            case "new_message":
                sockets.forEach((aSocket) => {aSocket.send(`${backSocket.nickname}: ${(message.payload).toString()}`)});
            case "nickname":
                backSocket["nickname"] = message.payload;// socket에 닉네임 넣어주기
        };
    });
});

server.listen(3000,handleListen);
  • 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")
        link(rel="stylesheet", href="https://unpkg.com/mvp.css")
        title Noom
    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 message", required)
                button Send Message
        script(src="/public/js/app.js") 

improve Chats

  1. 나를 제외한 사람들에게 문자 보내기, 내가 보낸 문자 화면에 그리기.
  • 우리는 현재 우리가 보내는 것이 아닌, 우리가 받는 메시지를 화면에 그리고 있음. -> 우리가 보내는 메 시지를 화면에 그리도록 코드 수정 ㄱ ㄱ

    하지만 이렇게 되면 받는 메시지도 화면에 그리고, 보내는 메시지도 화면에 그리게 됨. 따라서 나는 메시 지를 나를 제외한 모든 사람들에게 보내도록 수정할 것임.

  1. backend에서 message를 JSON.string형태로 보내고, frontend에서 JSON.parse해주기

  2. 이 외에도 여러 부수기능을 하나하나 새로 만들어야 돼서 다음 섹터에서는 framework를 이용해서 만들것임. wss는 기본적인 protocol이라, 아무 기능도 없었음 ㅆㅃ!

profile
github: https://github.com/WKlee0607

0개의 댓글