SeSAC 웹풀스택 14주차 | Socket.io

hatban·2023년 3월 1일
0

소켓

  • 프로세스가 네트워크로 데이터를 내보내거나 데이터를 받기위한 실제적인 창구 역할
  • 서버와 클라이언트를 연결하는 도구로써 인터페이스 역할을 함
  • 서버 : 클라이언트 소켓의 연결 요청을 대기하고 연결요청이 오면 클라이언트 소켓을 생성해 통신을 가능하게함
  • 클라이언트 : 실제로 데이터 송수신이 일어남
  • 소켓은 프로토콜 , Ip주소, 포트넘버로 이루어짐

소켓의 흐름

  • accpet 에서는 listen의 수신대기열에 쌓인것을 처리할때 처음서버에서 만든 소켓에 직접 연결하는게아니라 accept에서 매번 만들어서 소통을 하게된다

webSocket

  • 양방향 소통을 위한 프로토콜
  • 빠르게 작동, 통신할 때 아주적은 데이터 이용
  • 이벤트를 단순히 듣고 보내는것만 가능

socket.io

  • 양방향 통신을 하기 위해 웹소켓 기술을 활용하는 라이브러리
  • 방 개념을 이용해 일부 클라이언트에게만 데이터를 전송하는 브로드캐스팅이 가능
  • 실시간 웹 애플리케이션을 위한 자바스크립트 라이브러리
  • 이벤트기반, 양방향 통신 가능

Socket.io 불러오기

1. Client 단

<script src="https://cdn.socket.io/4.6.0/socket.io.min.js" integrity="sha384-c79GN5VsunZvi+Q/WObgk2in0CbZsHnjEqvFxC5DxHn9lTfNce2WW6h2pH6u/kF+" crossorigin="anonymous"></script>

2. Server단

const express = require('express');
const app = express();
const http = require('http').Server(app);
const io = require('socket.io')(http);

http.listen(8001, () => {
  console.log('Server Open : ', 8001);
});

Client와 Server 연결하기

1. Client

//클라이언트 소켓 생성 후 연결
let socket = io.connect();

socket.on('connect', ()=>{
	console.log('server connected');
})

2. Server

// 클라이언트 소켓ㅇ과 연결이 되고 새로 생성된 소켓
io.on("connection", (socket) => {
	console.log("sever socket connected");
	
	socket.on("disconnect", () =>{
		console.log("server socket disconnected");
	});
});
💡 socket 함수
- 메세지보내기 : socket.emit(”이벤트 명”, data);
- 메세지받기 : socket.on(”이벤트 명”, (data) ⇒ { data 처리 함수 });
  • 이벤트 명은 보통 직접 만드는데, connect나 disconnect 같이 이미 만들어진 이벤트도 존재한다

socket.emit : 전송한 클라이언트에게만 메시지 전송
io.emit : 서버에 접속된 모든 클라이언트에게 메시지를 전송


aws

EC2

  • 독립된 컴퓨터를 임대해주는 클라우드 서비스
  • 특징
    • 컴퓨터 요구사항의 변화에 따라 컴퓨팅 자원을 조절할 수 있다
    • 클릭 몇 번만으로 컴퓨터 한 대를 구성할 수 있다
    • 사용한만큼만 지불할 수 있다

RDS

  • AWS의 관계형 데이터베이스
  • AWS 측에서 모든 것을 관리해주소 개발자가 개발만 가능하도록 도와주는 서비스

S3

  • 내구성과 확장성이 뛰어난 스토리지 서비스
  • 안전하고 가변적인 Object 무제한 저장공간을 제공한다
  • 편리한 UI 인터페이스를 통해 어디서나 쉽게 데이터를 저장하고 불러올 수 있다.

실습

client

socket.on('connect', () => {
        console.log('server connected');

        socket.emit('username', username); //username이라는 이벤트에 메시지 보내기
});

//info라는 이벤트 메시지 받기
socket.on('info', (socketID) => { 
        my_id = socketID;
});

