Act99 기술블로그

[NextJs] 주식사이트 만들기 12 / Websocket & Express 를 이용한 실시간 채팅 구현 본문

개발팁저장소/nextjs

[NextJs] 주식사이트 만들기 12 / Websocket & Express 를 이용한 실시간 채팅 구현

Act99 2021. 12. 28. 16:50

프로젝트 완료가 다 되었다.

사용한 기술스택은 다음과 같다.

 

 

먼저 결과물부터 보면,

 

 

이렇게 상대방과 본인이 실시간으로 채팅이 가능하게 만들었다.

 

웹 소켓에 대한 이해를 하고 넘어가느라 오래걸렸다.

먼저 참고 영상은 다음과 같다.

 

https://www.youtube.com/watch?v=a_xo-SbIfUQ&t=3197s 

 

Websocket과 Express를 이용해 realtime chat을 만드는 영상이며,

많은 영상과 github, medium 들을 찾다가 이 영상이 제일 유익해서 링크를 남겨놓았다.

 

먼저, 웹소켓이란 서버와 클라이언트 간의 소켓 연결을 유지해 양방향통신과 데이터 전송이 가능하게 만든 기술이며,

서버와 클라이언트 간의 웹소켓 연결은 HTTP 프로토콜로 이루어지지만 정상적으로 연결된다면 웹소켓 연결이 이루어지면서 HTTP 연결이 자동으로 끊기게 된다.

 

또한 데이터 자체는 서버상에서 구성되기 때문에 서버가 끊기게 된다면 데이터는 사라지게 된다.

따라서 Graphql polling을 이용한 채팅의 경우 채팅 내용이 db에 저장되어 서버 연결이 완전히 차단된 후에도 남아있지만, 웹 소켓을 이용한 채팅의 경우 db에 저장되지 않기 때문에 서버 연결이 차단되면 모두 사라지게 된다.

 

코드는 다음과 같다.

 

 

-server/src/app.ts

 

import express from "express";
import { createServer } from "http";
import { Server } from "socket.io";
import config from "config";
import logger from "./utils/logger";
import { version } from "../package.json";

import socket from "./socket";

const port = config.get<number>("port");
const host = config.get<string>("host");
const corsOrigin = config.get<string>("corsOrigin");

const app = express();

const httpServer = createServer(app);

const io = new Server(httpServer, {
  cors: {
    origin: corsOrigin,
    credentials: true,
  },
});

app.get("/", (_, res) =>
  res.send(`Server is up and running version ${version}`)
);

httpServer.listen(port, host, () => {
  logger.info(`Server version ${version} is listening `);
  logger.info(`http://${host}:${port}`);

  socket({ io });
});

 

-server/src/socket.ts

 

import { nanoid } from "nanoid";
import { Server, Socket } from "socket.io";
import logger from "./utils/logger";

const EVENTS = {
  connection: "connection",
  CLIENT: {
    CREATE_ROOM: "CREATE_ROOM",
    SEND_ROOM_MESSAGE: "SEND_ROOM_MESSAGE",
    JOIN_ROOM: "JOIN_ROOM",
  },
  SERVER: {
    ROOMS: "ROOMS",
    JOINED_ROOM: "JOINED_ROOM",
    ROOM_MESSAGE: "ROOM_MESSAGE",
  },
};

const rooms: Record<string, { name: string }> = {};

function socket({ io }: { io: Server }) {
  logger.info(`Sockets enabled`);

  io.on(EVENTS.connection, (socket: Socket) => {
    logger.info(`User connected ${socket.id}`);

    socket.emit(EVENTS.SERVER.ROOMS, rooms);

    /*
     * When a user creates a new room
     */
    socket.on(EVENTS.CLIENT.CREATE_ROOM, ({ roomName }) => {
      console.log({ roomName });
      // create a roomId
      const roomId = nanoid();
      // add a new room to the rooms object
      rooms[roomId] = {
        name: roomName,
      };

      socket.join(roomId);

      // broadcast an event saying there is a new room
      socket.broadcast.emit(EVENTS.SERVER.ROOMS, rooms);

      // emit back to the room creator with all the rooms
      socket.emit(EVENTS.SERVER.ROOMS, rooms);
      // emit event back the room creator saying they have joined a room
      socket.emit(EVENTS.SERVER.JOINED_ROOM, roomId);
    });

    /*
     * When a user sends a room message
     */

    socket.on(
      EVENTS.CLIENT.SEND_ROOM_MESSAGE,
      ({ roomId, message, username }) => {
        const date = new Date();

        socket.to(roomId).emit(EVENTS.SERVER.ROOM_MESSAGE, {
          message,
          username,
          time: `${date.getHours()}:${date.getMinutes()}`,
        });
      }
    );

    /*
     * When a user joins a room
     */
    socket.on(EVENTS.CLIENT.JOIN_ROOM, (roomId) => {
      socket.join(roomId);

      socket.emit(EVENTS.SERVER.JOINED_ROOM, roomId);
    });
  });
}

export default socket;

 

app.ts에서 서버를 열어준 후, cors 문제를 해결하는 코드를 작성했다.

또한, socket.ts에서 소켓을 열어 서버상에서의 이벤트 송수신 코드를 작성했다. 

 

나머지 코드는 github에서 확인 바랍니다.

 

https://github.com/act99/stock-chat

 

GitHub - act99/stock-chat: stock&coin chart with Chatting Nestjs, Apollo, Redux, Redux-Toolkit

stock&coin chart with Chatting Nestjs, Apollo, Redux, Redux-Toolkit - GitHub - act99/stock-chat: stock&coin chart with Chatting Nestjs, Apollo, Redux, Redux-Toolkit

github.com