프로그래밍 언어/NODE JS

ws 모듈로 웹 소켓 사용하기

· 코딩마이데이

먼저 gif-chat이라는 새로운 프로젝트를 만듭니다.

{
  "name": "gif-chat",
  "version": "0.0.1",
  "description": "GIF 웹소켓 채팅방",
  "main": "app.js",
  "scripts": {
    "start": "nodemon app"
  },
  "author": "Zero Cho",
  "license": "ISC",
  "dependencies": {
    "cookie-parser": "^1.4.4",
    "dotenv": "^8.2.0",
    "express": "^4.17.1",
    "express-session": "^1.17.0",
    "morgan": "^1.9.1",
    "nunjucks": "^3.2.0",
    "ws": "^7.2.1"
  },
  "devDependencies": {
    "nodemon": "^2.0.2"
  }
}

 

패키지를 설치하고 .env와 app.js, routes/index.js 파일을 작성합니다.

$ npm i
COOKIE_SECRET=gifchat

 

app.js

const express = require("express");
const path = require("path");
const cookieParser = require("cookie-parser");
const session = require("express-session");
const nunjucks = require("nunjucks");
const dotenv = require("dotenv");

dotenv.config();
const indexRouter = require("./routes");
const morgan = require("morgan");

const app = express();
app.set("port", process.env.PORT || 8005);
app.set("view engine", "html");

nunjucks.configure("views", {
  express: app,
  watch: true,
});

app.use(morgan("dev"));
app.use(express.static(path.join(__dirname, "public")));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser(process.env.COOKIE_SECRET));
app.use(
  session({
    resave: false,
    saveUninitialized: false,
    secret: process.env.COOKIE_SECRET,
    cookie: {
      httpOnly: true,
      secure: false,
    },
  })
);

app.use("/", indexRouter);

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");
});

app.listen(app.get("port"), () => {
  console.log(app.get("port"), "번 포트에서 대기 중");
});

 

routes/index.js

const express = require("express");

const router = express.Router();

router.get("/", (req, res) => {
  res.render("index");
});

module.exports = router;

 

이제 ws 모듈을 설치하여 노드에 웹 소켓을 구현해봅시다.

$ npm i ws

 

웹 소켓을 익스프레스 서버에 연결합니다.

const express = require("express");
const path = require("path");
const cookieParser = require("cookie-parser");
const session = require("express-session");
const nunjucks = require("nunjucks");
const dotenv = require("dotenv");

dotenv.config();
const webSocket = require("./socket");
const indexRouter = require("./routes");
const morgan = require("morgan");

const app = express();
app.set("port", process.env.PORT || 8005);
app.set("view engine", "html");

nunjucks.configure("views", {
  express: app,
  watch: true,
});

app.use(morgan("dev"));
app.use(express.static(path.join(__dirname, "public")));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser(process.env.COOKIE_SECRET));
app.use(
  session({
    resave: false,
    saveUninitialized: false,
    secret: process.env.COOKIE_SECRET,
    cookie: {
      httpOnly: true,
      secure: false,
    },
  })
);

app.use("/", indexRouter);

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);

 

이제 웹소켓 로직이 들어 있는 socket.js 파일을 작성해봅시다.

const WebSocket = require("ws");

module.exports = (server) => {
  const wss = new WebSocket.Server({ server });

  wss.on("connection", (ws, req) => {
    // 웹소켓 연결 시
    const ip = req.headers["x-forwarded-for"] || req.connection.remoteAddress;
    console.log("새로운 클라이언트 접속", ip);
    ws.on("message", (message) => {
      // 클라이언트로부터 메시지
      console.log(message);
    });
    ws.on("error", (error) => {
      // 에러 시
      console.error(error);
    });
    ws.on("close", () => {
      // 연결 종료 시
      console.log("클라이언트 접속 해제", ip);
      clearInterval(ws.interval);
    });

    ws.interval = setInterval(() => {
      // 3초마다 클라이언트로 메시지 전송
      if (ws.readyState === ws.OPEN) {
        ws.send("서버에서 클라이언트로 메시지를 보냅니다.");
      }
    }, 3000);
  });
};

 

ws 모듈로 불러온 후 익스프레스 서버를 웹 소켓 서버와 연결했습니다. 익스프레스(HTTP)와 웹 소켓(WS)은 같은 포트를 공유할 수 있으므로 별도의 작업이 필요하지 않습니다.

웹 소켓 구조도

 

다음 NODE JS 글에서 계속....

'프로그래밍 언어 > NODE JS' 카테고리의 다른 글

Socket.IO 사용하기  (0) 2026.01.17
ws 모듈로 웹 소켓 사용하기  (0) 2026.01.14
웹 소캣 이해하기  (0) 2026.01.08
테스트 커버리지  (0) 2025.12.26
유닛 테스트(3)  (0) 2025.12.23