//notice라는 이벤트 메시지 받기
socket.on('notice', (msg) => {
     const container = document.querySelector('.container');
     const div = document.createElement('div');
     div.classList.add('notice');
     div.textContent = msg;
     container.appendChild(div);
        console.log(container);
});

//newMsg 라는 이벤트메시지를 받기
socket.on('newMsg', (json) => {
   //json = {msg : ~~~}
   const container = document.querySelector('.container');
   const outer_div = document.createElement('div');
   const div = document.createElement('div');
   let msg = '';
   if (json.from === my_id) {
      if (json.is_dm) {
          outer_div.classList.add('dm', 'my-dm');
      } else {
            outer_div.classList.add('my-chat');
      }
      msg = json.msg;
   } 
   else {
     if (json.is_dm) {
         outer_div.classList.add('dm', 'other-dm');
     } else {
         outer_div.classList.add('other-chat');
     }
     msg = json.username + ' : ' + json.msg;
 }
    div.textContent = msg;
    outer_div.appendChild(div);
    container.appendChild(outer_div);
});


//list 라는 이벤트메시지를 받기
socket.on('list', (list) => {
    const member_list = document.getElementById('members');
    //null이 아니면 계속 마지막요소 지워주기
    while (member_list.firstChild)
          member_list.removeChild(member_list.lastChild);
  
   const option = document.createElement('option');
   option.text = '전체';
   option.value = '전체';
   member_list.appendChild(option);
   console.log(Object.entries(list));
   for (let [key, value] of Object.entries(list)) {
      if (key !== my_id) {
          const option = document.createElement('option');
          option.text = value;
          option.value = value;
          member_list.appendChild(option);
        }
     }
});

/*전송 이벤트*/
const btnSend = () => {
     const input = document.getElementById('msg_box');
     const to = document.getElementById('members').value;
     socket.emit('send', { msg: input.value, to }); //send 라는 이벤트메시지 보내기
     input.value = '';
};

server

const express = require('express');
const app = express();
const http = require('http').Server(app);
const io = require('socket.io')(http);

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

//{소켓아이디 : 닉네임, ...}
let list = {};

//connect 라는 전체 이벤트메시지 받기
io.on('connection', (socket) => {
  console.log('Server Socket Connected');

  //info 라는 이벤트 보내기
  socket.emit('info', socket.id);

  //username 라는 이벤트메시지 받기
  socket.on('username', (name) => {
    list[socket.id] = name;
    io.emit('list', list); //list 라는 전체 이벤트메시지 보내기
    io.emit('notice', name + '님이 입장하셨습니다');//notice 라는 전체 이벤트메시지 보내기
  });

  
   //send 라는 이벤트메시지 받기
  socket.on('send', (json) => {
    //json = { msg : ~~}
    json['from'] = socket.id;
    json['username'] = list[socket.id];
    json['is_dm'] = false;
    if (json.to === '전체') {
      io.emit('newMsg', json); //newMsg 라는 전체 이벤트메시지 보내기
    } else {
      const to_userId = Object.keys(list).find((key) => list[key] == json.to);
      json['is_dm'] = true;
      io.to(to_userId).emit('newMsg', json); //newMsg 라는 이벤트메시지 to_userId 에게 보내기
      socket.emit('newMsg', json);
    }
  });

   //disconnect 라는 이벤트받기
  socket.on('disconnect', () => {
    io.emit('notice', list[socket.id] + '님이 퇴장셨습니다.');
    delete list[socket.id];
  });
});

http.listen(8001, () => {
  console.log('Server port : ', 8001);
});

후기

졸업프로젝트때 그렇게 하고싶었던 채팅기능을 구현할 수 있게되다니 ..
너무 기뻤다! 채팅은 정말 여기저기서 쓰일 수 있을 것같아 앞으로의 프로젝트에
도움이 많이 될 거같아서 복습 다시 해봐야겠다.

0개의 댓글