WebSocket은 클라이언트와 서버(브라우저와 서버)를 연결하고 실시간으로 통신이 가능하도록 하는 첨단 기술입니다
클라이언트와 서버 간의 연결은 당사자 중 하나에 의해 종료되거나 시간 초과에 의해 닫힐 때까지 열린 상태로 유지됩니다.
클라이언트와 서버 간의 연결을 설정하기 위해 핸드셰이크를 수행합니다.
설정된 연결은 열린 상태로 유지되며 클라이언트 또는 서버 측에서 연결이 종료될 때까지 동일한 채널을 사용하여 통신이 수행됩니다. 메시지는 양방향으로 교환됩니다.
WebSocket 프로토콜은 실시간 데이터 업데이트와 클라이언트에 메시지를 보내는 기능이 필요할 때 이상적입니다.
다음은 웹 소켓에 대한 보다 광범위한 사용 사례입니다.
우선 server 에서 socket.io 를 통해서 통신 준비를 해 주어야 합니다.
emit : 데이터를 보내는 함수이다. 클라이언트는 서버에게, 서버는 클라이언트에게 데이터를 보낸다.
on : 데이터를 받는 함수이다. 클라이언트 서버로부터, 서버는 클라이언트로부터 데이터를 받는다.
서버를 시작하기 전에 필요한 부분을 설치해 줍시다.
npm i express http socket.io cors
const express = require('express');
const cors = require('cors');
const http = require("http");
const { Server } = require('socket.io');
const app = express();
// HTTP 서버를 생성합니다.
const server = http.createServer(app)
// Socket.IO 서버를 생성합니다.
// 이때 프론트에서 실행할 localhost 를 입력하고 get, post 만 허용한다고 정해줍니다.
const io = new Server(server, {
cors: {
origin: "http://localhost:5173",
methods: ["GET", "POST"],
},
})
// 클라이언트가 소켓에 연결되었을 때의 이벤트 핸들러입니다.
// 클라이언트가 서버에 연결되면 실행됩니다. socket 객체를 통해 클라이언트와의 통신을 할 수 있습니다.
// 여기서 on 은 클라이언트에서 데이터를 받을 때 실행되고 emit 은 클라이언트로 데이터를 보낼 때 실행됩니다.
io.on('connection', socket => {
socket.on('send message', (item) => {
const msg = item.name + ' : ' + item.message;
console.log(msg);
io.emit('receive message', {name:item.name, message:item.message});
});
socket.on('disconnect', function () {
console.log('user disconnected: ', socket.id);
});
});
server.listen(4040, () => {
console.log("server running")
})
클라이언트에서는 websocket 을 사용하고 싶은 컴포넌트에서 설정해 주면 됩니다.
리액트에서는 따로 socket.io-client 라이브러리를 설치하고 이용해야 합니다.
npm i @types/socket.io-client
import React, { ChangeEvent, FormEvent, useEffect, useState } from 'react';
import socketIOClient from "socket.io-client";
interface Message {
name: string,
message: string
}
const SocketTest: React.FC = () => {
const [messageList, setMessageList] = useState<Message[]>([]);
const [data, setData] = useState({
name: '',
message: ''
})
// 서버쪽 socket 연결
const socket = socketIOClient('localhost:4040');
const submit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
// 서버 쪽에서 설정한 socket.on('send message') 으로 보내주기
socket.emit('send message', { name: data.name, message: data.message });
};
useEffect(() => {
// 서버 쪽에서 설장한 socket.emit('receive message') 실행하기
socket.on('receive message', (message: { name: string, message: string }) => {
setMessageList(messageList => [...messageList, message]);
})
}, []);
const handleOnChange = (e: ChangeEvent<HTMLInputElement>) => {
setData({
...data,
[e.currentTarget.name] : e.target.value,
})
}
return (
<div className="App">
<section className="chat-list">
{messageList.map((item: Message, i: number) =>
<div key={i} className="message">
<p className="username">{item.name.toUpperCase()}</p>
<p className="message-text">{item.message}</p>
</div>
)}
</section>
<form className="chat-form"
onSubmit={(e: FormEvent<HTMLFormElement>) => submit(e)}>
<div className="chat-inputs">
<input
type="text"
autoComplete="off"
onChange={handleOnChange}
name="name"
placeholder="유저이름"
/>
<input
type="text"
autoComplete="off"
onChange={handleOnChange}
name="message"
placeholder="메세지입력하기"
/>
</div>
<button type="submit">입력하기</button>
</form>
</div>
);
}
export default SocketTest;
이렇게 설정하고 실행하게 되면 정상적으로 작동하게 됩니다.