실시간 경매 시스템 만들기 - 서버센트 이벤트 사용하기(1)
플링이나 웹 소켓을 통해 서버 시간을 받아올 수도 있지만, 이번 예제에서는 서버센트 이벤트를 사용해 서버의 시간을 받아올 것입니다. 주기적으로 서버 시간을 조회하는 데 양방향 통신이 필요하지 않기 때문입니다.
웹 소켓도 사용합니다. 웹 소켓은 경매를 진행하는 동안에 다른 사람이 참여하거나 입찰했을 때 모두에게 금액을 알리는 약할을 할 것입니다. 서버센트 이벤트와 웹 소켓은 같이 사용할 수 있습니다.
SSE 패키지와 Socket.IO 패키지를 동시에 설치하겠습니다.
$ npm i sse socket.io@2
서버와 sse, socket.io 모듈을 연결합니다.
app.js
const express = require("express");
const path = require("path");
const morgan = require("morgan");
const cookieParser = require("cookie-parser");
const session = require("express-session");
const passport = require("passport");
const nunjucks = require("nunjucks");
const dotenv = require("dotenv");
dotenv.config();
const indexRouter = require("./routes/index");
const authRouter = require("./routes/auth");
const { sequelize } = require("./models");
const passportConfig = require("./passport");
const sse = require("./see");
const webSocket = require("./socket");
const app = express();
passportConfig();
app.set("port", process.env.PORT || 8010);
app.set("view engine", "html");
nunjucks.configure("views", {
express: app,
watch: true,
});
sequelize
.sync({ force: false })
.then(() => {
console.log("데이터베이스 연결 성공");
})
.catch((err) => {
console.error(err);
});
const sessionMiddleware = session({
resave: false,
saveUninitialized: false,
secret: process.env.COOKIE_SECRET,
cookie: {
httpOnly: true,
secure: false,
},
});
app.use(morgan("dev"));
app.use(express.static(path.join(__dirname, "public")));
app.use("/img", express.static(path.join(__dirname, "uploads")));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser(process.env.COOKIE_SECRET));
app.use(sessionMiddleware);
app.use(passport.initialize());
app.use(passport.session());
app.use("/", indexRouter);
app.use("/auth", authRouter);
app.use((req, res, next) => {
const error = new Error(`${req.method} ${req.url} 라우터가 없습니다.`);
error.status = 404;
next(error);
});
app.use((err, req, res, next) => {
res.locals.message = err.message;
res.locals.error = process.env.NODE_ENV !== "production" ? err : {};
res.status(err.status || 500);
res.render("error");
});
const server = app.listen(app.get("port"), () => {
console.log(app.get("port"), "번 포트에서 대기중");
});
webSocket(server, app);
sse(server);
see.js
const SSE = require("sse");
module.exports = (server) => {
const sse = new SSE(server);
sse.on("conection", (client) => {
// 서버센트 이벤트 연결
setInterval(() => {
client.send(Date.now().toString());
}, 1000);
});
};
see 모듈을 불러와 new SSE(익스프레스 서버)로 서버 객체를 생성하면 됩니다. 생성한 객체에는 connection 이벤트 리스너를 연결하여 클라이언트와 연결할 때 어떤 동작을 할지 정의할 수 있습니다. 매개변수로 client 객체를 쓸 수 있습니다. 클라이언트에 메시지를 보낼 때 이 객체를 사용합니다. 라우터에서 SSE를 사용하고 싶다면 app.set 메서드로 client 객체를 등록하고, req.app.get 메서드로 가져오면 됩니다.
1초마다 접속한 클라이언트에 서버 시간 타임스탬프를 보내도록 했습니다.
client.send 메서드를 보넬 수 있습니다. 단, 문자열만 보낼 수 있으므로 숫자인 타임스탬프를 toString 메서드를 사용하여 문자열로 변경했습니다.
socket.js
const SocketIO = require("socket.io");
module.exports = (server, app) => {
const io = SocketIO(server, { path: "/socket.io" });
app.set("io", io);
io.on("connection", (socket) => {
// 웹 소켓 연결 시
const req = socket.request;
const {
headers: { referer },
} = req;
const roomId = referer.split("/")[referer.split("/").length - 1];
socket.join(roomId);
socket.on("disconnect", () => {
socket.leave(roomId);
});
});
};
Socket.IO와도 연결합니다. 이번에는 사용자 정의 네임스페이스를 쓰지 않고 기본 네임스페이스(/)로 연결했습니다. 경매 화면에서 실시간으로 입찰 정보를 올리기 위해 웹 소켓을 사용합니다. 클라이언트 연결 시 주소로부터 경매방 아이디를 받아와 socket.join으로 해당 방에 입장합니다.
연결이 끊겼다면 socket.leave로 해당 방에 나갑니다.
'프로그래밍 언어 > NODE JS' 카테고리의 다른 글
| 실시간 경매 시스템 - 서버센트 이벤트 사용하기(3) (0) | 2026.03.01 |
|---|---|
| 실시간 경매 시스템 - 서버센트 이벤트 사용하기(2) (0) | 2026.02.26 |
| 실시간 경매 시스템 만들기 - 프로젝트 구조 갖추기(3) (0) | 2026.02.20 |
| 실시간 경매 시스템 만들기 - 프로젝트 구조 갖추기(2) (0) | 2026.02.16 |
| 실시간 경매 시스템 만들기 - 프로젝트 구조 갖추기(1) (0) | 2026.02.13 |