ws을 이용해 웹 소켓을 사용할 수 있지만 Socket.IO에 편의 기능이 많아서 편리합니다.
사실 socket.io는 웹 소켓이 아니라, 웹 소켓을 사용할 수 없는 브라우저에서는 폴링을 사용하는 등, 실시간 통신을 구현할 수 있는 여러가지를 합쳐서 추상화 시켜놓은 패키지입니다.
그런데 큰 규모라면 사용을 비추천한답니다. "웹브라우저와 서버가 통신할 일이 아니면 굳이 socket.io일 필요는 없다."는게 중론입니다.
socket.io의 이점은 프로토콜 추상화라고 할 수 있겠죠... protocol cycle에서 나오는 이슈 신경안써도 된다는거나 room 같은거 제공되는거 장점일순 있지만 애초에 네트워크 프로그래밍을 하는 프로그래머라면 이 정돈 그냥 뚝!딱! 만든다고 한다.
⚡ 설치
npm i socket.io
⚡ 사용
./app.js
const webSocket = require("./socket");
// listen
const server = app.listen(process.env.PORT, () => {
return console.log(`success on : http://localhost:${process.env.PORT}`);
});
// ws는 http와 동일 포트를 사용함
webSocket(server);
./socket.js
위 app.js에서 등록한 server 메서드를 작성해봅시다.
서버 객체를 받아서 소켓 객체를 생성하고 프론트가 접속할 경로(path)를 만들어 둡시다.
const SocketIO = require("socket.io");
module.exports = (server) => {
// path 변수는 백엔드랑은 아무 관련 없음
// 이는 클라이언트가 /socket.io 경로 접근시 소켓 연결을 시작함을 의미
const io = SocketIO(server, { path: "/socket.io" });
// 연결시 connection 이벤트 발생한 후 콜백 실행
io.on("connection", (socket) => {
// ws에 req가 따로 있었다면 socket에서는 socket.request에 존재합니다
const req = socket.request;
const ip = req.headers["x-forwarded-for"] || req.connection.remoteAddress;
console.log(
`✔ ${ip} 클라이언트 접속, socket.id : ${socket.id}, req.ip : ${req.ip}`
);
// 연결 해제
socket.on("disconnect", () => {
console.log(`${ip} 클라이언트 접속 해제. socket.id : ${socket.id}`);
clearInterval(socket.interval);
});
// 에러
socket.on("error", (error) => {});
// 프론트 단에서 넘긴 메세지의 키값을 받습니다
socket.on("from client", (data) => {
console.log(data);
});
socket.interval = setInterval(() => {
//메세지를 보내는 emit 메서드는 키, 값을 파라미터로 받습니다
socket.emit("from server", "hello. this is message from server");
}, 3000);
});
};
소켓 객체에는 이벤트를 달아둡니다.
connection 이벤트, disconnet이벤트, err 이벤트는 기본 내장 이벤트이고
from client 는 직접 만든 이벤트입니다. 이벤트를 기준으로 소켓 통신이 이루어집니다.
req 객체는 socket.request로 참고할 수 있으며
소켓과 통신하는 클라이언트는 socket.id 를 통해 구별할 수 있습니다.
./views/index.pug
클라이언트 단의 socket.io는 socket.io/docs/v4/client-installation/ 부분을 참고해보세요
소켓 통신을 이용하기 위해서 클라이언트 단에서는 /socket.io 경로로 이동하여 socket.io.js를 실행해야 합니다.
이 외에도 socket.io-client 패키지를 설치하는 방법도 있긴 하지만, 우선은 간단히 아래처럼 해봅시다.
<script src="/socket.io/socket.io.js"></script>
<script>
const socket = io();
</script>
그렇게 되면 io 객체를 이용할 수 있게 됩니다. 여기서 앞서 소켓 객체에서 path를 /socket.io로 설정했으므로 socket 객체를 만들 때 path 속성에 /socket.io를 등록합시다.
또, 웹소켓 통신을 통신이 시작되기 전 http 통신을 통해 웹소켓을 사용 가능한 브라우저 환경인지 탐지를 먼저 하고, 웹소켓이 불가능한 환경이면 폴링으로 통신을 합니다. 만약 폴링을 사용하지 않고 웹소켓이 아니면 통신 자체를 하지 못하게 하려면 tansports 속성에 ['websocket']을 지정해주면 됩니다.
extends layout
block content
div 개발자 도구 확인하십쇼.
script(src="/socket.io/socket.io.js")
script.
// connect하는 것이므로 첫 인자에는 소켓 통신을 시도하는 웹서버의 주소를 입력해줍시다.
const socket = io.connect("http://localhost:3000", {
//- path 변수는 백단에서 준 path값과 동일해야 함
path: "/socket.io",
// transports로 다음 값을 주면 폴링을 시도하지 않고 웹소켓만으로 통신합니다
transports: ['websocket']
});
// 백단에서 emit의 키값과 동일한 값을 줘야 합니다
socket.on("from server", (data) => {
console.log(data)
socket.emit("from client", "Hello from client")
});
소켓 통신이 이뤄진 것을 볼 수 있습니다. ws 와는 다르게 키와 값이 동시에 들어있는 것을 확인할 수 있습니다.
서버의 콘솔에 출력된 결과도 다음과 같음을 확인할 수 있습니다. socket.id를 통해 클라이언트를 구분할 수도 있습니다.
const ip = req.headers["x-forwarded-for"] || req.connection.remoteAddress;
console.log(
`✔ ${ip} 클라이언트 접속, socket.id : ${socket.id}, req.ip : ${req.ip}`
);
✔ ::1 클라이언트 접속, socket.id : 25GJNosDna87tVd2AAAA, req.ip : undefined
⚡ emit로 보내고 on으로 받는다.
정리하자면, emit로 메세지를 보낼 때 사용하는 키, 값에서 키는 해당 메세지를 받는 표식이며 값은 data입니다. socket.on("보낸 쪽에서 지정한 key", (data) => {console.log(data)})와 같이 사용됩니다.
emit로 보내고 on으로 받는다.
이걸 기억합시다
'Node, Nest, Deno > ⚡ ws , socket.io' 카테고리의 다른 글
소켓 통신 활용을 위한 변수 설정 및 미들웨어 구성하기 (0) | 2020.08.12 |
---|---|
Socket.IO Namespace, Room (0) | 2020.04.07 |
ws 모듈 이용해 웹 소켓 맛보기 (0) | 2020.04.04 |