미들웨어와 소켓 연결하기(2)
이제 라우터 부분을 작성합니다. 라우터에서 몽고디비의 웹 소켓 모두에 접근할 수 있습니다.
const express = require("express");
const Room = require("../schemas/room");
const Chat = require("../schemas/chat");
const router = express.Router();
router.get("/", async (req, res, next) => {
try {
const rooms = await Room.find({});
res.render("main", { rooms, title: "GIF 채팅방" });
} catch (error) {
console.error(error);
next(error);
}
});
router.get("/room", (req, res) => {
res.render("room", { title: "GIF 채팅방 생성" });
});
router.post("/room", async (req, res, next) => {
// ➊
try {
const newRoom = await Room.create({
title: req.body.title,
max: req.body.max,
owner: req.session.color,
password: req.body.password,
});
const io = req.app.get("io");
io.of("/room").emit("newRoom", newRoom);
res.redirect(`/room/${newRoom._id}?password=${req.body.password}`);
} catch (error) {
console.error(error);
next(error);
}
});
router.get("/room/:id", async (req, res, next) => {
// ➋
try {
const room = await Room.findOne({ _id: req.params.id });
const io = req.app.get("io");
if (!room) {
return res.redirect("/?error=존재하지 않는 방입니다.");
}
if (room.password && room.password !== req.query.password) {
return res.redirect("/?error=비밀번호가 틀렸습니다.");
}
const { rooms } = io.of("/chat").adapter;
if (
rooms &&
rooms[req.params.id] &&
room.max <= rooms[req.params.id].length
) {
return res.redirect("/?error=인원이 가득 찬 방입니다.");
}
return res.render("chat", {
room,
title: room.title,
chats: [],
user: req.session.color,
});
} catch (error) {
console.error(error);
next(error);
}
});
router.delete("/room/:id", async (req, res, next) => {
// ➌
try {
await Room.remove({ _id: req.params.id });
await Chat.remove({ room: req.params.id });
res.send("ok");
setTimeout(() => {
req.app;
}, 2000);
} catch (error) {
console.error(error);
next(error);
}
});
module.exports = router;
GET / 라우터는 채팅방 목록이 보이는 메인 화면을 렌더링하는 라우터고, GET /room 라우터는 채팅방 생성 화면을 렌더링하는 라우터입니다. POST /room, GET /room/:id, DELETE /room/:id 라우터를 주목해서 봐야 합니다.
➊ POST /room 라우터는 채팅방을 만드는 라우터입니다. app.set('io', io)로 저장했던 io 객체를 req.app.get('io')로 가져옵니다. io.of('/room').emit 메서드는 /room 네임스페이스에 연결한 모든 클라이언트에 데이터를 보내는 메서드입니다. GET / 라우터에 접속한 모든 클라이언트가 새로 생성된 채팅방에 대한 데이터를 받을 수 있습니다. 네임스페이스가 따로 없는 경우에는 io.emit 메서드로 모든 클라이언트에 데이터를 보낼 수 있습니다.
➋ GET /room/:id는 채팅방을 렌더링하는 라우터입니다. 렌더링 전에 방이 존재하는지, 비밀방일 경우에는 비밀번호가 맞는지, 허용 인원을 초과하지는 않았는지 검사합니다. io.of('/chat').adapter.rooms에 방 목록이 들어 있습니다. io.of('/chat').adapter.rooms[req.params.id]를 하면 해당 방의 소켓 목록이 나옵니다. 이것으로 소켓의 수를 세서 참가 인원의 수를 알아낼 수 있습니다.
➌ DELETE /room/:id는 채팅방을 삭제하는 라우터입니다. 채팅방과 채팅 내역을 삭제한 후 2초 뒤에 웹 소켓으로 /room
네임스페이스에 방이 삭제되었음(removeRoom)을 알립니다.
이제 접속해서 방을 생성해봅시다.
서버를 시작하기 전에 몽고디비를 먼저 실행해야 한다는 것을 잊지 마세요. 몽고디비와 서버를 실행한 후 브라우저 두 개를 띄워놓고 http://localhost:8005에 접속합니다. 브라우저 두 개를 사용하는 이유는 두 명이 접속한 것과 비슷한 상황을 연출하기 위해서입니다.

한 브라우저에서 방을 생성해 봅시다.

방이 생성되는 순간에 서버가 newRoom 이벤트를 호출하고, 다른 브라우저에서도 방 목록이 업데이트됩니다.

방 나가기를 누르면 참여자가 0명이므로 removeRoom 이벤트가 호출되어 2초 후 양쪽 브라우저에서 모두 방이 사라집니다.
'프로그래밍 언어 > NODE JS' 카테고리의 다른 글
| 프로젝트 마무리하기 (0) | 2026.02.10 |
|---|---|
| 채팅 구현하기 (0) | 2026.02.07 |
| 미들웨어와 소켓 연결하기 (0) | 2026.02.01 |
| 실시간 GIF 채팅방 만들기(4) (0) | 2026.01.29 |
| 실시간 GIF 채팅방 만들기(3) (0) | 2026.01.26 |