Node.js 및 Socket.io로 간단한 채팅 앱 구축

39726 단어 nodejavascriptexpress
채팅 앱을 구축하는 방법을 찾고 있지만 모든 것을 설명하는 간단한 자습서를 찾는 데 어려움을 겪고 있습니까?

이것은 당신에게 딱 맞는 기사입니다!

이것은 우리가 만들 것의 미리보기입니다.



부인 성명



이 기사에서는 채팅 뒤에 있는 논리를 다룰 것이며 모든 스타일링 부분을 다루지는 않을 것입니다. css 파일이 필요한 경우 기사 끝에 github repo 링크를 추가하겠습니다.

설정



나는 당신이 npm과 노드를 설치했고 그것들이 어떻게 작동하는지 알고 있다고 가정합니다(최소한 기본 사항). Javascript에 대한 기본 지식이 필요합니다.
시작하겠습니다.

애플리케이션용 디렉터리를 생성하고 즐겨 사용하는 편집기로 디렉터리를 엽니다.

mkdir chatApplication && cd client

다음으로 디렉토리를 Nodejs 애플리케이션으로 초기화하겠습니다.

npm init -y

이제 이 앱을 빌드하는 데 필요한 모든 종속 항목을 설치해 보겠습니다.

npm i express randomcolor socket.io uuid

그리고 개발 종속성으로 소스의 변경 사항을 모니터링하고 서버를 자동으로 다시 시작하는 유틸리티인 nodemon을 설치합니다.

npm i -D nodemon

서버 측 구축



간단한 익스프레스 서버인 app.js 파일(메인 폴더에 있음)에 서버 측 로직을 보관합니다.

//app.js

const express = require('express');
const app = express();
let randomColor = require('randomcolor');
const uuid = require('uuid');

//middlewares
app.use(express.static('public'));

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

//Listen on port 5000
server = app.listen( process.env.PORT || 5000);


