250x250
Notice
Recent Posts
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
관리 메뉴

일상 코딩

[ node.js / javascript] Node.js 이용한 실시간 채팅 기능 구현 본문

Node.js/Toy Project

[ node.js / javascript] Node.js 이용한 실시간 채팅 기능 구현

polarcompass 2022. 4. 19. 00:57
728x90
출처

https://book.naver.com/bookdb/book_detail.nhn?bid=21139328

 

Node.js로 서버 만들기

빠르게실무형 NODE.JS 개발자가 될 수 있도록 도와주는 실습형 입문서다.5줄로 만드는NODE.JS 서버로 핵심 개념을 파악하고,데이터베이스 연동,실시간 통신 실습을 통해 실무형 개발 지식을 습득한

book.naver.com

작동 방법

세 개의 파일이 있는 폴더로 이동 후 터미널에서 아래 코드 실행

$ node app.js

관련 라이브러리는 위의 책을 참고하는걸 추천함.

app.js
const http = require("http");
const express = require("express");
const app = express();

app.use(express.static(__dirname)); 

const server = http.Server(app);
const io = require("socket.io")(server);
let users = [];

server.listen(8080, () => {
    console.log("8080포트에서 서버 실행 중...");
});

app.get("/", (req, res) => {
    res.sendFile(__dirname + "/index.html");
});

io.on("connection", (socket) => {
    let name = "";
    socket.on("has connected", (username) => { // 이벤트 : has connected
        name = username;
        users.push(username);
        io.emit("has connected", { username: username, usersList: users });
    });

    socket.on("has disconnected", () => { // 이벤트 : has disconnected
        users.splice(users.indexOf(name), 1); // arr.splice(i,1) : arr[i] 요소 삭제(1)  
        io.emit("has disconnected", { username: name, usersList: users });
    })

    socket.on("new message", (data) => { // 이벤트 : new message
        io.emit("new message", data); // 모든 소켓에 메세지를 보냄
    });
});

 

index.html
<!DOCTYPE html>
<html>
  <head>
    <script
      src="https://code.jquery.com/jquery-3.4.1.js"
      integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU="
      crossorigin="anonymous"
    ></script>
    <script type="text/javascript" src="socket.io/socket.io.js"></script>

    <link rel="stylesheet" type="text/css" href="./index.css" />
    <title>실시간 채팅</title>
  </head>
  <body>
    <div id="login-area">
      <div id="login-text"><h1>Username 등록</h1></div>
      <div id="login-form-area">
        <form id="login-form">
          <input
            id="user-name"
            type="text"
            placeholder="Username"
            autocomplete="off"
          />
          <input id="login-submit" type="submit" value="Login" />
        </form>
      </div>
    </div>
    <div id="chat-area">
      <div id="users-area">
        <div id="online-users-text">
          <h1>Online users:</h1>
        </div>
        <div id="online-users">
          <ul id="users"></ul>
        </div>
      </div>

      <div id="message-area">
        <div id="display-message-area">
          <ul id="messages"></ul>
        </div>

        <div id="message-form-area">
          <form id="message-form">
            <input
              id="message"
              type="text"
              placeholder="Type your message..."
              autocomplete="off"
            />
            <input id="message-submit" type="submit" value="Send" />
          </form>
        </div>
      </div>
    </div>
  </body>

  <script type="text/javascript">
    const socket = io();

    function updateUsers(list) {
      for (let i = 0; i < list.length; i++) {
        $("#users").append("<li><b>" + list[i] + "</b></li>");
      }
    }

    $("#login-form").submit(function (event) {
      event.preventDefault(); // 이벤트 취소
      if ($("#user-name").val() == "" || $("#user-name").val() == " ") {
        alert("Invalid username");
      } else {
        $username = $("#user-name").val(); // get username
        $("#login-area").hide();
        $("#chat-area").show();

        $("#messages").html(""); // 오래된 메세지 삭제
        socket.emit("has connected", $username);
      }
    });

    $("#message-form").submit(function (event) {
      event.preventDefault();
      if ($("#message").val() == "" || $("message").val() == " ") {
        alert("메세지를 입력해주세요.");
      } else {
        socket.emit("new message", {
          username: $username,
          message: $("#message").val(),
        });
        $("#message").val(""); // Clear text area
      }
    });

    socket.on("has connected", function (data) {
      $("#users").html(""); // 유저 disconnect
      updateUsers(data.usersList);
      $("#messages").append(
        "<li><i><b>" + data.username + "</b> has connected </i></li>"
      ); // 다른 사용자 접속 알림
    });

    socket.on("has disconnected", function (data) {
      $("#users").html("");
      updateUsers(data.usersList);
      $("#messages").append(
        "<li><i><b>" + data.username + "</b> has disconnected </i></li>"
      );
    });

    socket.on("new message", function (data) {
      $("#messages").append(
        "<li><i><b>" + data.username + "</b>: " + data.message + "</i></li>"
      );
    });
  </script>
