본문 바로가기

portfolio

리액트 노드 socket.io를 활용한 실시간 영화예매시스템 구축

서버에서 socket.emit 이벤트함수를 발신하고 클라이언트에서 이벤트를 발생시켜 socket.on 함수로 수신하면 실시간으로 양방향 통신이 가능하다.
 
 
server.js

io.on("connection", (socket) => {
  console.log("A user connected");

  // 클라이언트가 'requestData' 이벤트를 보내면 데이터베이스 조회
  socket.on("requestData", () => {
    const query = "SELECT * FROM seats";

    // 데이터베이스 조회 실행
    db.query(query, (err, results) => {
      if (err) {
        // 에러가 있다면 클라이언트에 에러 전송
        socket.emit("dataResponse", {
          status: "error",
          message: err.message,
        });
        return;
      }

      // 조회 결과를 클라이언트에 전송
      socket.emit("dataResponse", { status: "ok", data: results });
    });

    // 'updateMovie' 이벤트 처리
    socket.on("updateMovie", (data) => {
      const updateQuery = "UPDATE seats SET status = '예매완료' WHERE id = ?";
      db.query(updateQuery, [data.id], (err, results) => {
        if (err) {
          socket.emit("updateResponse", {
            status: "error",
            message: err.message,
          });
          return;
        }
        // 변경된 데이터 조회
        db.query("SELECT * FROM seats", (err, updatedResults) => {
          if (err) {
            socket.emit("dataResponse", {
              status: "error",
              message: err.message,
            });
            return;
          }
          // 모든 클라이언트에게 변경된 데이터 브로드캐스트
          io.emit("dataResponse", { status: "ok", data: updatedResults });
        });
      });
    });
  });

 
서버에서 데이터베이스 조회, 수정후 조회 이벤트 함수를 클라이언트로 발신 이때 수정후 조회이벤트를 보면 io.emit은 모든 클라이언트에게 변경된 상태데이터를 실시간으로 전송된다. 그러니깐 브라우저를 여러개 열면 하나의 브라우저에서 상태를 변경시키면 다른 브라우저에서 새로고침 안하고 실시간으로 변경된 상태를 볼수 있다
 
 
 
 
client.js

import React, { useState, useEffect } from "react";
import { socket } from "../src/socket";

function App() {
  const [data, setData] = useState([]); // 객체를 저장할 상태로 초기화

  function updateMovie(id) {
    // 서버에 'updateMovie' 이벤트 전송
    socket.emit("updateMovie", { id });
  }

  useEffect(() => {
    // 'dataResponse' 이벤트를 수신 대기
    // 소켓 연결을 수동으로 시작
    socket.connect();

    // 데이터 요청
    socket.emit("requestData");

    socket.on("dataResponse", (response) => {
      if (response.status === "ok") {
        console.log(response.data); // 'data' 필드 내용만 따로 로그로 출력
        // 서버로부터 응답받은 데이터를 상태에 저장
        setData(response.data);
      } else {
        // 오류 처리
        console.error("Error fetching data:", response.message);
      }
    });

    // 'updateResponse' 이벤트 수신
    socket.on("updateResponse", (response) => {
      if (response.status === "ok") {
        // 서버로부터의 응답 처리: 데이터 상태 업데이트
        setData((prevData) =>
          prevData.map((item) =>
            item.id === response.data.id
              ? { ...item, movie: response.data.movie }
              : item
          )
        );
      } else {
        // 오류 처리
        console.error("Error updating data:", response.message);
      }
    });

    // 컴포넌트가 언마운트될 때 리스너 제거
    return () => {
      socket.off("dataResponse");
      socket.off("updateResponse");
      socket.disconnect();
    };
  }, []);

  return (
    <div>
      <h1>영화관 예매시스템</h1>
      <ul>
        {data.map((item, index) => (
          <li key={index}>
            ID: {item.id}, 예매현황: {item.status}, 좌석번호: {item.seatNumber}
            <button
              onClick={() => updateMovie(item.id)}
              disabled={item.status === "예매완료"}
            >
              예매하기
            </button>
          </li>
        ))}
      </ul>
    </div>
  );
}

export default App;

 
서버로부터 응답받은 데이터를 setData상태에 저장하고 데이터조회,수정  'dataResponse ', 'updateResponse' 이벤트 수신하여 이벤트를 실행시킨다 버튼을 누르면 예매현황 상태가 예매완료로 변경되고 버튼이 비활성화되어서 모든 클라이언트에게 전송된다 
 
 

mysql데이터를 조회해보면 status값이 예매완료로 변경된것을 확인해 볼 수 있다




 
 
테스트 화면