Node js + Express + Socket.io 로 1대 1 채팅 구현하기 (1)

2021. 3. 14. 01:03·DEV/Node.js

github.com/jokj624/CustomEmojiChatting

 

jokj624/CustomEmojiChatting

Media Interface Lab 2020-2 프로젝트 중 일부인 커스텀 이모티콘 채팅 프로토타입 코드 입니다. - jokj624/CustomEmojiChatting

github.com

프로토타입 채팅 전체 코드는 위 깃헙 저장소에 있습니다.


 

블로그 스킨을 오랜만에 바꾼김에 쓰자쓰자 해놓고 맨날 미룬 채팅 구현방법 포스팅을 작성하려합니다.

연구실에서 진행한 프로토타입인데 이 중에 1대 1 채팅을 구현하는 방법만 빼서 소개해보려 합니다.

1편은 텍스트 채팅에 대해서만 설명해보고, 2편에서 이모티콘(나는 특정 목적 때문에 이모티콘이었고, 사실 그냥 이미지 전송이다) 이미지를 Multer-s3 , AWS S3를 이용해 전송해보는 법을 설명해보려합니다.

 

** 저도 하나하나 구글링해가고, 책을 통해 찾아가며 구현한 거라 정확하지 않거나 비효율적일 수도 있습니다. 다 같이 공부해나가는 학생이니까 이해 부탁 dream

 

1. 최종 구현 화면 (텍스트 채팅)

짜잔 진짜 카톡 같죠? 아님 말구요.

아무튼 이런식으로 두개의 브라우져에서 실시간으로 채팅이 가능합니다.

이걸 잘 활용하신다면 후에 다른 웹에 채팅을 추가하거나 쪽지 대화 이런 기능을 추가할 수 있을 듯 합니다.

 

2. Dependencies

"dependencies": {
    "aws-sdk": "^2.834.0",
    "express": "^4.17.1",
    "multer": "^1.4.2",
    "multer-s3": "^2.9.0",
    "ngrok": "^3.4.0",
    "socket.io": "^3.0.5"
  }

이 중에서 텍스트 채팅만 사용하신다면 express + socket.io 만 있으면 됩니다! 

설치 법은 

npm install --save express
npm install --save socket.io

3. Node js + Express 로 서버 생성 + Socket.io로 웹 소켓 사용

Project__ package.json

           |__ node_modules

           |__ server.js

           |__ public ___ index.html 

                           |___ customemoji.js (채팅 js) 

                           |___ customemoji.css 

 

구조를 이런식으로 잡았습니다. 

 

server.js 코드를 봅시다.

 

const express = require('express');
const app = express(); 
app.set('port', process.env.PORT || 4000);

express 모듈을 실행해 app 변수에 할당해줍시다.

서버가 실행될 포트를 4000으로 설정합니다.

app.use(express.static(__dirname + '/public'));

static 미들웨어는 정적 파일들을 제공하는 라우터 역할을 합니다. 따라서 우리가 만든 public 폴더 내부에 정적인 파일 (js,html,css,image 등) 을 두고 express 객체 안에서 static을 꺼내쓰면 됩니다.

책에 따르면

public/css/style.css는 http://localhost:3000/css/style.css 로 접근한다고 합니다.

실제 요청 주소에는 public이 없는데 이는 보안상의 이유라고 합니다. 외부인이 쉽게 구조를 파악할 수 없게 하기 위해서래요.

const socket = require('socket.io');
const http = require('http');
const server = http.createServer(app);
const io = socket(server); 

server.listen(4000, function() {
    console.log('Server On !');
});

실시간 통신을 위해서는 웹 소켓을 사용해야합니다. 편리하게 사용 할 수 있는 Socket.io를 사용합시다.

io 객체를 통해 다양한 소켓 이벤트를 구현할 수 있습니다.

 

let socketList = [];

