socket 실시간 채팅 만들기

woo ki·2023년 1월 25일

JavaScript

목록 보기
3/9

노마드 코더

노마드 코더에서 줌 클론 코딩을 조금 배웠다. 줌을 만들면서 socket을 이용해서 실시간 채팅을 만들었다. 여기서 배운 것 토대로 요즘 혼자 웹페이지 프로젝트에 추가시키고 싶어서 만들게 되었습니다. 시작해 보겠습니다.

실시간 채팅 환경 셋팅

일단 실시간 채팅을 만들기 위해서는 백엔드 즉 서버가 필요하다. 그래서 이번 백엔드는 Node.js를 사용해서 벡엔드를 만들고 socket.io와 Express를 설치하여 기본적인 환경 셋팅을 마치고 마지막으로 설치가 잘 되었는지 확인한다.

서버 셋팅

app.js를 하나 만들어 서버셋팅을 한다.

/* 설치한 express 모듈 불러오기 */
const express = require('express')

/* 설치한 socket.io 모듈 불러오기 */
const socket = require('socket.io')

/* Node.js 기본 내장 모듈 불러오기 */
const http = require('http')

/* Node.js 기본 내장 모듈 불러오기 */
const fs = require('fs')

/* express 객체 생성 */
const app = express()

/* express http 서버 생성 */
const server = http.createServer(app)

/* 생성된 서버를 socket.io에 바인딩 */
const io = socket(server)

app.use('/css', express.static('./static/css'))
app.use('/js', express.static('./static/js'))

/* Get 방식으로 / 경로에 접속하면 실행 됨 */
app.get('/', function(request, response) {
  fs.readFile('./static/index.html', function(err, data) {
    if(err) {
      response.send('에러')
    } else {
      response.writeHead(200, {'Content-Type':'text/html'})
      response.write(data)
      response.end()
    }
  })
})

/

/* 서버를 5500 포트로 listen */
server.listen(5500, function() {
  console.log('서버 가동 중')
})


서버 셋팅을 해서 서버를 실행하니 서버가 실행이 된다. 서버 포트는 5500으로 설정했다. 이제 서버를 만들었으니 채팅방을 셋팅해보겠습니다.

채팅방 셋팅

index.html 파일을 하나 만들어 기본적인 셋팅만 해줍니다.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>채팅</title>
    <link rel="stylesheet" href="/css/index.css">
    <script src="/socket.io/socket.io.js"></script>
    <script src="/js/index.js"></script>
  </head>
  <body>
    <div id="main">
      <div id="chat-log">
      </div>
      <form id="messaging-form" action="">
        <input type="text" id="my-message" placeholder="enter message" autocomplete="off" onkeyup="checkTyping()">
        <button onclick="send()">전송</button>
        <p>
          <span class="notification"></span>
        </p>
      </form>
    </div>
  </body>
  </html>

이제 index.js를 만들어서 채팅방의 기능적인 부분을 만들겠습니다.
index.js

const socket = io();

socket.on('connect', () => {
  const nickname = prompt('안녕하세요 닉네임을 설정해주세요.');
  
  if (!nickname) {
    socket.emit('newUser', 'Guest');
  } else {
    socket.emit('newUser', nickname);
  }
});

socket.on('typing', (data) => {
  const notification = document.querySelector('.notification');

  if (data.numOfTyper - 1) {
    notification.innerHTML = `${data.numOfTyper - 1} besides ${data.nickname} are typing.`;
  } else {
    notification.innerHTML = `${data.nickname} is typing.`
  }
});

socket.on('stop typing', (numOfTyper) => {
  const notification = document.querySelector('.notification');

  if (!numOfTyper) {
    notification.innerHTML = '';
  }
});

socket.on('update', (data) => {
  const chat = document.getElementById('chat-log');

  const message = document.createElement('div');
  const className = data.type;
  let node = null;
  if (data.nickname) {
    node = document.createTextNode(`${data.nickname}: ${data.message}`);
  } else {
    node = document.createTextNode(`${data.message}`);
  }

  message.classList.add(className);
  message.appendChild(node);
  chat.appendChild(message);
});

const send = () => {
  const messageInputForm = document.getElementById('messaging-form');
  const input = document.getElementById('my-message');

  const chatLog = document.getElementById('chat-log');
  const messageBox = document.createElement('div');
  const node = document.createTextNode(input.value);

  messageBox.classList.add('myMessage');
  messageBox.appendChild(node);
  chatLog.appendChild(messageBox);

  messageInputForm.addEventListener('submit', (event) => {
    event.preventDefault();
    if (input.value) {
      socket.emit('message', {
        type: 'otherMessage',
        message: input.value
      });

      socket.emit('stop typing');
      input.value = '';
    }
  });
};

const checkTyping = () => {
  const messageInputForm = document.getElementById('messaging-form');
  const input = document.getElementById('my-message').value;

  messageInputForm.addEventListener('keyup', (event) => {
    if (input) {
      socket.emit('typing');
    } else {
      socket.emit('stop typing');
    }
  });
}

원하던 기능은 닉네임을 만들어서 익명으로 서로의 정보를 실시간으로 공유하는 형태의 대화방을 만들고 싶었습니다. 제가 지금 만들고 있는 사이트는 여행지의 기록이나 좋은 여행지를 실시간으로 물어서 정보를 공유해야 하기 때문에 닉네임을 만들고 실시간 채팅을 구현했습니다.

app.js에도 서버에 닉네임을 저장하고 메시지를 저장해서 상대방한테 보여주게 서버를 셋팅했습니다.

io.sockets.on('connection', function(socket) {

  /* 새로운 유저가 접속했을 경우 다른 소켓에게도 알려줌 */
  socket.on('newUser', function(name) {
    console.log(name + ' 님이 접속하였습니다.')

    /* 소켓에 이름 저장해두기 */
    socket.name = name

    /* 모든 소켓에게 전송 */
    io.sockets.emit('update', {type: 'connect', name: 'SERVER', message: name + '님이 접속하였습니다.'})
  })

  /* 전송한 메시지 받기 */
  socket.on('message', function(data) {
    /* 받은 데이터에 누가 보냈는지 이름을 추가 */
    data.name = socket.name
    
    console.log(data)

    /* 보낸 사람을 제외한 나머지 유저에게 메시지 전송 */
    socket.broadcast.emit('update', data);
  })

  /* 접속 종료 */
  socket.on('disconnect', function() {
    console.log(socket.name + '님이 나가셨습니다.')

    /* 나가는 사람을 제외한 나머지 유저에게 메시지 전송 */
    socket.broadcast.emit('update', {type: 'disconnect', name: 'SERVER', message: socket.name + '님이 나가셨습니다.'});
  })
})

채팅창 오픈

이제 한번 서버를 실행시키고 채팅이 되는지 실행해보겠습니다.

서버를 실행하고 5500포트에 들어가니 닉네임창이 먼저 나오네요.
닉네임을 한번 정해볼까요? 익명이니 아무 닉네임을 정햇습니다.

닉네임을 잘 인식하군요. 다행입니다.
길어지니 2탄으로 제작하여 채팅구현은 2탄에서 뵙겠습니다.

profile
안녕하세요. 깃허브 주소는 : https://github.com/gosuuk 입니다.

0개의 댓글