Node 강의/심화

1-7 커넥션 핸들러 ( 점프 게임 )

kagan-draca 2024. 9. 27. 16:36

커넥션 핸들러 :

 

- 웹소켓과 TCP에서는 데이터 통신을 위해 Connection을 맺어야

하는데 그 Connection을 어떻게 관리할 것인지, 어떻게 핸들링할 것인지

 

- 서버에서 유저를 위한 데이터를 생성해 저장할 수 있다.

 

1. 기획 리마인드 

스테이지 관련 내용을 리마인드 해봅시다.

☑️ 스테이지에 따라서 더 높은 점수 획득

  • 0점 , 1스테이지
  • 1000점, 2스테이지
  • 위와 같이 점수로 나뉘어서 스테이지 구분
  • 스테이지가 올라갈수록 시간당 높은 점수 획득 가능
    • ex) 1스테이지 = 1점 per 1s, 2스테이지 = 2점 per 1s

‘0점, 1스테이지’ 의 내용을 구현하려면 유저는 연결(계정)이

생성되는 즉시 스테이지에 관한 정보를 가지고 있어야합니다.

해당 내용에 따라 배운 내용을 토대로 만들어봅시다

 

 

그럼 스테이지를 위한 

 

models(현재 존재하는 파일)/stage.model.js를 만들어

stage와 관련된 필요 기능을 구현해보겠습니다.

 

models/stage.model.js

// key : uuid, value : array -> stage 정보는 배열
const stages = {};

// 스테이지 초기화
const createStage = (uuid) => {
  stages[uuid] = [];
};

// 유저에게 현재 스테이지
const getStage = (uuid) => {
  return stages[uuid];
};

// 유저에게 제공할 스테이지
const setStage = (uuid, id) => {
  return stages[uuid].push({ id });
};

export { createStage, getStage, setStage };

 

그럼 스테이지가 제공되야 할 위치는 언제일까요?

 

처음에는 유저가 게임에 접속했을 때 입니다.

 

유저가 처음 접속했을 장소인

 

register.handler.js의 registerHandler함수로 가봅시다.

handlers/register.handler.js

import { addUser } from '../models/user.model.js';
import { v4 as uuid } from 'uuid';
import { handleDisconnect } from './helper.js';

const registerHandler = (io) => {
  io.on('connection', (socket) => {
    // 최초 커넥션을 맺은 이후 발생하는 각종 이벤트를 처리하는 곳

    const userUUID = uuid;
    // v4 메서드를 바탕으로 uuid를 생성 및 담아준다.
    addUser({ uuid: userUUID, socketId: socket.id });
    // socketId는 socket.id로 받아온다.

    //이 시점이 현재 유저가 막 접속을 했을 시점 입니다.

    //접속 해제시 이벤트
    socket.on('disconnect', (socket) => handleDisconnect(socket, userUUID));
  });
  // io.on을 사용하면 'connection'이 발생할 때 까지
  // 소켓 객체가 대기하겠다는 의미
};

export default registerHandler;

 

addUser와 socket.on('disconnect', 생략) 사이가 현재는 유저가 접속한 이후 입니다.

 

그럼 이곳에 함수로해서 stage와 관련된 기능을 처리해줍시다.

 

handlers/helper.js에

const handleConnection = (socket, uuid) => {
  console.log(`New user connected ${uuid}`);
};
export { handleDisconnect, handleConnection };

을 추가시켜 줍니다.

 

그리고,

handlers/register.handler.js도

import { handleDisconnect, handleConnection } from './helper.js';

handleConnection을 추가해주고,

const registerHandler = (io) => {
  io.on('connection', (socket) => {
    // 최초 커넥션을 맺은 이후 발생하는 각종 이벤트를 처리하는 곳

    const userUUID = uuid;
    // v4 메서드를 바탕으로 uuid를 생성 및 담아준다.
    addUser({ uuid: userUUID, socketId: socket.id });
    // socketId는 socket.id로 받아온다.

    //이 시점이 현재 유저가 막 접속을 했을 시점 입니다.
    handleConnection(socket, userUUID);

    //접속 해제시 이벤트
    socket.on('disconnect', (socket) => handleDisconnect(socket, userUUID));
  });
  // io.on을 사용하면 'connection'이 발생할 때 까지
  // 소켓 객체가 대기하겠다는 의미
};

handleConnection(socket, userUUID)를 addUser와 socket.on 사이에 추가해줍니다.

 

handlers/helper.js에 돌아와

handleConnection함수를 

const handleConnection = (socket, uuid) => {
  console.log(`New user connected ${uuid} with socket Id ${socket.id}`);
  console.log('Current users : ', getUser());

  const {stages} = getGameAssets();
  // stages 배열에서 0번 째 = 첫 번째 스테이지
  setStage(uuid, stages.data[0].id);
  console.log('Stage : ' + getStage(uuid));

  socket.emit('connection', { uuid });
  //소켓을 가지고 있는 유저 본인에게 정보를 보내줍니다.
};

위와 같이 바꿔줍니다.

 

getGameAssets()로 (일부 내용들 가져옴)

let gameAssets = {};
const [stages, items, itemsUnlocks] = await Promise.all([
      readFileAsync('stage.json'),
      readFileAsync('item.json'),
      readFileAsync('item_unlock.json'),
    ]);
    // readFileAsync로 assets 폴더 안 .json파일
    // 을 읽어오고, 배열에 값을 저장해줍니다.
    // 파일 이름을 따로 관리하는 방식으로
    // 하드 코딩을 안 하는 방법도 있다.

    gameAssets = { stages, items, itemsUnlocks };
const getGameAssets = () => {
  return gameAssets;
};

 

위의 내용들을 바탕으로 가져온 Game의 핵심 Assets 정보들을 담고 있는 배열인

gameAssets를 getGameAssets함수로 return해줍니다.

 

그 결과 handlers/helper.js의 handleConnection 함수 내부에서

const { stage } = getGameAssets();

 

setStage(uuid, stages.data[0].id)

 

stages의 0번 째 → 첫 스테이지 id와 uuid(uer unique id)

가 setStage로 전달 돼

// 유저에게 제공할 스테이지
const setStage = (uuid, id) => {
  return stages[uuid].push({id});
};

 

첫 번째로 이동하게 됩니다.

 

그 후,

  socket.emit('connection', { uuid });
  //소켓을 가지고 있는 유저 본인의 정보를 보내줍니다.

유저의 소켓으로 유저 본인의 정보를 보내줍니다.