728x90

#2.2 SocketIO is Amazing

이제 room 에 대해 배워보자. 

Userr가 웹사이트로 가면, 방을 만들거나 다른 방에 참여할 수 있다. 여기서 room 의 개념이 사용되며

socketIO에는 room 기능이 있어서 방에 참가하고 나가는 것이 매우 쉽다. 

또한 room 기능으로 방에 메세지를 보내는 것도 지원해준다. 

 

room 기능 사용을 위해 먼저 frontend 에 form 을 만들어주자.  (line 13~16)

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
        link(rel="stylesheet", href="https://unpkg.com/mvp.css")
    body 
        header
            h1 Noom 
        main 
            div#welcome
                form
                    input(placeholder="room name", required, type = "text")
                    button Enter Room 
        script(src="/socket.io/socket.io.js")    
        script(src="/public/js/app.js")

socketIO를 사용하면 

1. event 명을 임의로 지정하여 emit 할 수 있다. (여기선 enter_room) => emit의 event 명과 on의 event 명이 동일해야한다. 

2. Object 를 emit 할 수 있다.

3. 인자를 여러개 보낼 수 있다. (socket.emit("enter_room", {~~}, 3,5,6,,,,,10 );  와 같이 보낼 수 있다. 추가로 인자 수만큼 데이터를 받는 backend 쪽에도 on 메소드에 인자를 추가로 넣어줘야한다. )

 

frontend 

 : line 9와 같이 enter_room 이벤트에 payload(Object) 를 backend 로 전송한다. 

 

 

backend 

 : front에서 보낸 메세지를 받는다. (Line 23)

 

브라우저 창에 myroom 이라고 치면 이 메세지가 backend 로 전달되어 터미널에 출력되는 것을 확인할 수 있다. 

이는 Javascript Object 형식임에 주목하자. 

front에서 back 으로 Object 를 전송하면 SocketIO가 Object를 처리한다.

 

다음은 Callback 에 대해 알아보자. Callback 은 서버에서 호출하는 function 이다. 

frontend의 emit() 메소드의 세번째 인자로 function을 넣어보자. 

 

front -> back 으로 emit 할 때 함수 정보도 함께 보내고,

back 에서는 이렇게 받은 인자들을 처리한다.

backend 에서는 done() 메소드를 호출하고

메소드가 실행되는 것은 frontend 에서 되는 것임을 유의하자. 

(만약 front 에서 보낸 function을 back 에서 실행한다면 이건 보안 이슈임)

 

//app.js 

const socket = io();

const welcome = document.getElementById("welcome")
const form = welcome.querySelector("form");

function handleRoomSubmit(event){
    event.preventDefault();
    const input = form.querySelector("input");
    socket.emit("enter_room", {payload: input.value}, () => {
        console.log("server is done!");
    });;
    input.value = "";
}
form.addEventListener("submit", handleRoomSubmit);

//server.js

import http from "http";
import SocketIO from "socket.io"
import WebSocket from "ws";
import express from "express";

const app = express();

//set the view
app.set("view engine", "pug");
app.set("views", __dirname + "/views");
app.use("/public", express.static(__dirname + "/public")); //user가 public 으로 이동하면 __dirname+/public 폴더를 보여주는 것. 
app.get("/", (req, res) => res.render("home"));//render 
app.get("/*", (req, res) => res.redirect("/"));

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

//http의 서버
const httpServer = http.createServer(app); //app은 requestListener 의 경로. express application으로부터 서버 생성. 
const wsServer  = SocketIO(httpServer);

wsServer.on("connection", (socket) => {
    socket.on("enter_room", (msg, done) => {
        console.log(msg);
        setTimeout(() => {
            done();
        }, 10000);
    });
});


//websocket 서버
//const wss = new WebSocket.Server({ httpServer });


// function handleConnection(socket) {
//     console.log(socket)
// }

// const sockets = [];

// wss.on("connection", (socket) => {
//     sockets.push(socket);
//     socket["nickname"] = "Anon";    //처음엔 익명으로 설정 
//     console.log("Connected to Browser ✅");
//     socket.on("close", () => {
//         console.log("Disconnected from the Browser ❌");
//     });
//     socket.on("message", (msg) => { 
//         const message = JSON.parse(msg);        //string -> Object
//         //console.log(message, message.toString('utf-8'));
//         switch(message.type){
//             case "new_message" :
//                 //sockets.forEach((aSocket) => aSocket.send(message.payload.toString('utf-8'))); //채팅 메세지만 출력하기 위해 이것만 브라우저에 보냄 
//                 sockets.forEach((aSocket) => aSocket.send(`${socket.nickname}: ${message.payload}`)); //누가 보냈는지, 뭘 보냈는지 
//             case "nickname" :
//                 //console.log(message.payload.toString('utf-8'));     
//                 socket["nickname"] = message.payload;
//         }
//     });
    
// });

httpServer.listen(3000, handleListen);

frontend 에서 함수가 실행되어서 console 창에 함수 결과가 프린트된 것을 확인할 수 있다. 

주의) emit에 여러개의 인자를 넣고 on 에서 그걸 받는다고 했을 때, function을 다시 front 로 넘겨주기 위해서는 마지막 인자에 넣어서 보내줘야 한다. 

 

 

 

728x90

+ Recent posts