IceCraft - 방 만들기 모달창 리팩토링
소켓부분을 커스텀 훅으로 리팩토링이 진행됨에 따라
메인페이지, 메인페이지에서 방 생성하는 모달창 리팩토링을 진행하였다.
이전 코드
useEffect(() => {
socket.on("createRoom", ({ room_id }) => {
roomId.current = room_id;
socket.emit("joinRoom", userId, room_id, nickname);
});
socket.on("createRoomError", (message) => {
toast.error(message);
isGoInClick.current = false;
});
socket.on("joinRoom", () => {
if (roomId.current) {
setRoomId(roomId.current);
setIsCreate(false);
if (selectedGame === "마피아") {
router.push(`/room/${roomId.current}/`);
}
return null;
}
});
socket.on("joinRoomError", (message) => {
toast.error(message);
isGoInClick.current = false;
});
return () => {
socket.off("createRoom");
socket.off("createRoomError");
socket.off("joinRoom");
socket.off("joinRoomError");
};
}, []);
이전코드에서는 그대로 socket.on으로 연결하고
socket.emit 보내고
socket.off 로 언마운트 되면 종료시키는 내용을 전부 담고 있었다.
일일이 한줄씩 써주고 있었던 내용들을 커스텀 훅으로 변경함에 따라,
메인페이지도 리팩토링을 진행하게 되었다.
리팩토링 - 커스텀 훅으로 변경
const createSocket = {
createRoom: ({ room_id }: CreateRooms) => {
roomIdRef.current = room_id;
socket.emit("joinRoom", userId, roomIdRef.current, nickname);
},
createRoomError: (message: string) => {
toast.error(message);
isGoInClick.current = false;
},
joinRoom: () => {
if (roomIdRef.current) {
setRoomId(roomIdRef.current);
setIsCreate(false);
router.push(`/room/${roomIdRef.current}/`);
}
},
joinRoomError: (message: string) => {
toast.error(message);
isGoInClick.current = false;
}
};
useSocketOn(createSocket);
훨씬 코드가 깔끔해졌다...!
커스텀훅으로 변경하고, 메인페이지 방 만들기 모달창은
방 이름과 인원수를 선택하고 확인 버튼을 눌렀을때,
방 만들기 핸들러가 실행되면서 서버에 "createRoom"을 보내주고
"joinRoom"에 있는 내용들을 보내 주어야 했다.
방 만들기 핸들러(확인버튼) 코드
//NOTE - 방 만들기 핸들러
const createRoomSubmitHandler = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
try {
if (!roomTitle.trim()) {
toast.error("방 제목을 입력해 주세요.");
return;
}
if (!isGoInClick.current && selectedGame === "마피아") {
isGoInClick.current = true;
socket.emit("createRoom", roomTitle, selectedGame, numberOfPlayers);
setSelectedGame("마피아");
setRoomTitle("");
setNumberOfPlayers(5);
return;
} if (!isGoInClick.current && selectedGame === "노래맞추기") {
toast("노래 맞추기 게임은 준비중입니다.");
return;
}
} catch (error) {
console.log("error", error);
}
};
리팩토링한 방 만들기 핸들러 코드이다.
하지만 여기서 문제가 발생하는데....
사용자가 방 내용을 입력하고 확인 버튼을 누르면
socket.emit("createRoom", roomTitle, selectedGame, numberOfPlayers);
클라이언트측에서 서버에 사용자가 입력한 내용을 보내주면,
서버에서는 "createRoom" 에 대한 수신을 받고 난 뒤
서버에서 다시 클라이언트에게 "JoinRoom"을 송신해준다!
그러면 클라이언트측에서는 서버에서 기다렸다가 "JoinRoom"을 받아오는 구조였다.
그림으로 설명하면 이렇게 순서대로 클라이언트와 서버간 이렇게 socket.io로 양방향 통신 순서를 진행 하고 있는데
문제는 방 만들기 버튼을 누르자마자
클라이언트에서 "createRoom" 내용과 "JoinRoom" 내용을 전부 보내줘버렸다 ^_ㅠ
그림대로 이렇게 한꺼번에 보내주고 있다는 사실...!
이렇게 묶어서 보내주다보니
서버에서 createRoom을 클라이언트에서 받아왔으면,
"joinRoom" 메서드를 클라이언트에게 줘야하는데
클라이언트측에서 한꺼번에 createRoom과 joinRoom을 동시에 보내주다보니
joinRoom에서 서버에서 보내줄 roomId 의 값이 undefined으로 뜨는 현상이 일어나고 말았다.
처음에는 방 만들기 핸들러에 emit으로 서버에게 보낼 때,
"createRoom"에 대한 정보와 "joinRoom"값을 동시에 보내주었는데
방 만들기 핸들러에서는 "createRoom"에 대한 정보를 먼저 보내주도록 수정하였다.
방 만들기 모달창 핸들러
if (!isGoInClick.current && selectedGame === "마피아") {
isGoInClick.current = true;
socket.emit("createRoom", roomTitle, selectedGame, numberOfPlayers);
클라이언트에서 처리 할 내용(중략)
return;
}
그리고 서버에서 "createRoom" 메서드를 수신하고 난 뒤,
useRef로 room_id값을 넣고, roomId 값을 받아오고 나서,
"joinRoom"으로 보내주는 방식으로 진행하였다.
createRoom 소켓 이벤트
createRoom: ({ room_id }: CreateRooms) => {
roomIdRef.current = room_id;
socket.emit("joinRoom", userId, roomIdRef.current, nickname);
},
서버에서 "createrRoom"을 수신하면,
roomId 값을 useRef에 저장해두고,
"joinRoom" 에 대한 내용을 송신한다.
joinRoom 소켓 이벤트
joinRoom: () => {
if (roomIdRef.current && selectedGame === "마피아") {
setRoomId(roomIdRef.current);
setIsCreate(false);
setIsEntry(true);
router.push(`/room/${roomIdRef.current}/`);
}
},
현재 roomId에 값이 있고, 게임 이름이 마피아인 경우 RoomId값을 저장한다.
그리고 사용자가 방을 생성하고 들어가면, joinRoom이벤트가 실행되어
해당방으로 이동할 수 있도록 router.push를 넣어준다.
클라이언트에서 emit으로 createRoom을 먼저 받고, 그뒤로 RoomId 값이 들어오면 진행할 수 있도록
콜백함수로 시도를 해보았는데,
joinRoom에 있는 내용을 송신하면 서버에서 joinRoom에 대한 내용의 값을 전부 인식을 못했다.
알고보니 서버에서 코드도 같이 콜백함수로 맞춰줘야 joinRoom을 받을 수 있었다...ㅠㅠ
어찌저찌 결과는 쉽게 해결한거 같지만 처음에 삽질을 엄청했다 ㅜㅜ
서로 송수신하면서 코드파악을 하고 적용하는데 시간이 오래걸렸다.
계속 console.log로 추적해보고 고민해보고 서버코드도 확인해보면서 해결하게 되었다.