<aside> 💡 Socket.IO를 이용하여, 여러명이 채팅방에 참여하여 실시간 채팅이 가능한 웹 어플리케이션을 만들어 보자.

</aside>

Socket.IO???

실시간 커뮤니케이션을 도와주는 웹 에플리케이션이다.

Server

//express module 변수에 담기
const express = require("express");
//Node.js기본 모듈 불러오기
const http = require("http");
//cors불러오기
const cors = require("cors");
//express객체 생성
const app = express();
const corsOptions = {
  origin: "<http://localhost:3000>",
  methods: ["GET", "POST", "OPTION"],
  credentials: true,
};
app.use(cors(corsOptions));
//express http서버 생성
const server = http.createServer(app);
//생성된 서버를 socket.io에 바인딩
const io = require("socket.io")(server, {
  cors: {
    origin: "<http://localhost:3000>",
    methods: ["GET", "POST"],
    allowedHeaders: ["my-custom-header"],
    credentials: true,
  },
});

io.on("connection", (socket) => {
    **// 여기서 중요한 것은 join이이벤트를 받았을때, socket.join을 실행 시켜주는 것이다. 
		// 그렇지 않고, connection이 일어날때 바로 socket.join을 하게 되면,
		// 총 두번 접속하게 되어, 나중에 접속자 수를 구할때, 2명으로 측정되게 된다.**
    socket.on('join', (data) => {
        // let { roomId } = socket.handshake.query;
        socket.join(data.roomId);
        io.to(data.roomId).emit('welcome', `${data.userName} has entered No.${data.roomId} Room`)
    })

    socket.on('newMessage', (data) => {
        console.log(data)
        io.to(data.roomId).emit("newMessage", data.newMsg);
    })

		**//현재 방에 들어와 있는 총 접속자 수를 구하는 부분이다.**
    socket.on('getUsers', async (roomId, id) => {
        const num = io.sockets.adapter.rooms.get(roomId).size;
        console.log(roomId, id)
        io.to(roomId).emit('newMessage', `현재 ${num}명이 접속 중입니다.`)
    })
		socket.on('disconnect', (reason)=>{
        socket.emit("newMessage", `User left!! cuz ${reason}`)
    })
})

server.listen(8080, () => {
    console.log("8080 port is working");
});

Client

import { useState, useEffect}from 'react'
import { useParams} from 'react-router-dom'
import { io } from 'socket.io-client'

const ChatRoom = () => {
    const {roomId} = useParams();
    const [newMsg, setNewMsg] = useState('');
    const [userName, setUserName] = useState('Mark');
    const [msg, setMsg] = useState([])
    const socket = io('<http://localhost:8080>', {query: {roomId}});

    useEffect(() => {
        socket.emit('join', ({roomId, userName}));
        socket.on('welcome', (data) => console.log(data));
        socket.on('newMessage', (data)=>console.log(data));

				**//여기서 마지막 return이 의미하는 바는 한번 접속을 하여 일련의 이벤트를 다 처리한 뒤에는 
				//접속을 종료해 준다는 것이다. 이렇게 하면 자동적으로 접속을 시키려고 하지 않는다. 
				//만약 마지막에 disconnect를 해주지 않는다면, 접속자수는 기하급수적으로 늘어날 것이고, 
				//콘솔창이 난리가 나는 상황을 경험해 볼 수 있을것이다.**
        return () => socket.disconnect()
    }, [])

    const nameHandler = (e) => {
        setUserName(e.target.value)
    }
    const magHandler = (e) => {
        setNewMsg(e.target.value)
    }
    const sendMsg = (e) => {
        e.preventDefault();
        socket.emit('newMessage', {roomId, newMsg})
    }
    const getUsers = () => {
        socket.emit('getUsers', roomId, socket.id)
    }
    return (
        <div>
            This is Room
            {msg.map(e => {
                return (<div>{e}</div>)
            })}
            <div>
                <input type="text" placeholder="name" onChange={nameHandler}/>
                <form onSubmit={sendMsg}>
                    <input type="text" placeholder="msg" onChange={magHandler}/>
                    <button type="submit">전송</button>
                </form>

                <button onClick={getUsers}>현재 접속중 인원?</button>
            </div>
        </div>
    )
}

export default ChatRoom