본문 바로가기
개발자 준비/Node.js

웹 소켓 실습

by osul_world 2021. 11. 15.
728x90

Socket.io 사용하기


+ node.js(express) 와 socket.io 모듈을 이용하여 간단한 채팅 구현하기

 

개발툴 설정

#node 설치후 잘 설치되었는지 확인
node -v
npm -v 
#express 설치
cmd (명령 프롬프트) 실행
프로젝트를 만들고자 하는 경로로 이동 [ex] cd Desktop
express --ejs (프로젝트 폴더이름) 명령어 실행 [ex] express --ejs test
프로젝트 폴더로 경로 이동 [ex] cd test
npm install 명령어 실행
#express 프로젝트 생성
cmd (명령 프롬프트) 실행
프로젝트를 만들고자 하는 경로로 이동 [ex] cd Desktop
express --ejs (프로젝트 폴더이름) 명령어 실행 [ex] express --ejs test
프로젝트 폴더로 경로 이동 [ex] cd test
npm install 명령어 실행
#nodemon 설치: 라이브 서버기능
cmd (명령 프롬프트) 실행
npm install -g  nodemon 명령어 실행
nodemon -v 명령어 실행
#실행중지 및 취소
ctrl+c

#nodemon으로 서버 실행 app.js는 메인 js파일
nodemon app.js

 

express 계층구조

계층역할
bin웹 서버 구성
node_modules설치한 npm 모듈 저장소
public리소스(javascript, image, css 등등..) 관리 저장소
routes클라이언트 리퀘스트 관리
views웹 화면 관리
app.js웹 서버 운영 관리
package-lock.json package.jsonnpm 모듈 관리

 

개발환경 설정

//app.js
//server 운영 관리

 //========================================================================================================================

//*express 모듈
const express = require("express") //node_modules에 저장된 express module
const app = express() //express 모듈을 변수 app에 저장

//*http 모듈
const http  = require('http') //웹 소켓을 사용하기위해 http 모듈이 필요: ws프로토콜은 http프로토콜을 이용한다.
const server = http.createServer(app); //express app을 http 서버로 

//*socket.io 모듈
const socketIO = require('socket.io');
const io = socketIO(server) //socket.io http 서버

//*Date()사용을 위해 moment 모듈
const moment = require("moment");


//*path 모듈: 서버 기본 시작 경로 설정
const path = require('path');
app.use(express.static(path.join(__dirname,"src")));
//console.log(__dirname); //__dirname은 현재 프로젝트 경로를 의미함


//*포트 설정 및 서버 시작 포트 지정
const PORT = process.env.PORT || 5000; //프로세스 환경 포트가 있으면 그걸 사용하고 || 아니면 5000 번
server.listen(PORT,()=>console.log(`server is running ${PORT}`)); //서버 시작시 PORT로 연결: ``(백틱)사용으로 ${} 표현식 사용

 //========================================================================================================================

//client -> server
io.on("connection",(socket)=>{
    socket.on("chatting",(param)=>{
        const {name , msg } = param; //html에서 받은 param 분해
        io.emit("chatting",{
            name: name,
            msg: msg,
            time: moment(new Date()).format("h:ss A")
        })
    }) 
})
  • 서버부분을 관리한다. 클라이언트 요청에 대한 처리 및 서버 관리

 

//chat.js
//client 관리

"ust strict" //오류최소화

const socket = io(); //client 에 socket io 모듈 불러오기

//* from index.html

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");


//* client 이밴트 처리

//client -> server: param send
function send(){
    
    const param = { //json object
        name: nickname.value,
        msg: chatInput.value
    }
    socket.emit("chatting",param); //서버에 객체 전송
}

//enterKey press event
chatInput.addEventListener("keypress",(event)=>{
    if(event.keyCode === 13){
        send();
        chatInput.value = "" //입력창 초기화
    }
})
//전송 click event
sendButton.addEventListener("click",()=>{
    send();
    chatInput.value = "" //입력창 초기화
})



//* server -> client 처리
socket.on("chatting",(param)=>{
    
    const {name,msg,time} = param; //param parsing data 분리
    const item = new LiModel(name,msg,time);
    //const item = new LiModel(param.name,param.msg,param.time);
    
    item.makeLi();
    displayContainer.scrollTo(0,displayContainer.scrollHeight); //scroll 자동 갱신
})

function LiModel(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") 
        //정보 전달자 nickname이 현재 사용자와 같으면 ls name = "sent"
        //name="send" 면 우측, received면 좌측에 float 되도록 css에서 설계

        const dom = `<span class="profile">
        <span class="user">${this.name}</span>
        <img class="image" src="" alt="any">
        </span>
        <span class="message">${this.msg}</span>
        <span class="time">${this.time}</span>`;
        
        li.innerHTML = dom;
        chatList.appendChild(li) //display에 표기
    }

}
  • 서버로 부터 받은 응답을 처리하고, 클라이언트 HTML구조를 필요에 맞게 변경한다.
  • 채팅창 display는 css를 통해 구현한다.

 

ETC

//package.json

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "nodemon app.js" //이와 같이 명령어 스크립트를 생성해서 간단히 사용가능
  },
      
//terminal에서 nodemon app.js를 npm start로 실행가능 긴 문장을 짧게 사용하도록 할수있다
#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"> <!--왜 src는 안돼는거지?-->
</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">
        //node_modules에 있는 soket.io/socket.io.js 파일을 로드
    </script>

    <script src="js/chat.js"> //chat.js 불러오기
    </script>
</body>
</html>
#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: center;
    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: 03rem;
    display:flex;
    justify-content: flex-start;
    align-items: flex-end;
    margin-top: 0.5rem;
}

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

.sent .message {
    background: darkorange;
}

.received .message{
    background: deepskyblue;
}


.profile {
    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;
}

 

 

728x90

'개발자 준비 > Node.js' 카테고리의 다른 글

Node.js 특징  (0) 2021.11.15
JS  (0) 2021.11.15
Node.js란?  (0) 2021.11.08