하나씩 차근차근
article thumbnail

앞에서 채팅방을 생성하는 기능을 만들었습니다.

마지막으로 채팅방의 이름이 기존에 존재하는 이름일 경우 채팅방을 생성하지 않고

존재하지 않을 경우에만 생성하도록 하겠습니다.

 

시작

클라이언트

다음과 같이 app.js 파일을 수정합니다.

const roomName = document.getElementById("roomNameText");

function makeRoom(check) {
  if (check == false) {
    // 동일한 이름의 채팅방이 있을 경우
    alert("채팅방이 존재합니다.");
    roomName.value = "";
  } else {
    const li = document.createElement("li");
    li.textContent = roomName.value;
    roomList.appendChild(li);

    // roomList와 modal의 hidden = true, message From의 hidden = false
    room.hidden = true;
    form.hidden = false;
    modal.hidden = true;
  }
}

function modalClick(event) {
  if (event.target.id == "modal") {
    // modal창의 바깥부분을 클릭했을 경우 close
    modal.hidden = true;
    roomName.value = "";
  } else if (event.target.id == "roomMakeAndEnter") {
    // 생성 버튼을 클릭했을 경우
    socket.emit("make_room", roomName.value, makeRoom);
  } else if (event.target.id == "cancel") {
    // 취소버튼을 누르면 modal hidden = true
    modal.hidden = true;
    roomName.value = "";
  }
}

modalClick 메서드에서 생성 버튼을 클릭했을 경우

socket 을 통해 서버로 채팅방의 이름과 makeRoom 메서드를 같이 보내게 됩니다.

socket emit 메서드는 이벤트를 발생시키고, 어떤 데이터(변수, 객체, 콜백함수) 도 서버쪽으로 전달할 수 있음

emit 메서드를 통해 "make_room" 이벤트를 통해 서버쪽으로 콜백함수를 전달하게 되면,

서버에서 해당 콜백함수를 실행시켜 다시 클라이언트에서 해당 함수를 실행시킬 수 있습니다.

 

우리는 서버쪽에서 채팅방 이름(roomName) 을 받아서

  • 해당 채팅방이 존재할 경우 -> makeRoom(false) 실행 -> alert 메세지 출력
  • 해당 채팅방이 존재하지 않을 경우 -> makeRoom(true) 실행 -> 채팅방 목록에 추가 및 채팅방 이동

위와 같이 처리하겠습니다.

 

서버

"make_room" 이벤트를 통해 서버는 roomName 과 makeRoom 함수를 받습니다.

socket.on("make_room", (roomName, makeRoom) => {
    if (rooms.includes(roomName) == true) {
      // 동일한 이름의 채팅방이 존재할 경우
      // TODO : 추후 DB 연동시 쿼리로 존재여부 확인
      makeRoom(false);
    } else {
      // TODO : 추후 DB 연동시 쿼리로 room 저장
      rooms.push(roomName);
      socket.join(roomName);
      console.log(socket.rooms);

      makeRoom(true);
    }
  });

rooms 배열에서 전달받은 roomName 존재 여부를 확인하고 makeRoom 메서드를 실행합니다.

 

결과

다음과 같이 서버에 저장된 room1 을 입력해서 채팅방을 생성할 경우 alert 메세지가 출력됩니다.

 

전체코드

app.js

const socket = io();

const form = document.getElementById("textSend");
const room = document.getElementById("room");
const roomList = document.getElementById("roomList");
const roomMake = document.getElementById("roomMake");
const modal = document.getElementById("modal");
const roomName = document.getElementById("roomNameText");

form.hidden = true;
modal.hidden = true;

// 서버와 연결됬을 경우 방 목록 그리기
socket.on("init", (rooms) => {
  rooms.forEach((room) => {
    const li = document.createElement("li");
    li.textContent = room;
    roomList.appendChild(li);
  });
});

