Intro
개발 환경을 구축하고 사용자가 처음 접속하면 보여질 방과 관련된 기능들을 개발했다.
사용자가 방을 생성하고, 다른 사용자가 생성된 방에 참가하면 오목 경기를 시작시킬 것이다.
그 후에 들어오는 사용자들은 관전자로 놔둘 생각이다.
React를 처음 써봐서 기능을 개발하며 많이 헤맸지만, 생각보다 간단하고 강력한 기능을 제공해줘서 금방 이정도까지 만들 수 있었던것 같다.
방 생성

input에 방 이름을 입력하고 Enter를 치거나 '방 만들기' 버튼을 클릭하면 해당 이름으로 방이 생성된다.
아래의 경우 방이 생성되지 않도록 설정했다.
- 같은 이름의 방이 이미 존재하는 경우
- 사용자가 이미 다른 방에 참가중인 경우
- 방 이름에 아무것도 입력하지 않았을 경우
코드는 아래와 같다.
이벤트 발생 시 roomname이 공백인지 확인하고 서버에 'room_new' Event로 방 이름을 전달하도록 했다.
const NewRoom = () => {
  const handleNewRoom = (event) => {
    event.preventDefault();
    const name = event.target.roomname.value;
    event.target.roomname.value = "";
    if (name.length == 0) return;
    socket.emit("room_new", name);
  };
  return (
    <div className="newroom">
      <form className="newroom__form" onSubmit={handleNewRoom}>
        <input
          className="newroom__input"
          type="text"
          name="roomname"
          placeholder="방 이름"
        ></input>
        <button className="newroom__submit">방 만들기</button>
      </form>
    </div>
  );
};방 목록

사이트에 접속하면 소켓이 연결되며 방 목록을 조회하도록 설정했다.
서버에서 온 Object Array를 React Component Array로 바꾸는데 고생 좀 했다.
socket.on을 함수 밖으로 빼내고 싶었는데 roomList는 함수 밖으로 꺼내면 에러가 발생해서 어쩔 수 없이 socket.on을 함수 내부에 뒀다.
같은 socket event listener를 여러개 둘 수 있기 때문에 별 문제는 안되겠지만 나중에 해결방법이 떠오르면 고쳐야겠다.
const RoomItem = (room) => {
  const handleEnterRoom = () => {
    socket.emit("room_enter", room.name);
  };
  return (
    <li key={room.name} className="room-list__item">
      <p className="room-list__name">{room.name}</p>
      <button className="room-list__enter" onClick={handleEnterRoom}>
        입장하기
      </button>
    </li>
  );
};
const RoomList = () => {
  const [roomList, setRoomList] = React.useState([]);
  socket.on("room_change", (list) => {
    setRoomList(list);
  });
  return (
    <div className="room-list">
      <h3>방 목록</h3>
      <ul className="room-list__container">{roomList.map(RoomItem)}</ul>
    </div>
  );
};
서버 코드는 아래와 같다.
wsServer.on("connection", (socket) => {
  socket.onAny((event) => {
    console.log(`Socket event: ${event}`);
  });
  //방 만들기
  socket.on("room_new", (name) => {
    name = name.trim();
    console.log(`Socket ${socket.id} is creating room ${name}.`);
    //Socket은 ID와 같은 Room을 Default로 갖고 있음
    if (socket.rooms.size > 1) {
      console.log(`socket ${socket.id} is already in room.`);
      console.log(socket.rooms);
      socket.emit("error", "이미 다른 방에 참가중입니다.");
      return;
    }
    //동일한 방이 존재할 경우
    if (!checkDuplicateRoomName(name)) {
      console.log(`Room name ${name} already exists.`);
      socket.emit("error", "동일한 방이 이미 존재합니다.");
      return;
    }
    const roomInfo = {
      name: "room",
      blackPlayer: "",
      whitePlayer: "",
      takes: [],
    };
    roomInfo.name = name;
    roomInfo.blackPlayer = socket.id;
    publicRoom.push(roomInfo);
    wsServer.sockets.emit("room_change", publicRoom);
    socket.join(name);
    socket.emit("room_enter", name);
    console.log(publicRoom);
  });방 참가 / 퇴장

방 생성 / 참가 이후에 서버에서 'room_enter' 이벤트를 주면 오목 게임이 진행되는 방으로 화면이 전환된다.
게임 화면은 아직 구현되지 않았다.
방 나가기 버튼을 누르면 서버에 'room_leave' 이벤트를 주고, 서버에서 이벤트를 다시 주면 대기실 화면으로 전환된다.
'room_enter', 'room_leave' 이벤트가 들어오면 gaming state를 변경하고, state에 따라 화면을 다시 렌더링한다.
const WaitingRoom = () => {
  return (
    <>
      <NewRoom />
      <RoomList />
    </>
  );
};
const GamingRoom = () => {
  return (
    <>
      <button
        onClick={() => {
          socket.emit("room_leave");
        }}
      >
        방 나가기
      </button>
    </>
  );
};
const App = () => {
  const [gaming, setGaming] = React.useState(false);
  socket.on("room_enter", () => {
    setGaming(true);
  });
  socket.on("room_leave", () => {
    setGaming(false);
  });
  return (
    <>
      <Header />
      {gaming ? <GamingRoom /> : <WaitingRoom />}
    </>
  );
};
방 퇴장 시 자꾸 이런 에러가 뜨는데 나중에 수정해야겠다.

대기실 화면

다음엔 실제 오목 게임을 구현해야겠다.
'Projects > Socket Omok' 카테고리의 다른 글
| [Socket Omok] 6. 착수 위치 미리보기 및 선택하기 (0) | 2022.06.13 | 
|---|---|
| [Socket Omok] 5. 바둑판, 바둑알 표시하기 (0) | 2022.06.06 | 
| [Socket Omok] 4. 플레이어 참가 기능 개발 (0) | 2022.06.06 | 
| [Socket Omok] 2. 개발환경 구성하기 (0) | 2022.06.02 | 
| [Socket Omok] 1. 프로젝트 시작 (0) | 2022.05.31 | 
 
										
									 
										
									