728x90

#2.6 Room Notifications

이제 사용자가 방을 떠날 때 이를 알리는 기능을 구현해보자.

여기서 disconnecting 과 disconnected 를 구별해야한다.

disconnecting 은 완전히 disconnected 되기 전의 상태이기 때문에 메세지를 보낼 수 있는 것이다.  

 

socket.rooms 를 하면 아래와 같이 Set 을 의미한다. Set 이기 때문에 forEach 즉, 반복이 가능하다. 

qay... 는 room.id 이며 myroom~ 은 roomName 이다. 

그리고 server.js 에 아래의 line 31~33 과 같이 disconnecting 이벤트에 대해 코드를 추가해준다.

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.onAny((event) => {   //socket 에 있는 모든 이벤트 모니터링 가능
        console.log(`Socket Event: ${event}`);
    });
    socket.on("enter_room", (roomName, done) => {
        socket.join(roomName);
        done();
        socket.to(roomName).emit("welcome");    //모든 사람에게 welcome 이벤트 Emit
    });
    socket.on("disconnecting", () => {
        socket.rooms.forEach(room => socket.to(room).emit("bye"));
    })
});

httpServer.listen(3000, handleListen);

 

app.js 에도 앞서 했던 welcome 과 동일한 방식으로 bye 도 추가해준다.

socket.on("bye", () => {
    addMessage("Someone Left!");  
});

 

방에 들어갔다가 나갔음을 알 수 있다. 

 

 

이제 메세지를 보내보자. 

room 안에 있는 message 를 from 에서 찾아서 -> addEventListener 를 추가한뒤 -> new_message event 를 보내면 된다. 

먼저 방에 들어왔음을 보여주는 showRoom 메서드 안에서 from 을 찾아보자. (line 32~33)

 

그 후 line 17~25 와 같이 handleMessageSubmit 을 작성한다. 이 메소드는 우리가 브라우저에서 입력한 메세지 내용을 backend로 전송해주는 역할을 한다.  전송 시 roomName도 함께 인자로 보내줘서 backend 가 어디 room 으로 보낼지 식별 가능하도록 한다. 

 

handleMessageSubmit 에서 input.value 를 초기화 시켜줄때 주의해야한다.

왜냐하면 emit 을 통해 backend 로 보내고 다시 메세지를 front 로 받는 과정에서 

input.value = "" 를 통해 초기화 되어버리기 때문에 브라우저에 출력이 되지 않게 되는 문제가 있기 때문이다. 

그렇기 때문에 value 라는 변수 선언을 통해 값을 저장해놓고 (line20)

line22 에서 그 저장된 값을 쓰도록 함으로써 line 24에 영향을 받지 않도록 한다. 

 

//app.js

const socket = io();

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

room.hidden = true;
let roomName;

function addMessage(message){
    const ul = room.querySelector("ul");
    const li = document.createElement("li");
    li.innerText = message;
    ul.appendChild(li);
}

function handleMessageSubmit(event){
    event.preventDefault();
    const input = room.querySelector("input");
    const value = input.value;
    socket.emit("new_message", input.value, roomName, () => {     //백엔드에 입력한 메세지 전송 
        addMessage(`You: ${value}`);  //대화창에 메세지 출력 
    });
    input.value = "";
}

function showRoom(){
    welcome.hidden = true;
    room.hidden = false; 
    const h3 = room.querySelector("h3");
    h3.innerText = `Room ${roomName}`;
    const form = room.querySelector("form");
    form.addEventListener("submit", handleMessageSubmit);
}

function handleRoomSubmit(event){
    event.preventDefault();
    const input = form.querySelector("input");
    socket.emit("enter_room", input.value, showRoom);
    roomName = input.value;
    input.value = "";
}
form.addEventListener("submit", handleRoomSubmit);

socket.on("welcome", () => {
    addMessage("Someone Joined!");  
}); 

socket.on("bye", () => {
    addMessage("Someone Left!");  
});

socket.on("new_message", (addMessage)); 
// = socket.on("new_message", (msg) => {addMessage});

front 에서 보낸 메세지를 이제 backend 에서 받아보자. 

(line 34~37 추가)

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.onAny((event) => {   //socket 에 있는 모든 이벤트 모니터링 가능
        console.log(`Socket Event: ${event}`);
    });
    socket.on("enter_room", (roomName, done) => {
        socket.join(roomName);
        done();
        socket.to(roomName).emit("welcome");    //모든 사람에게 welcome 이벤트 Emit
    });
    socket.on("disconnecting", () => {
        socket.rooms.forEach(room => socket.to(room).emit("bye"));
    })
    socket.on("new_message" , (msg, room, done) => {
        socket.to(room).emit("new_message", msg);
        done();
    })
});

httpServer.listen(3000, handleListen);

 

그 후 backend 에서 front 로 보내는 socket.to(room).emit("new_message", msg) 부분을 

front 에 출력하기 위해 아래와 같이 함수를 추가해준다. 

socket.on("new_message", (addMessage));

실행해보자. 

You 를 통해 어디서 보낸 메세지인지 식별이 가능해졌다.

728x90

+ Recent posts