React

 

 

 

1. 백엔드 서버 nodejs

 

소스 : https://github.dev/braverokmc79/react-chatting

 

 

전체적인 설명

  1. Express 서버 설정:

    • Express 애플리케이션을 생성하고, HTTP 서버를 만듭니다.
    • CORS를 설정하여 모든 출처에서 접근을 허용하고, 특정 HTTP 메서드와 헤더를 허용합니다.
    •  
  2. Socket.IO 초기화:

    • Socket.IO를 초기화하고, 클라이언트 연결 시 CORS 설정을 추가합니다.
    • 클라이언트가 소켓에 연결되었을 때 발생하는 이벤트('connect')를 처리합니다.
    •  
  3. 사용자 관리:

    • join 이벤트: 사용자가 방에 참여할 때 발생하며, 사용자를 추가하고 방에 참여시키고 환영 메시지를 보냅니다.
    • sendMessage 이벤트: 사용자가 메시지를 보낼 때 발생하며, 해당 방의 모든 사용자에게 메시지를 전송합니다.
    • disconnect 이벤트: 사용자가 연결을 끊을 때 발생하며, 사용자를 제거하고 방의 다른 사용자들에게 알립니다.
    •  
  4. 사용자 관리 함수:

    • addUser: 사용자를 추가하고 방에 참여시킵니다.
    • removeUser: 사용자를 제거합니다.
    • getUser: 특정 ID를 가진 사용자를 반환합니다.
    • getUsersInRoom: 특정 방에 있는 모든 사용자를 반환합니다.

 

 

 

1)package.json

{
  "name": "server",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start":"nodemon index.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "cors": "^2.8.5",
    "express": "^4.19.2",
    "nodemon": "^3.1.3",
    "socket.io": "^4.7.5"
  }
}

 

 

2)router.js

const express = require("express");
const router = express.Router();

router.get("/", (req, res) => {
  res.send({ response: "Server is up and running." }).status(200);
});

module.exports = router;

 

 

3)index.js

const express = require('express'); // Express 모듈을 불러옵니다.
const socketio = require('socket.io'); // Socket.IO 모듈을 불러옵니다.
const http = require('http'); // HTTP 모듈을 불러옵니다.
const cors = require('cors'); // CORS 모듈을 불러옵니다.

const { addUser, removeUser, getUser, getUsersInRoom } = require('./users'); // 사용자 관리 함수를 불러옵니다.

const router = require('./router'); // 라우터를 불러옵니다.

const app = express(); // Express 앱을 생성합니다.
const server = http.createServer(app); // HTTP 서버를 생성합니다.

// CORS 설정
app.use(cors()); // 모든 출처에 대해 CORS를 허용합니다.
app.use((req, res, next) => {
  res.setHeader('Access-Control-Allow-Origin', '*'); // 모든 출처에 대해 허용합니다.
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE'); // 허용하는 HTTP 메서드를 설정합니다.
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); // 허용하는 헤더를 설정합니다.
  next(); // 다음 미들웨어로 넘어갑니다.
});

// Socket.IO 초기화 시 CORS 설정
const io = socketio(server, {
  cors: {
    origin: 'http://localhost:3000', // React 앱이 실행되는 주소
    methods: ['GET', 'POST'], // 허용하는 HTTP 메서드
    allowedHeaders: ['Content-Type'], // 허용하는 헤더
    credentials: true // 자격 증명을 허용합니다.
  }
});

app.use(router); // 라우터를 사용합니다.

io.on('connect', (socket) => { // 클라이언트가 소켓에 연결되었을 때 실행됩니다.
  socket.on('join', ({ name, room }, callback) => { // 'join' 이벤트를 수신합니다.
    const { error, user } = addUser({ id: socket.id, name, room }); // 사용자를 추가합니다.

    if (error) return callback(error); // 오류가 있으면 콜백으로 오류를 전달합니다.

    socket.join(user.room); // 사용자를 해당 방에 참여시킵니다.

    socket.emit('message', { user: '시스템', text: `${user.name}, welcome to room ${user.room}.` }); // 시스템이 환영 메시지를 보냅니다.
    socket.broadcast.to(user.room).emit('message', { user: 'admin', text: `${user.name} has joined!` }); // 다른 사용자들에게 참여 메시지를 보냅니다.

    io.to(user.room).emit('roomData', { room: user.room, users: getUsersInRoom(user.room) }); // 방 정보와 사용자 목록을 업데이트합니다.

    callback(); // 콜백을 실행합니다.
  });

  socket.on('sendMessage', (message, callback) => { // 'sendMessage' 이벤트를 수신합니다.
    const user = getUser(socket.id); // 사용자를 가져옵니다.

    if (user) {
      io.to(user.room).emit('message', { user: user.name, text: message }); // 메시지를 해당 방에 전송합니다.
    }

    callback(); // 콜백을 실행합니다.
  });

  socket.on('disconnect', () => { // 소켓 연결이 끊어졌을 때 실행됩니다.
    const user = removeUser(socket.id); // 사용자를 제거합니다.

    if (user) {
      io.to(user.room).emit('message', { user: 'Admin', text: `${user.name} has left.` }); // 다른 사용자들에게 퇴장 메시지를 보냅니다.
      io.to(user.room).emit('roomData', { room: user.room, users: getUsersInRoom(user.room) }); // 방 정보와 사용자 목록을 업데이트합니다.
    }
  });
});

server.listen(process.env.PORT || 5000, () => console.log(`Server has started.`)); // 서버를 실행합니다.

 

 

 

 

4)users.js

const users = []; // 사용자 목록을 저장할 배열입니다.

const addUser = ({ id, name, room }) => {
  name = name.trim().toLowerCase(); // 이름의 공백을 제거하고 소문자로 변환합니다.
  room = room.trim().toLowerCase(); // 방 이름의 공백을 제거하고 소문자로 변환합니다.

  const existingUser = users.find((user) => user.room === room && user.name === name); // 같은 방에 같은 이름의 사용자가 있는지 확인합니다.

  if (!name || !room) return { error: 'Username and room are required.' }; // 이름과 방이 없으면 오류를 반환합니다.
  if (existingUser) return { error: 'Username is taken.' }; // 같은 이름의 사용자가 있으면 오류를 반환합니다.

  const user = { id, name, room }; // 새로운 사용자를 생성합니다.

  users.push(user); // 사용자 목록에 추가합니다.

  return { user }; // 사용자 정보를 반환합니다.
}

const removeUser = (id) => {
  const index = users.findIndex((user) => user.id === id); // 사용자 목록에서 해당 ID를 가진 사용자의 인덱스를 찾습니다.

  if (index !== -1) return users.splice(index, 1)[0]; // 사용자가 있으면 목록에서 제거하고 반환합니다.
}

const getUser = (id) => users.find((user) => user.id === id); // 해당 ID를 가진 사용자를 반환합니다.

const getUsersInRoom = (room) => users.filter((user) => user.room === room); // 해당 방에 있는 모든 사용자를 반환합니다.

module.exports = { addUser, removeUser, getUser, getUsersInRoom }; // 함수들을 모듈로 내보냅니다.

 

 

Procfile

web: node index.js


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

about author

PHRASE

Level 60  라이트

뿔뿔이 흩어진 집안은 살아갈 수 없다. 저는 연방이 해체되거나 집안이 뿔뿔이 흩어지는 것을 바라지 않습니다. -링컨

댓글 ( 0)

댓글 남기기

작성