1. 백엔드 서버 nodejs
소스 : https://github.dev/braverokmc79/react-chatting
전체적인 설명
Express 서버 설정:
- Express 애플리케이션을 생성하고, HTTP 서버를 만듭니다.
- CORS를 설정하여 모든 출처에서 접근을 허용하고, 특정 HTTP 메서드와 헤더를 허용합니다.
Socket.IO 초기화:
- Socket.IO를 초기화하고, 클라이언트 연결 시 CORS 설정을 추가합니다.
- 클라이언트가 소켓에 연결되었을 때 발생하는 이벤트('connect')를 처리합니다.
사용자 관리:
- join 이벤트: 사용자가 방에 참여할 때 발생하며, 사용자를 추가하고 방에 참여시키고 환영 메시지를 보냅니다.
- sendMessage 이벤트: 사용자가 메시지를 보낼 때 발생하며, 해당 방의 모든 사용자에게 메시지를 전송합니다.
- disconnect 이벤트: 사용자가 연결을 끊을 때 발생하며, 사용자를 제거하고 방의 다른 사용자들에게 알립니다.
사용자 관리 함수:
- 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
댓글 ( 0)
댓글 남기기