io.on('connection', function(socket) {
    socketList.push(socket);
    console.log('User Join');
 
    socket.on('SEND', function(msg) {
        socketList.forEach(function(item, i) {
            console.log(item.id);
            if (item != socket) {
                item.emit('SEND', msg);
            }
        }); 
    });
    
    ...
    
 }

connection 은 클라이언트가 접속했을 때 발생하는 이벤트 리스너 입니다.

콜백함수에는 socket 객체를 사용할 수 있습니다.

socketList 배열은 단체 채팅일 때 사용자를 구분하기 위해 필요한데 사실 지금은 일대일 채팅이라 무의미합니다.

단체 채팅일 경우 socketList 에 socket을 넣어 후에 구분이 가능합니다.

브라우저가 열릴 때마다 (사용자가 들어올 때 마다) 콘솔에 User join이 찍힙니다.

socket.on('SEND', function(msg) {
        socketList.forEach(function(item, i) {
            console.log(item.id);
            if (item != socket) {
                item.emit('SEND', msg);
            }
        }); 
    });

SEND 이벤트를 보면 자신이 메세지를 송신할 시 자신을 제외한 다른 모두에게 emit 메서드로 메시지를 보내게 됩니다.

socket.on('disconnect', function() {
        socketList.splice(socketList.indexOf(socket), 1);
});

연결이 종료되면 socketList에서 없애줍니다.

 

전체코드 (이미지는 다음편에)
const express = require('express');
const socket = require('socket.io');
const upload = require('./multer');

const app = express(); 
app.set('port', process.env.PORT || 4000);

const http = require('http');
const server = http.createServer(app);
const io = socket(server); 

let socketList = [];

app.use(express.static(__dirname + '/public'));

server.listen(4000, function() {
    console.log('Server On !');
});

io.on('connection', function(socket) {
    socketList.push(socket);
    console.log('User Join');
 
    socket.on('SEND', function(msg) {
        socketList.forEach(function(item, i) {
            console.log(item.id);
            if (item != socket) {
                item.emit('SEND', msg);
            }
        }); 
    });
    ...중략
    
    socket.on('disconnect', function() {
        socketList.splice(socketList.indexOf(socket), 1);
    });
}

 4. html + js

채팅화면은 어느정도 알아서 구현하실 거라 생각하기에 자바 스크립트 위주로 설명할게요. 

<form id = "chatform" onsubmit="return false">
	<div style="display: inline-block;">
		<input type="text" id="input_box" contenteditable="true" autocomplete="off">
    </div>
	<input type = "submit" id="sendmsg"  class="btn btn-warning btn-sm" value="Send">
    
    ... 중략
    
</form>

html 은 이런식의 form 구조를 가지고 있습니다.

 

var msgText = $('#input_box');
  
  if (msgText.val() == '') {
      return;
  } else {
    socket.emit('SEND', msgText.val());
      var msgLine = $('<div class="msgLine">');
      var msgBox = $('<div class="me">');
 
      msgBox.append(msgText.val());
      msgBox.css('display', 'inline-block');
      msgLine.css('text-align', 'right');
      msgLine.append(msgBox);
 
      $('#msg').append(msgLine);
      msgText.val('');
      chatView.scrollTop = chatView.scrollHeight;
    }
  });

form을 제출할 시 입력한 글자를 input_box에서 가지고 와서 socket.emit을 통해 보내주면 됩니다.

이미 server.js에서 이벤트를 구현해놨기 때문에 바로 호출해주시면 됩니다.

밑에는 제 화면에서 제가 송신한 텍스트를 오른쪽에 예쁘게 보여주기 위해 사용한 코드입니다.

 

