하나씩 차근차근
article thumbnail

이번에는 채팅방 나가는 기능과 접속과 나갈때 알림 메세지를 보내도록 하겠습니다.

 

채팅방 나가기

먼저 home.html 페이지에 채팅방 상태에서 나갈 수 있도록 나가기 버튼을 추가합니다.

<!DOCTYPE html>
<html>
  <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>Chatting</title>
    <link rel="stylesheet" href="/style/home.css" />
  </head>
  <body>
    <header>Chatting Web Page</header>
    <main>
      <h2>Welcome</h2>
      <div id="room">
        <ul id="roomList"></ul>
        <button id="roomMake">방 만들기</button>
      </div>
      <div id="modal">
        <div id="modalContent">
          <input
            type="text"
            id="roomNameText"
            place="방 이름을 입력해주세요."
          />
          <button id="roomMakeAndEnter">생성</button>
          <button id="cancel">취소</button>
        </div>
      </div>
      <div id="chattingRoom">
        <div id="roomName"></div>
        <button id="exit">나가기</button>
        <div id="chatting">
          <ul id="message"></ul>
        </div>
        <form id="textSend">
          <input
            type="text"
            id="messageText"
            placeholder="메세지를 입력해주세요."
            ,
            required
          />
          <button type="submit">전송</button>
        </form>
      </div>
    </main>
  </body>
  <script src="/socket.io/socket.io.js"></script>
  <script type="text/javascript" src="/js/app.js"></script>
</html>

 

app.js

다음으로 나가기 버튼을 눌렀을때 발생시킬 이벤트를 버튼에 연결하고

채팅방에 메세지를 띄워주는 addMessage 메서드를 작성합니다.

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 roomNameInput = document.getElementById("roomNameText");
const roomName = document.getElementById("roomName");
const chattingRoom = document.getElementById("chattingRoom");
const exit = document.getElementById("exit");

...

function exitRoom() {
  socket.emit("exit");
}

...

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

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

 

server.js

채팅방에서 나가는 경우는 다음과 같이 두 가지 경우가 있습니다.

  • 나가기 버튼을 클릭해서 나가는 경우
  • 탭을 닫거나 브라우저를 닫는 경우

나가기 버튼을 클릭하는 경우는 다음과 같이 클라이언트에서 "exit" 이벤트를 발생시켜

서버에서 해당 이벤트를 받으면 다음과 같이 연결을 종료하도록 합니다.

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

  ...
  
  socket.on("exit", () => {
    console.log("disconnect 전 : " + socket.rooms);
    socket.disconnect();
    console.log("disconnect 후 : " + socket.rooms);
  });

});

채팅방에 접속한 뒤 나가기 버튼을 누르면

disconnect 메서드를 실행하기 전에는 rooms 가 2개가 있지만, 

disconnect 메서드를 실행한 후에는 rooms 가 비어있는 것을 알 수 있습니다.

[nodemon] restarting due to changes...
[nodemon] starting `babel-node src/server.js`
Server Start
Set(2) { 'PwF_jMJg2tiR_QWSAAAE', 'room1' }
Set(0) {}

다음으로 탭을 닫거나 브라우저를 종료했을때 나가는 경우는

브라우저 창을 닫거나 컴퓨터를 꺼서 채팅방을 나갈때 socket.io 의 disconnecting 이벤트가 발생하면서 

자동으로 socket 과 연결이 끊어지게 됩니다.

  socket.on("disconnecting", () => {
    // socket 연결이 끊어졌을때 동작할 메서드 작성
  });

server.js 에 위와 같이 disconnecting 이벤트를 연결해주고

이후, 연결이 끊어졌을때 메세지를 보내보겠습니다.

 

접속 및 나가기 메세지

다음으로 채팅방에 접속하고 나갈때 메세지를 보내보도록 하겠습니다.

 

app.js

채팅방에 메세지를 출력하는 addMessage 메서드를 작성하겠습니다.

...

function exitRoom() {
  socket.emit("exit");
}

function addMessage(message) {
  const ul = document.getElementById("message");
  const li = document.createElement("li");

  li.innerText = message;
  ul.appendChild(li);
}

...

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

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

 

server.js

채팅방을 나갈때 "bye" 이벤트를 발생시켜 클라이언트에서 해당 이벤트를 받아서 

브라우저에 "누군가 나갔습니다" 라는 메세지를 띄워보겠습니다.

  • 나가기 버튼을 통해 나가는 경우 : "exit " 이벤트 발생
  • 브라우저 또는 컴퓨터가 종료되어 나가는 경우 : "disconnecting" 이벤트 발생
socketServer.on("connection", (socket) => {

  ...

  socket.on("exit", () => {
    socket.rooms.forEach((room) => socketServer.to(room).emit("bye"));
    socket.disconnect();
  });

  socket.on("disconnecting", () => {
    socket.rooms.forEach((room) => socketServer.to(room).emit("bye"));
  });
});

위와 같이 각 경우에 "bye" 이벤트를 발생시킵니다.

이와 동일하게 "welcome" 이벤트를 발생시켜서 클라이언트에서 해당 이벤트가 발생하면 

브라우저에 "누군가 입장했습니다" 메세지를 출력하도록 합니다.

  socket.on("enter_room", (roomName) => {
    socket.join(roomName);

    // 클라이언트가 채팅방에 접속하면 "welcome" 이벤트 발생
    socketServer.to(roomName).emit("welcome");
  });

이때 socketServer.to(roomName) 을 통해 현재 socket 이 접속한 방에 "welcome" 이벤트를 발생시킵니다.

 

app.js 추가

server.js 에서 발생시킨 "bye" 이벤트를 받아서 클라이언트에서는 addMessage 를 통해 "누군가 퇴장했습니다" 라는 

메세지를 화면에 그려줍니다.

...

socket.on("bye", () => {
  addMessage("누군가 퇴장했습니다.");
});

function exitRoom() {
  socket.emit("exit");
}

function addMessage(message) {
  const ul = document.getElementById("message");
  const li = document.createElement("li");

  li.innerText = message;
  ul.appendChild(li);
}

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

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

또한 이와 동일하게 클라이언트가 채팅방에 입장했을 때에도 "누군가 입장했습니다" 라는 메세지를 출력합니다.

socket.on("welcome", () => {
  roomName.innerText = currentRoom;
  addMessage("누군가 입장했습니다.");
});

 

결과

다음과 같이 room1 채팅방에 접속을 하게 되면 "누군가 입장했습니다" 라는 메세지가 출력됩니다.

또한, 탭을 하나 더 생성해서 room1 채팅방에 접속을 하면 첫번째 탭에서 "누군가 입장했습니다" 라는 메세지가

한번 더 출력이 됩니다.

 

profile

하나씩 차근차근

@jeehwan_lee

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