괴발개발/node.js
[node.js 교과서] ch12. 웹 소켓으로 실시간 데이터 전송하기
ebulsok
2023. 2. 7. 17:53
웹 소켓
실시간 양방향 데이터 전송을 위한 기술
- 폴링: 웹소켓이 나오기 이전 HTTP 기술을 사용하여 구현. 주기적으로 서버에 새로운 업데이트가 있는지 확인하는 요청을 보낸 후 있다면 새로운 내용을 가져옴
- HTTP와 다르게 WS라는 프로토콜 사용 ⇒ 브라우저와 서버가 WS를 지원해야 사용할 수 있음
- 처음에 웹 소켓 연결이 이루어지고 나면 업데이트 요청을 따로 보낼 필요가 없고, 업데이트 할 내용이 생겼다면 서버에서 바로 클라이언트에 알림. HTTP 프로토콜과 포트를 공유할 수 있으므로 다른 포트에 연결할 필요 없음
- Socket.IO: 웹소켓을 편리하게 사용할 수 있도록 도와주는 라이브러리
- 웹소켓은 이벤트 기반으로 작동하고, 실시간으로 데이터를 전달받으므로 항상 대기하고 있어야 함. connection 이벤트는 클라이언트가 서버와 웹소켓 연결을 맺을 때 발생.
- req.headers['x-forwarded-for'] || req.connection.remoteAddress; 클라이언트의 ip를 알아내는 방법 중 하나(express에서는 proxy-addr 패키지 사용). localhost로 접속한 경우, 크롬에서는 ip가 ::1로 뜸
message: 클라이언트로부터 메시지가 왔을 때 발생
error: 웹소켓 연결 중 문제가 생겼을 때 발생
close: 클라이언트와 연결이 끊겼을 때 발생
setInterval: 3초마다 연결된 모든 클라이언트에 메시지를 보내는 부분
- readyState가 OPEN 상태인지 확인
- CONNECTING, OPEN, CLOSING, CLOSED
- 확인 후 ws.send 메서드로 하나의 클라이언트에 메시지를 보냄
- close 이벤트에서 setInterval을 clearInterval로 정리(메모리 누수 방지)
const webSocket = new WebSocket("ws://localhost:8005");
webSocket.onopen = function () {
console.log('서버와 웹소켓 연결 성공!');
};
webSocket.onmessage = function (event) {
console.log(event.data);
webSocket.send('클라이언트에서 서버로 답장을 보냅니다');
};
socket.io
- socket.io 패키지를 불러와서 익스프레스 서버와 연결
- SocketIO 객체의 두번째 인수로 옵션 객체를 넣어 서버 설정
- path: 클라이언트가 접속할 경로
- 이벤트 리스너
- connection: 클라이언트가 접속했을 때 발생, 콜백으로 socket 객체 제공. socket.request로 요청 객체에, socket.request.res로 응답 객체에 접근, socket.id로 소켓 고유 아이디 확인
- disconnect: 클라이언트가 연결을 끊었을 때 발생
- error: 통신 과정에서 에러가 나왔을 때 발생
- reply: 사용자가 직접 만든 이벤트
- emit: 3초마다 클라이언트 한 명에게 메시지 전송
- 첫번째 인수: 이벤트 이름
- 두번째 인수: 데이터
ws 프로토콜이 아니라 http 프로토콜을 사용
먼저 폴링 방식으로 서버와 연결 후, 웹소켓을 사용할 수 있다면 업그레이드
처음부터 웹소켓만 사용: transports: ['websocket'],
io.connect: 네임스페이스를 여러 개 구분해 주고받을 데이터를 분류할 수 있음
io.of: Socket.IO에 네임스페이스를 부여
현재 웹페이지의 url: socket.request.headers.referer
io.use: 미들웨어 정착하면 모든 웹소켓 연결 시마다 실행됨
socket.to(방 아이디): 특정 방에 데이터를 보냄
color-hash: 세션 아이디를 HEX 형식의 색상 문자열로 바꿔주는 패키지
브라우저에서 axios 요청을 보낼 때는 자동으로 쿠키를 같이 넣어서 보내지만, 서버에서 axios 요청을 보낼 때 session이 판단할 수 있게 하려면 요청 헤더에 세션 쿠키를 직접 넣어야 함