이제 서버가 준비되었으므로 socket.io 로직 작업을 시작하겠습니다. 우선 socket.io를 인스턴스화해야 합니다. 이후 io는 모든 연결을 수신합니다. 사용자가 연결되면 소켓은 다음 이벤트를 수신합니다.

  • change_username: 사용자 이름 가져오기 및 보내기

  • new_message: 사용자의 새 메시지를 듣습니다
  • .

  • 연결 해제: 사용자가 채팅에서 연결 해제될 때 수신 대기

  • 그럼 작동하도록 코드를 작성해 봅시다!

    //app.js
    
    //socket.io instantiation
    const io = require("socket.io")(server);
    
    const users = [];
    const connnections = [];
    
    //listen on every connection
    io.on('connection', (socket) => {
        console.log('New user connected');
        //add the new socket to the connections array
        connnections.push(socket)
        //initialize a random color for the socket
        let color = randomColor();
    
        //Set the first username of the user as 'Anonymous'
        socket.username = 'Anonymous';
        socket.color = color;
    
        //listen on change_username
        socket.on('change_username', data => {
            let id = uuid.v4(); // create a random id for the user
            socket.id = id;
            socket.username = data.nickName;
            users.push({id, username: socket.username, color: socket.color});
            updateUsernames();
        })
    
        //update Usernames in the client
        const updateUsernames = () => {
            io.sockets.emit('get users',users)
        }
    
        //listen on new_message
        socket.on('new_message', (data) => {
            //broadcast the new message
            io.sockets.emit('new_message', {message : data.message, username : socket.username,color: socket.color});
        })
    
        //Disconnect
        socket.on('disconnect', data => {
    
            if(!socket.username)
                return;
            //find the user and delete from the users list
            let user = undefined;
            for(let i= 0;i<users.length;i++){
                if(users[i].id === socket.id){
                    user = users[i];
                    break;
                }
            }
            users.splice(user,1);
            //Update the users list
            updateUsernames();
            connnections.splice(connnections.indexOf(socket),1);
        })
    })
    

    randomColor()가 무엇인지 궁금하다면 프론트엔드 측을 언제 덮을지 알게 될 것입니다.

    프런트 엔드 쪽



    따라서 프런트 엔드는 매우 쉽고 html 파일과 두 개의 javascript 파일(및 이 튜토리얼에서 다루지 않을 css 파일)로만 구성됩니다.
    클라이언트 폴더로 이동하여 index.html, chat.js, modalScript.js 및 style.css를 보관할 css 폴더를 생성합니다.
    index.html은 처음 렌더링할 때 사용자 이름을 가져오는 모달이 있고 다른 항목의 경우 반응성을 높이기 위해 flexbox를 사용합니다.

    <!--index.html-->
    
    <!DOCTYPE html>
    <html>
    <head>
        <meta http-equiv="Content-Type" const="text/html;charset=UTF-8" />
        <link href="http://fonts.googleapis.com/css?family=Comfortaa" rel="stylesheet" type="text/css">
        <link rel="stylesheet" type="text/css" href="css/style.css" >
        <!--Socket.io scirpt-->
        <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.js"></script>
        <title>Simple Chat App</title>
    </head>
    
    <body>
        <!-- The Modal -->
        <div id="myModal" class="modal">
    
            <!-- Modal content -->
            <div class="modal-content">
                <h1 class="modal-title">What's your nickname?</h1>
                <input id="nickname-input" class="custom-input" type="text" />
            </div>
    
        </div>
    
        <!--Big wrapper-->
        <div class="big-wrapper">
            <!-- Left Column-->
            <div class="online-user-wrapper">
                <div class="online-user-header-container">
                    <header>
                        <h2>Online Users</h2>
                    </header>
                </div>
                <div>
                    <!--Online users goes here-->
                    <ul id="users-list">
    
                    </ul>
                </div>
            </div>
            <!--Chat Wrapper -->
            <div class="chat-wrapper">
                <div class="super-chat-title-container">
                    <header>
                        <h1>Chat</h1>
                    </header>
                </div>
    
                <!--Messages container-->
                <div id="chatroom">
                    <!--x is typing goes here-->
                    <div id="feedback"></div>
                </div>
    
                <!-- Input zone -->
                <div id="input_zone">
                    <input id="message" class="vertical-align custom-input" type="text" />
                    <button id="send_message" class="vertical-align btn" type="button">Send</button>
                </div>
    
            </div>
        </div>
        <!--jQuery script-->
        <script src="http://code.jquery.com/jquery-latest.min.js"></script>
        <!--Scripts-->
        <script src="./chat.js"></script>
        <script src="./modalScript.js"></script>
    </body>
    </html>
    

    index.html을 그대로 두면 모달이 사라지지 않으므로 처리할 자바스크립트를 추가해야 합니다.

    //modalScript.js
    
    // Get the modal
    var modal = document.getElementById("myModal");
    const nicknameInput = document.getElementById("nickname-input");
    
    // Close modal when nick-name is typed
    nicknameInput.onkeypress = e => {
        let keycode = (e.keyCode ? e.keyCode : e.which);
        if(keycode == '13'){
            modal.style.display = "none";
        }
    };
    

    백엔드가 이벤트를 수신하는 경우 프런트엔드에서 이러한 이벤트를 보내야 합니다. 우리는 이러한 이벤트 생각을 chat.js 파일로 보낼 것입니다. 예를 들어 새로운 사용자가 앱에 들어올 때 우리는 그것을 듣고 사용자 이름을 가져와서 백엔드로 보내야 합니다.

    //chat.js file
    
    $(function () {
        //make connection
        let socket = io.connect('http://localhost:5000');
    
        //buttons and inputs
        let message = $("#message");
        let send_message = $("#send_message");
        let chatroom = $("#chatroom");
        let feedback = $("#feedback");
        let usersList = $("#users-list");
        let nickName = $("#nickname-input");
    
            //Emit typing
        message.bind("keypress", e => {
            let keycode = (e.keyCode ? e.keyCode : e.which);
            if(keycode != '13'){
                socket.emit('typing')
            }
        });
    

    메시지



    당신이 메시지에 대해 짐작했듯이 같은 원리입니다!

    //chat.js
    
    $(function () {
        //make connection
        let socket = io.connect('http://localhost:5000');
    
        //buttons and inputs
        let message = $("#message");
        let send_message = $("#send_message");
        let chatroom = $("#chatroom");
        let feedback = $("#feedback");
        let usersList = $("#users-list");
        let nickName = $("#nickname-input");
    
        //Emit message
        // If send message btn is clicked
        send_message.click(function(){
            socket.emit('new_message', {message : message.val()})
        });
        // Or if the enter key is pressed
        message.keypress( e => {
            let keycode = (e.keyCode ? e.keyCode : e.which);
            if(keycode == '13'){
                socket.emit('new_message', {message : message.val()})
            }
        })
    
        //Listen on new_message
        socket.on("new_message", (data) => {
            feedback.html('');
            message.val('');
            //append the new message on the chatroom
            chatroom.append(`
                            <div>
                                <div class="box3 sb14">
                                  <p style='color:${data.color}' class="chat-text user-nickname">${data.username}</p>
                                  <p class="chat-text" style="color: rgba(0,0,0,0.87)">${data.message}</p>
                                </div>
                            </div>
                            `)
            keepTheChatRoomToTheBottom()
        });
    
        //Emit a username
        nickName.keypress( e => {
            let keycode = (e.keyCode ? e.keyCode : e.which);
            if(keycode == '13'){
                socket.emit('change_username', {nickName : nickName.val()});
                socket.on('get users', data => {
                    let html = '';
                    for(let i=0;i<data.length;i++){
                        html += `<li class="list-item" style="color: ${data[i].color}">${data[i].username}</li>`;
                    }
                    usersList.html(html)
                })
            }
        });
    
    });
    
    // function thats keeps the chatbox stick to the bottom
    const keepTheChatRoomToTheBottom = () => {
        const chatroom = document.getElementById('chatroom');
        chatroom.scrollTop = chatroom.scrollHeight - chatroom.clientHeight;
    }
    

    타자



    채팅 앱을 완성하려면 모든 채팅 앱에 있는 기능을 추가해야 합니다. 그것을 구현하는 것은 매우 쉽습니다.
    우리의 chat.js 파일에서 우리는 당신이 타이핑하고 있을 때 내보내고 다른 사용자들이 타이핑하고 있을 때 리스닝해야 합니다.
    다음 몇 줄의 코드를 추가해 보겠습니다.

        //Emit typing
        message.bind("keypress", e => {
            let keycode = (e.keyCode ? e.keyCode : e.which);
            if(keycode != '13'){
                socket.emit('typing')
            }
        });
    
        //Listen on typing
        socket.on('typing', (data) => {
            feedback.html("<p><i>" + data.username + " is typing a message..." + "</i></p>")
        });
    

    app.js 파일에 있는 동안 사용자가 입력하고 있는 것을 브로드캐스트하고 싶습니다. 다음 세 줄의 코드를 추가하기만 하면 됩니다.

        //listen on typing
        socket.on('typing', data => {
            socket.broadcast.emit('typing',{username: socket.username})
        })
    

    결론



    이것이 우리 앱의 끝입니다. 보시다시피 매우 간단하고 빌드하기 전에 생각했던 것처럼 많은 코드가 필요하지 않습니다.
    자유롭게 문제와 버그를 보고하고 이 코드를 개선하여 더 좋게 만드세요.
    그것이 Github 저장소입니다.


    파올로델리아99 / 단순 노드 채팅 앱


    node.js 및 socket.io로 구축된 간단한 채팅 앱

    좋은 웹페이지 즐겨찾기