• 서버 측 코드(node.js , express)
// 영화관을 만드는데 관을 1번비행기 2번비행기 3번비행기 나누어서 3개로 // 좌석을 예약 할수있게 // 사용할 모듈 // socket.io express ejs // 서버 대기 // view 세팅 // 소켓 연결 까지 const express = require("express"); const app = express(); const path =require("path"); // 선택된 자리들을 보여줄 배열 let seats = []; let temp = [ [1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1], [1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1], [1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1], [1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1], [1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1] ]; let temp2 = [ [1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1], [1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1], [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1], [1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1], [1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1] ]; let temp3= [ [1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1], [1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1], [1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1], [1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1], [1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1] ]; let seatsArr = [temp, temp2, temp3]; // 선택한 비행기의 인덱스 let index = 0; app.set("views",path.join(__dirname,"page")); app.set("view engine","ejs"); app.unsubscribe(express.urlencoded({extended: false})); app.get('/',(req,res)=>{ res.render("main"); }) const socketio = require("socket.io"); app.get("/seats/:id",(req,res)=>{ index = req.params.id; seats = seatsArr[index]; // 요청에 대한 응답으로 seatsArr배열에서 id로 전달한 인덱스로 호출한 배열을 // 응답해준다. res.send(seats); }) const server=app.listen(8000,()=>{ console.log("server on"); }) const io = socketio(server); io.sockets.on("connection",(socket)=>{ console.log("접속했습니다."); socket.on("reserve",(data)=>{ console.log("예약"); let seatTemp = seatsArr[data.selectCount]; seatTemp[data.y][data.x] = 2; io.sockets.emit('reserve',data); }) })
• 서버 설정:
• app.set("views" ,path.join(__dirname,"page")) //view 파일의 경로 설정
• app.set("view engine","ejs") // view 파일로 ejs 템플릿 엔진을 사용
• app.unsubscribe(express.urlencoded({extended:false})) // 폼 데이터를 파싱하기 위한 미들웨어 설정
• 클라이언트 요청 처리:
• app.get("/seats/:id" , (req,res) =>{ ... } //seats/:id 경로에 대한 get 요청을 처리하며, 해당 id에 해당하는 비행기의 좌석정보를 응답한다. 😂😂😂(어렵다)
• 소켓 통신 :
• io.sockets.on("connection", (socket) => { ... } // 클라이언트와의 소켓 연결을 처리하는 함수
클라이언트로부터 "reserve" 이벤트를 수신하고 다른 클라이언트에게 예약 정보를 전달 😂😂😂(어렵다)
• 좌석 예약 처리:
• socket.on("reserve", (data) =>{...} // 클라이언트로부터 예약 정보를 받아서 처리하는 함수
좌석 예약 상태를 업데이트하고 "reserve" 이벤트를 다른 클라이언트에게 전송 😂😂😂(어렵다)
어려운 부분 다시
• app.get("/seats/:id" , (req,res) =>{ ... }
// 이 코드는 클라이언트가 /seats/:id 경로로 get 요청을 보낼때 서버에서 처리하는 부분
예를 들어 /seats/1 경로로 get 요청이 오면 id가 1인 비행기의 좌석 정보를 응답으로 전송한다.
• io.sockets.on("connection", (socket) => { ... }
//
• socket.on("reserve", (data) =>{...}
// 클라이언트가 좌석을 예약할려고 할때 해당 이벤트가 발생한다.
서버는 받은 예약 정보(data)를 처리하고 좌석 예약 상태를 업데이트 한다.
이후 reserve 이벤트를 다른 클라이언트에게 전송하여 실시간으로 좌석 예약 상태를 업데이트한다.
새로알게된 내용
• params??
express.js에서 요청 객체의 하위 객체중 하나
req.params 객체는 url의 경로 매개변수를 포함하고 있다.
예를 들어 "/users/:id와 같은 경로에 대한 요청이 있을 때. "id" 는 동적으로 변하는 사용자 Id값을 나타낸다.
코드 분석
app.get("/seats/:id",(req,res)=>
{ index = req.params.id;
seats = seatsArr[index];
1. 클라이언트가 "/seats/:id 경로로 get 요청을 보낸다.
2. 서버는 해당 값을 받고 req.params.id를 통해 동적인 경로 값에 접근한다. 이 값을 인덱스에 저장
3. seatsArr 배열에서 index를 사용하여 해당 비행기의 좌석 정보를 가져온다. 좌석 정보는 seats 변수에 할당
4. res.send(seats)를 사용하여 클라이언트에게 좌석 정보를 응답한다.
• 클라이언트 측 코드 (HTML,javaScript)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> .line { overflow: hidden; } .seat{ margin: 2px; float: left; width: 30px; height: 30px; border-radius: 3px; } .enable{ background-color: gray; } .disable{ background-color: blueviolet; } </style> <script src="/socket.io/socket.io.js"></script> <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> </head> <body> <div>비행기</div> <!-- select 선택 박스 태그 --> <select name="" id="selectBtn"> <option value="0">1번</option> <option value="1">2번</option> <option value="2">3번</option> </select> <div id="content"></div> </body> <script> window.onload =() =>{ const socket = io.connect(); socket.on('reserve',(data)=>{ if(data.selectCount == selectBtn.selectedIndex){ let target = document.querySelector(`div[data-x="${data.x}"][data-y="${data.y}"]`); target.classList.remove("enable"); target.classList.add("disable"); } }) let selectCount = 0; selectBtn.onchange = function(){ content.innerHTML = ""; // select 태그의 선택한 옵션의 value를 호출한다. selectCount = this.selectedIndex; console.log(selectCount); // 시트 생성 함수 여기에 getseats(selectCount); } // 시트를 클릭해서 예약하는 함수 const onClickSeat = function(){ // 클래스가 있는지 확인 메서드 contains if(this.classList.contains("disable")){ // 이미 예약이 되어있으면 여기서 끝 return; } // 어트리뷰트 데이터 속성을 호출 getAttribute 메서드로 매개변수로 가져올 속성 이름 let x = this.getAttribute("data-x"); let y = this.getAttribute("data-y"); if(confirm("이 좌석을 예약할거임?")){ // socket 이벤트를 푸쉬할 예정 socket.emit("reserve",{ x, y, selectCount }) }else{ alert("ㅇㅇ 하지마셈"); } } // 시트 생성 함수 function getseats(selectIndex){ // 요청 응답으로 시트를 가져올 예정 // 변수로 받을 예정 // axios 무조건 이것만 쓸거임 // CDN으로 사용 // 요청은 get방식이고 매개변수는 아이디 값으로 요청 axios.get("/seats/" + selectIndex).then((e)=>{ // 요청 이후 응답받은 값이 e // 시트 배열이 넘어온다. console.log(e); let {data} = e; data.forEach((line, indexY) =>{ let lineElem = document.createElement("div"); // 시트들의 열 lineElem.classList.add("line"); line.forEach((seat, indexX)=>{ let seatElem = document.createElement("div"); // 시트들 seatElem.classList.add("seat"); // 데이터 속성 이라는 어트리뷰트속성을 사용 // setAttribute : 어트리뷰트 속성을 추가 메서드 // 첫번째 매개변수는 속성의 이름 // 두번째 매개변수는 속성의 값 seatElem.setAttribute("data-x",indexX); seatElem.setAttribute("data-y",indexY); // 빈공간, 예약 가능한 시트, 이미 예약된 시트 if(seat == 1){ seatElem.classList.add("enable"); // 시트를 클릭하면 예약 seatElem.addEventListener("click",onClickSeat); }else if(seat == 2){ seatElem.classList.add("disable"); } lineElem.appendChild(seatElem); }); content.appendChild(lineElem); }) }) } } </script> </html>
• 소켓 통신 :
• const socket = io.connect() // 클라이언트가 서버와 소켓 연결을 수행한다.
• socket.on(`reserve`, (data) => {...} //서버로부터 reserve 이벤트를 수신하면 실행되는 콜백함수
• 비행기 선택 :
•selectBtn.onchange = function() {...}
// 선택한 비행기에 해당하는 좌석을 서버로부터 가져와서 표시한다.
• 좌석 예약
•const onClickseat = function() {...}
// 좌석을 클릭했을때 실행되는 함수 예약 가능한 좌석인 경우에만 동작가능하다.
코드 분석
const socket = io.connect(); socket.on('reserve',(data)=>{ if(data.selectCount == selectBtn.selectedIndex){ let target = document.querySelector(`div[data-x="${data.x}"][data-y="${data.y}"]`); target.classList.remove("enable"); target.classList.add("disable"); } })
1. 클라이언트에서 소켓을 생성하고 서버에 연결한다.
2. 서버로부터 reserve 이벤트를 수신할 때의 동작을 정의
즉 다른 클라이언트에서 좌석 예약 정보를 전송했을 때 이를 수신하여 처리한다.
3.if (data.selectCount == selectBtn.selectedIndex) { ... }
// 클라이언트에서 수신한 예약 정보와 현재 클라이언트에서 선택한 비행기가 일치하는지 확인하는 조건문
•data.selectCount는 클라이언트에서 선택한 좌석정보
• selectBtn.selectedIndex는 현재 클라이언트에서 선택된 비행기의 인덱스
// 이 값은 선택한 비행기의 좌석 번호를 나타냄
4. let target = document.querySelector('div[data- ....)
// html 문서에서 특정 선택자에 해당하는 첫 번째 요소를 선택한다.
이 부분에서는 div 요소중에서 data-x 속성값이 data.x와 일치하고 data-y 속성값이 data.y와 일치하는 요소를 선택함
'node.js' 카테고리의 다른 글
socket 활용 채팅방 만들기(방을 따로 나눠서 유저간에 귓속말) (0) | 2023.05.25 |
---|---|
node.js에 관한것 (1) | 2023.05.23 |
로그인 게시판 혼자 만들수있게 연습 (0) | 2023.05.23 |
sequelize orm을 사용하여 mysql 데이터베이스와 연동/ foreach 함수 (0) | 2023.05.19 |
node.js 로그인 회원가입 까지 토큰 만료기간 설정 (0) | 2023.05.17 |