socket.on('SEND', function(msg) {
    var msgLine = $('<div class="msgLine">');
    var msgBox = $('<div class="msgBox">');

    msgBox.append(msg);
    msgBox.css('display', 'inline-block');

    msgLine.append(msgBox);
    $('#msg').append(msgLine);
}

SEND 이벤트로 수신 시에는 마찬가지로 왼쪽에 보여주게끔 했습니다.

전체 코드
chatForm.addEventListener('submit', function() {
  var msgText = $('#input_box');
  
  if (msgText.val() == '') {
      return;
  } else {
    socket.emit('SEND', msgText.val());
      var msgLine = $('<div class="msgLine">');
      var msgBox = $('<div class="me">');
 
      msgBox.append(msgText.val());
      msgBox.css('display', 'inline-block');
      msgLine.css('text-align', 'right');
      msgLine.append(msgBox);
 
      $('#msg').append(msgLine);
      msgText.val('');
      chatView.scrollTop = chatView.scrollHeight;
    }
});

socket.on('SEND', function(msg) {
    var msgLine = $('<div class="msgLine">');
    var msgBox = $('<div class="msgBox">');

    msgBox.append(msg);
    msgBox.css('display', 'inline-block');

    msgLine.append(msgBox);
    $('#msg').append(msgLine);

    chatView.scrollTop = chatView.scrollHeight;
});

 

5. 마무리

이렇게 까지만 하셔도 실시간 텍스트 채팅이 가능합니다!!

저도 오랜만에 다시 열어보니 참 코드를 비효율적으로 작성한 것 같아 반성하게 되네요.

이때는 사실 오랜만에 자바스크립트 만져서 es6문법도 잘 몰랐거든요 var만 주구장창 쓴거 보이시죠. 이러지 마세요.

(지금은 그래도 es6문법에 어느정도 적응했답니다)

지금 짜라하면 이렇게 안짜지~ 

 

이 글을 보신다면 꼭 붙여넣기 하지 마시고 더 좋은 코드로 다듬어 보세요!

저도.. 졸업 작품 끝나고 채팅 코드를 더 수정해봐야겠어요.

 

저작자표시 비영리 변경금지 (새창열림)

'DEV > Node.js' 카테고리의 다른 글

[CI/CD] AWS CodeDeploy, CodePipeline 으로 node.js, ec2, git 배포 자동화하기  (4) 2021.12.16
[Node.js] Express, TypeScript, MongoDB 회원가입 (1)  (3) 2021.06.18
Node.js , express, mongoDB, typescript 초기 설정  (0) 2021.05.26
Node.js + Koa + Typescript 로 슬랙 봇 개발해보기 (1)  (0) 2021.04.19
React, Mongoose(MongoDB), Node js 게시판 검색 구현  (2) 2021.03.13
'DEV/Node.js' 카테고리의 다른 글
  • [Node.js] Express, TypeScript, MongoDB 회원가입 (1)
  • Node.js , express, mongoDB, typescript 초기 설정
  • Node.js + Koa + Typescript 로 슬랙 봇 개발해보기 (1)
  • React, Mongoose(MongoDB), Node js 게시판 검색 구현
jobchae
jobchae
말하는 감자지만, 코드를 끄적이는 Node.js 백엔드 개발자입니다.
  • jobchae
    JOBCHAE
    jobchae
  • 전체
    오늘
    어제
    • 🚀 JOBCHAE (182)
      • DEV (151)
        • PS (108)
        • Node.js (12)
        • React (3)
        • docker (1)
        • 잡다한 개발 일지 (21)
        • injection (1)
        • JS, TS (3)
        • DB (2)
      • 축구 (0)
      • 일상 (19)
      • 영화 (3)
      • 음악 (8)
  • 블로그 메뉴

    • 💻 Github
    • 🙋🏻 Linkedin
    • 📖 방명록
  • 링크

    • PS Github
  • 공지사항

  • 인기 글

  • 태그

    nodejs
    슬랙봇
    우선순위큐
    db
    이분탐색
    BFS
    Nest.js
    리액트
    mongoDB
    typescript
    슬랙
    DP
    위상정렬
    앱잼
    node.js
    렛츠락페스티벌
    PS
    boj
    JavaScript
    SOPT
    react
    백준
    솝트
    Express
    DFS
    개발
    회고
    GitHub
    알고리즘
    일상
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
jobchae
Node js + Express + Socket.io 로 1대 1 채팅 구현하기 (1)
상단으로

티스토리툴바