function makeRoom(check) {
  if (check == false) {
    // 동일한 이름의 채팅방이 있을 경우
    alert("채팅방이 존재합니다.");
    roomName.value = "";
  } else {
    const li = document.createElement("li");
    li.textContent = roomName.value;
    roomList.appendChild(li);

    // roomList와 modal의 hidden = true, message From의 hidden = false
    room.hidden = true;
    form.hidden = false;
    modal.hidden = true;
  }
}

function modalClick(event) {
  if (event.target.id == "modal") {
    // modal창의 바깥부분을 클릭했을 경우 close
    modal.hidden = true;
    roomName.value = "";
  } else if (event.target.id == "roomMakeAndEnter") {
    // 생성 버튼을 클릭했을 경우
    socket.emit("make_room", roomName.value, makeRoom);
  } else if (event.target.id == "cancel") {
    // 취소버튼을 누르면 modal hidden = true
    modal.hidden = true;
    roomName.value = "";
  }
}

function messageSubmit(event) {
  event.preventDefault();
  const input = document.getElementById("messageText");
  socket.emit("send_message", input.value);
  input.value = "";
}

function enterRoom(event) {
  socket.emit("enter_room", event.target.textContent);
  room.hidden = true;
  form.hidden = false;
}

form.addEventListener("submit", messageSubmit);
roomList.addEventListener("click", enterRoom);

// 채팅방 생성 모달창 보여주기
roomMake.addEventListener("click", () => {
  modal.hidden = false;
});
modal.addEventListener("click", modalClick);

 

server.js

import express from "express";
import http from "http";
import SocketIO from "socket.io";
import { setTimeout } from "timers/promises";

const app = express();
const httpServer = http.createServer(app);
const socketServer = SocketIO(httpServer);

const sockets = [];
const rooms = ["room1", "room2"];

app.use("/js", express.static(__dirname + "/js"));
app.use("/style", express.static(__dirname + "/style"));

app.get("/", (req, res) => res.sendFile(__dirname + "/views/" + "home.html"));
app.get("/*", (req, res) => res.redirect("/"));

socketServer.on("connection", (socket) => {
  sockets.push(socket);

  // 서버와 클라이언트가 연결되면 rooms 배열을 클라이언트로 보냄
  // TODO : 추후 DB 연동시 쿼리로 room 가져와서 보내기
  socket.emit("init", rooms);

  socket.on("send_message", (message) => console.log(message));

  socket.on("enter_room", (roomName) => {
    socket.join(roomName);
    console.log(socket.rooms);
  });

  socket.on("make_room", (roomName, makeRoom) => {
    if (rooms.includes(roomName) == true) {
      // 동일한 이름의 채팅방이 존재할 경우
      // TODO : 추후 DB 연동시 쿼리로 존재여부 확인
      makeRoom(false);
    } else {
      // TODO : 추후 DB 연동시 쿼리로 room 저장
      rooms.push(roomName);
      socket.join(roomName);
      console.log(socket.rooms);

      makeRoom(true);
    }
  });
});

const handleListen = () => {
  console.log("Server Start");
};
httpServer.listen(3000, handleListen);

 

생각해볼 점

채팅방이 존재하는지 여부를 확인하는 방법은

  1. 클라이언트에 rooms 배열을 만들어 서버에 저장된 rooms 배열을 가져와서 클라이언트에서 존재 여부 확인
  2. 서버에서 클라이언트에서 보낸 roomName 을 통해 존재 여부 확인

위와 같이 두 가지 방법이 있습니다.

 

다만 이 프로젝트에서는 두번째 방법인 서버에서 존재 여부를 확인하는 것으로 했는데,

이것은 추후에 DB를 연동할때 서버에서 쿼리를 통해 존재여부를 바로 확인하고 결과를 보낼 수 있기 때문입니다.

 

만약, 클라이언트에서 존재 여부를 확인하게 되면 DB가 업데이트 될때마다

클라이언트의 rooms 배열에 서버에 저장된 room 들의 값들을 계속 가져와야하기 때문에 효율성이 떨어지기 때문에

추후 DB 연동을 위해 두번째 방법을 선택했습니다.

 

profile

하나씩 차근차근

@jeehwan_lee

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!