</html>

 

index.css
html {
  height: 100%;
  width: 100%;
  margin: 0;
  padding: 0;
  font-family: Verdana, Geneva, Tahoma, sans-serif;
}

body {
  height: 100%;
  width: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden;
}

#login-area {
  width: 500px;
  height: 300px;
  border: 1px solid #000;
  margin: 0 auto;
  margin-top: 150px;
}

#login-area #login-text {
  width: 100%;
  margin-top: 70px;
  text-align: center;
}

#login-area #login-form-area {
  width: 100%;
  margin-top: 40px;
  text-align: center;
}

#login-area #login-form-area #login-form #user-name {
  height: 50px;
  width: 300px;
  padding: 0px 5px;
  font-size: 26px;
  outline: none;
  outline-offset: 0;
}

#login-area #login-form-area #login-form #login-submit {
  font-size: 26px;
  background-color: transparent;
  border: 1px solid #000;
  height: 52px;
  width: 100px;
  cursor: pointer;
  outline: none;
  outline-offset: 0;
}

#login-area #login-form-area #login-form #login-submit:hover {
  background-color: #000;
  color: #fff;
}

#chat-area {
  display: none;
  widows: 100%;
  height: 100%;
}

#chat-area #users-area {
  width: 20%;
  height: 100%;
  border-top: 1px solid transparent;
  border-right: 1px solid black;
  float: left;
  background-color: #ddd;
}

#chat-area #users-area #online-users-text {
  margin: 0;
  padding: 0;
  margin-top: 50px;
  text-align: center;
}

#chat-area #users-area #online-users-text h1 {
  margin: 0;
  padding: 0;
}

#chat-area #users-area #online-users {
  margin-top: 50px;
}

#chat-area #users-area #online-users #users {
  text-align: center;
  padding: 0;
  margin: 0;
}

#chat-area #users-area #online-users #users li {
  list-style-type: none;
  font-weight: bold;
  margin-top: 10px;
}

#chat-area #message-area {
  width: calc(80% - 1px);
  height: 100%;
  float: right;
  background-color: #aaa;
}

#chat-area #message-area #display-message-area {
  width: 100%;
  height: 90%;
  border-top: 1px solid transparent;
}

#chat-area #message-area #display-message-area #messages {
  margin: 0;
  padding: 0;
}

#chat-area #message-area #display-message-area #messages li {
  list-style-type: none;
  padding: 10px;
  margin: 0;
}

#chat-area #message-area #display-message-area #messages li:nth-child(odd) {
  background-color: #eee;
}

#chat-area #message-area #message-form-area {
  width: 100%;
  height: 10%;
  border-top: 1px solid black;
}
#chat-area #message-area #message-form-area #message-form #message {
  height: 90px;
  width: 90%;
  font-size: 28px;
  padding: 0 5px;
  outline: none;
  outline-offset: 0;
  background-color: transparent;
  color: #fff;
  border: 0;
}

#chat-area
  #message-area
  #message-form-area
  #message-form
  #message::placeholder {
  color: #fff;
}

#chat-area #message-area #message-form-area #message-form #message-submit {
  height: 95px;
  width: calc(10% - 20px);
  border: 1px solid #000;
  font-size: 28px;
  background-color: transparent;
}

#chat-area
  #message-area
  #message-form-area
  #message-form
  #message-submit:hover {
  color: #fff;
  background-color: #000;
}
728x90