이번에는 방에 입장할 때와 퇴장할 때 채팅방의 다른 사람에게 '#12C6B8 님이 입장하셨습니다' 같은 시스템 메시지를 보내려고 합니다.
그런데 사용자의 이름은 세션(req.session.color)에 들어있습니다.
Socket.IO도 미들웨어를 사용할 수 있으므로 express-session을 공유하면 됩니다.
추가로 채팅방 접속자가 0명일 때 방을 제거하는 코드도 같이 넣어보겠습니다.
app. js와 socket.is 간에 express-session미들웨어를 공유하기위해 변수로 분리했습니다.
socket.is 작성
chat.use 메서드에 미들웨어를 장착할 수 있습니다.
이 미들웨어는 chat 네임스페이스에 웹 소켓이 연결될 때마다 실행됩니다.
wrap 함수는 미들웨어에 익스프레스처럼 req, res, next를 제공해주는 함수입니다.
이제 socket.request 객체 안에 socket.request.session 객체가 생성됩니다.
socket.to(방 아이디) 메서드로 특정 방에 데이터를 보낼 수 있습니다.
조금 전에 세션 미들 웨어와 Socket.IO를 연결했으므로 웹 소켓에서 세션(socket.request.session)을 사용할 수 있습니다.
방에 참여할 때 방에 누군가가 입장했다는 시스템 메시지를 보냅니다.
접속 해제 시에는 현재 방의 사람 수에 따라 동작이 달라집니다.
socket.request.headers. referer에 브라우저 주소가 들어 있고, 여기서 URL 객체를 사용해 방 아이디를 추출해낼 수 있습니다.
방 아이디는 pathname의 마지막에 위치하고 있어서 at(-1) 메서드로 가져왔습니다.
socket.adapter.rooms.get(방 아이디)에 참여 중인 소켓 정보가 들어 있고, 참여자 수는 size 속성으로 구할 수 있습니다.
참여자 수가 0명이면 방을 제지하고, 0명이 아니면 방에 남아 있 는 참여자에게 퇴장했다는 메시지를 보냅니다.
여기서 주의할 점은 방을 제거할 때 removeRoom 컨트롤러가 아니라 서비스라는 점입니다.
컨트롤러가 아니라 서비스를 사용한 이유는 웹 소켓에는 req, res, next가 없기 때문입니다.
미들웨어처럼 req, res, next를 각각 socket.request, (3, () => {})로 대체하면 안 되는지 궁금할 수 있 는데,
socket.request에는 params.id(방 아이디)가 들어 있지 않습니다.
이렇듯 현재 컨트롤러는 HTTP 요청에 적합하게 구성되어 있으므로 웹 소켓 요청이 컨트롤러를 사용하기에는 부자연스럽습니다.
따라서 req, res, next을 사용하지 않아도 되도록 서비스를 분리하는 것이 좋습니다. removeRoom 서비스는 다음과 같이 생성합니다.
remove 컨트롤러는 removeRoom 서비스를 가져와 사용합니다.
removeRoom 서비스를 호출하는 데는 RoomId(방 아이디)만 필요하므로
removeRoon 컨트롤러와 socket.js에서 removeRoom 서비스를 사용할 수 있습니다.
다시 브라우저 두 개를 열어 localhost:8005에 접속합니다.
접속 후 방을 하나 만들고, 다른 브라우저로는 그 방에 입장합니다.
입장할 때와 퇴장할 때 모두 메시지가 출력됩니다. 또한, 방에서 모 두 나가면 방이 제거됩니다.
'clone toy projects > node_expresss_chat' 카테고리의 다른 글
이미지를 포함한 채팅 (0) | 2023.08.30 |
---|---|
채팅 기능 구현하기 (0) | 2023.08.30 |
실시간 GIF 채팅방 만들기 (0) | 2023.08.30 |
Soket.IO 사용하기 (0) | 2023.08.30 |
ws 모듈로 웹소켓 사용하기 (0) | 2023.08.30 |