카테고리 없음

websocket 으로 채팅 만들기

seongjin08 2021. 12. 28. 02:00

$ npm init

$ npm install express moment socket.io

app.js  파일 생성 후  server 실행시 html 을 불러오기 위한 작업을 한다.

__dirname 을 console.log 로 찍어 보면 이렇게 주수가 나온다.

path.join() 을 쓰는 이유는 운영체제마다 주소의 슬레시 역슬레시가 다르기 

때문에 사용한다.

server 에서 socket.io 셋팅을 해야한다.

socket.io 는 http 을 이용해서 통신해야되기 때문이 사진과 같이 io 변수에 셋팅을 해준후

io에  on() 함수를 사용해서 connection 이라는 method을 이용해서 cnnection 이 이루어지면 실행하게 

작업한다.

 

index.html 파일에서 socket.io 파일을 연결해보자.

express 앱을 사용하고 있으니 절대 경로를 활용해서 nodemodules 파일에 있는 socket.io 를 가져올수있다.

socket.io.js 파일을 제데로 불러오는지 확인해보자!

웹에서 console 에 에러가 뜨지 않으면 잘 불러오는 거다.

만약 불러오지 못한다면 

https://cdnjs.com/

 

cdnjs - The #1 free and open source CDN built to make life easier for developers

Simple. Fast. Reliable. Content delivery at its finest. cdnjs is a free and open-source CDN service trusted by over 12.5% of all websites, serving over 200 billion requests each month, powered by Cloudflare. We make it faster and easier to load library fil

cdnjs.com

cdnjs 에서 socket.io 를 검색하고 copy script tag 를 클릭하여 복붙하면 된다.

javascript 코드를 사용하기 위한 js 파일을 따로 만들고 연결한다.

chat.js 파일을 만들고

이렇게 코드를 작성하면 server 와 연결이 된다.

emit 은 보내기 위함 method 이고 첫번째 인자값은 연결할 ID 가 오면 되고 두번째 인자값은 보낼 값을 적어주면 된다.

 

app.js

on() method 를 사용해서 값을 받을수 있다.

첫번째 인자값은 똑같이 연결할 인자값을 주고 두번째인자값은 애로우 함수를 이용해 받은 값을

consol.log 로 찍어보자.

io.emit  method 를 사용해서 답변을 해보자.

 

chat.js

chat.js 파일에서 on method 를 사용해서 값을 받아온걸 찍어보자

웹에서 확인가능하다.

이렇게 하면 기본적인 주고 받는 셋팅이 준비 된것이다.

 

app.js

const express = require('express');
const http = require('http')
const app = express();
const path = require('path')
const server = http.createServer(app)
const socketIO = require('socket.io');
const moment = require('moment')
const io = socketIO(server)

app.use(express.static(path.join(__dirname, "src")))

const PORT = process.env.PORT || 3000;

io.on("connection", (socket) => {
    socket.on("chatting", (data) => {
        const { name, msg } = data;
        io.emit("chatting", {
            name,
            msg,
            time: moment(new Date()).format("h:ss A")
        })
    })
})

server.listen(PORT, () => {
    console.log(`server start ${PORT}`);
})

index.html

< !DOCTYPE html >
    <html lang="en">

        <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>Document</title>
                        <link rel="stylesheet" href="css/style.css">
                        </head>

                        <body>
                            <div class="wrapper">
                                <div class="user-container">
                                    <label for="nickname">대화명</label>
                                    <input type="text" id="nickname">
                                </div>
                                <div class="display-container">
                                    <ul class="chatting-list">

                                    </ul>
                                </div>
                                <div class="input-container">
                                    <span>
                                        <input type="text" class="chatting-input">
                                            <button class="send-button">전송</button>
                                    </span>
                                </div>
                            </div>

                            <script src="/socket.io/socket.io.js"></script>
                            <script src="js/chat.js"></script>
                        </body>
                    </html>

chat.js

const socket = io();

const nickname = document.querySelector("#nickname");
const chatlist = document.querySelector('.chatting-list');
const chatInput = document.querySelector('.chatting-input');
const sendButton = document.querySelector('.send-button');
const displayContainer = document.querySelector('.display-container')

chatInput.addEventListener("keypress", (event) => {
    if (event.keyCode === 13) {
        send()
        chatInput.value = ""
    }
})

function send() {
    const param = {
        name: nickname.value,
        msg: chatInput.value
    }
    socket.emit("chatting", param)
}

sendButton.addEventListener("click", send)

socket.on("chatting", (data) => {
    const { name, msg, time } = data
    const item = new LiModle(name, msg, time)
    item.makeLi()
    displayContainer.scroll(0, displayContainer.scrollHeight)
})

function LiModle(name, msg, time) {
    this.name = name;
    this.msg = msg;
    this.time = time;

    this.makeLi = () => {
        const li = document.createElement("li")
        li.classList.add(nickname.value === this.name ? "sent" : "received")
        const dom = `<span class="profile">
<span class="user">${this.name} </span>
<img class="image" src="https://placeimg.com/200/50/any">
</span>
<span class="message">${this.msg}</span>
<span class="time">${this.time}</span>`;
        li.innerHTML = dom;
        chatlist.appendChild(li)
    }
}

style.css

* {
    margin: 0;
    padding: 0;
}

html,
body {
    height: 100%;
}

.wrapper {
    height: 100%;
    width: 100%;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.user-container {
    background: #a9bdce;
    flex: 1;
    display: flex;
    justify-content: flex-start;
    align-items: center;
    padding: 0.5rem;
}

.user-container label {
    font-size: 14px;
    margin-right: 1rem;
}

.user-container input {
    border-radius: 3px;
    border: none;
    height: 100%;
}

.display-container {
    flex: 12;
    background: #b2c7d9;
    overflow-y: scroll;
}

.input-container {
    flex: 1;
    display: flex;
    justify-content: stretch;
    align-items: center;
}

.input-container span {
    display: flex;
    justify-content: flex-start;
    align-items: cneter;
    padding: 0.3rem;
    width: 100%;
}

.chatting-input {
    font-size: 12px;
    height: 100%;
    flex: 8;
    border: none;
}

.send-button {
    flex: 1;
    background: #ffeb33;
    border: none;
    height: 100%;
    border-radius: 3px;
}


.chatting-list li {
    width: 90%;
    padding: 0.3rem;
    display: flex;
    justify-content: flex-start;
    align-items: flex-end;
    margin-top: 0.5rem;
}

.proffile {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}

.profile .user {
    font-size: 10px;
    margin-bottom: 0.3rem;
}


.profile .image {
    border-radius: 50%;
    object-fit: cover;
    width: 50px;
    height: 50px;
}

.message {
    border-radius: 5px;
    padding: 0.5rem;
    font-size: 12px;
    margin: 0 5px;
    flex: 7;
}


.time {
    font-size: 10px;
    margin: 0 5px;
}

.sent {
    flex-direction: row-reverse;
    float: right;
}


.sent .message {
    background: #ffeb33;
}

.received .message {
    background: #fff;
}

 

 이렇게 작동하는 것을 확인할수 있다.