Skip to content

Commit

Permalink
Merge pull request #236 from boostcampwm-2024/dev-fe
Browse files Browse the repository at this point in the history
chore: dev-fe -> main
  • Loading branch information
dev-taewon-kim authored Dec 3, 2024
2 parents 4c18286 + 8ba9b1f commit 69d8570
Show file tree
Hide file tree
Showing 51 changed files with 1,053 additions and 433 deletions.
130 changes: 51 additions & 79 deletions fe/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,82 +7,54 @@
- 훅/컴포넌트 내부에서 사용: useRoomStore()
- React 외부의 비동기 작업, 이벤트 핸들러: useRoomStore.getState()

### 게임 시작했을 때 Timer와 Lyric이 등장하는 타이밍이 맞지 않음

- startGame을 이미 했는데 Intro 화면을 2초 보여줘서 그런 건가 싶음
- 게임 시작 버튼 클릭했을 때 Intro 화면을 GameScreen에서 먼저 2초 띄우고, startGame을 하도록 하면 되려나?
- 원인: Lyric 애니메이션 duration이 timeLimit으로 설정해서, 가사 길이가 짧으면 늦게 등장하게 됐던 것이었다.
- 가사의 길이를 동일하게 맞추지 않는 이상 등장하는 시간을 제한 시간과 완벽하게 맞출 수는 없을 것 같다.
- 해결: Lyric 애니메이션 delay 시간을 -0.5로 설정해서 길이가 짧은 가사는 게임 스크린 중앙쯤부터 등장하도록 했다.
- 적어도 '가사가 왜 안 나오지?' 생각은 안 들 것 같다..!

### 게임 진행 UI 구현 문제: 실시간은 너무 어려워

- startGame을 하면 turnChanged로 다음 차례 사용자 데이터(turnData)를 받는다.
- startRecording을 하면 해당 차례 사용자의 음성 데이터를 전달하고 채점 결과(result)를 받는다.
- 그런데 startGame을 하면 이 turnData가 계속 들어온다.
- 이게 문제가 뭐냐면, 음성 데이터 전달 -> 채점 -> 결과 -> 다음 턴 이런 순서로 되어야 하는데, 결과를 받기도 전에 다음 turnData가 들어와서 결과를 보여줄 수 없어진다. (제발 아직 오지 마.. 제발)
- 난 이게 내 역량 부족이라고 생각해 금, 토 꼬박 12시간을 바쳐서 해결해 보려고 했다. setTimeout 떡칠을 하고, 정말 별짓을 다 했는데 안 됐다. 뭐라고 표현하면 좋을까. 쓰나미를 구멍 난 우산으로 막겠다고 까불다가 집도 절도 잃어버린 물에 빠진 생쥐 꼴이 된 거 같다고 해야 하나. 몸도 마음도 너덜너덜해졌다.
- 내가 하도 찡찡대서 백엔드 쪽에서 이벤트를 하나 더 만들어 주셨다. 주말에 죄송함니다 진성님. 그리고 저를 살려주셔서 감사합니다,,
- 이제 클라이언트에서 result를 받은 후 next 이벤트를 보내야 다음 turnData를 받게 된다. 이제 돼야 한다. 되겠지..?
- next 이벤트 쓰고 바로 잘 되는 줄 알았는데 채점 중에서 결과로 안 넘어가질 때가 있다. (안 될 때가 더 많다)
- 잘 됐다가 안 됐다가 하는 게 너무 화가 난다,, 초반에 낚여서 PR 날릴 뻔 했네,, 진짜 사람 미치게 만드는구만
- 발음 게임 채점이 제대로 안 됐던 거였다..! 휴우 내 잘못 아니라서 다행이다(?)

### 게임 종료됐는데, startRecording이 계속된다?

```tsx
// 턴 데이터 변경 시 게임 초기화
useEffect(() => {
if (!turnData && !resultData) return;
// 순위 데이터가 있으면 종료시켜야 했는데..!
if (rank.length > 0) return;

...
}, [turnData, currentRoom, currentPlayer]);
```

### react-router-dom 경고

정체: React Router v7에서 상대 경로의 해석 방식이 변경될 예정이고, 이를 사전에 알려주는 경고 메시지

```
react-router-dom.js?v=ceca9ee8:4374 ⚠️ React Router Future Flag Warning: Relative route resolution within Splat routes is changing in v7. You can use the v7_relativeSplatPath future flag to opt-in early. For more information, see https://reactrouter.com/v6/upgrading/future#v7_relativesplatpath.
```

```
react-router-dom.js?v=ceca9ee8:4374 ⚠️ React Router Future Flag Warning: React Router will begin wrapping state updates in React.startTransition in v7. You can use the v7_startTransition future flag to opt-in early. For more information, see https://reactrouter.com/v6/upgrading/future#v7_starttransition.
```

최신 버전으로 업데이트하니까 경고 사라졌음

```bash
npm install react@latest react-dom@latest
```

업데이트하고 나서 라우팅 문제 생겨서 다운그레이드함.. 방 나가기 시 나가기 처리가 제대로 안 됨
어떻게 해야 하는지 모르겠다ㅜㅜ

### VolumeBar 스피커 버튼을 토글하여 볼륨 0 ↔ 50으로 조절할 수 있도록 함

- 진성님이 피드백 주신 부분 반영

### 키보드 Enter로도 동작하도록 함

- Dialog에서 항상 마우스로 Input 필드를 눌러 입력하고, 확인 버튼을 클릭해야만 하는 게 불편했다.
- 그래서 다음과 같은 것들이 가능하도록 했다.
- Dialog Open 시 첫 Input 필드에 포커싱
- Input 필드가 여러 개인 경우 Enter로 다음 Input 필드 이동
- Enter로 Submit(확인 버튼 클릭과 동일한 동작)
- shadcn/ui Dialog 컴포넌트는 ESC 키를 눌렀을 때 Dialog Close를 해줘서 이건 따로 처리가 필요 없었다.
- SearchBar(방 검색)에도 적용할 생각!

### 게임 진행 테스트 도중 버그 발견

- 본인 마이크 버튼을 음소거하면 setMute 이벤트를 보내고 updateUsers를 수신해 players 상태를 변경한다.
- 게임 진행 중에 이 마이크 버튼을 음소거하면 각 player의 isMuted 상태가 바뀌고, 이는 currentRoom의 상태를 바꿔 리렌더링 되면서 voice recording이 되지 않는다. (게임방을 나갔을 경우에도 동일, 이 부분은 나중에 해결하기로)
- PlayScreen의 useEffect 의존성 배열에 currentRoom이 있어서 그런 것 같다.
- 그래서 일단 각 player에서 isMuted를 없애고, setMute 시 updateUsers가 아닌 muteStatusChanged 이벤트를 수신해 muteStatus: {닉네임: false/true, ...} 데이터를 받아온다.
- Player 컴포넌트 내부에 isMuted 초기 상태를 정해주고, muteStatus 데이터 상태가 변경되었을 때 isMuted를 변경해 주는 방식으로 바꿨다.
- 이렇게 해서 Player 컴포넌트와 GameScreen 컴포넌트를 독립적으로 리렌더링 해줄 수 있게 됐다.
- 문제: muteStatus의 initial state를 null로 설정하니까 처음에 가져올 때 에러 발생해서 빈 객체로 초기화
### 채점 중에서 게임 페이즈가 넘어가지 않는 문제

- 음소거 버튼 문제처럼 userUpdates로 상태가 변경되면 채점 중에서 넘어가지 않는다.
- 턴이 바뀌고 해당 차례의 사용자의 음성 정보를 넘겨줄 때 roomId가 필요한데 currentRoom의 roomId를 전달하고 있어서, updateUsers로 currentRoom이 변경되면 이 문제가 일어날 수 있다.
- 그래서 currentRoom에서 가져오지 않고, useParams로 가져와서 전달해 주니까 채점 중에서 넘어가지 않는 문제는 없어진 것 같다. (아직 모름..)
- 그런데 이렇게 처리하니까 게임 중일 때 또 다른 문제가 생겼다.
- 자기 차례일 때 새로고침 시: 재입장 처리 돼서 순위에 2번 반영되고, 게임 준비 & 시작하면 이전 게임의 결과가 나와 버린다. (result가 초기화 되지 않음)
- 다른 사람 차례일 때 새로고침 시: 순위에 2번 반영되지는 않지만, 역시나 게임 준비 & 시작하면 이전 게임의 결과가 나온다. (result가 초기화 되지 않음)
- 새로고침 해서 준비 화면에 있는 상태에서 새로고침을 한 번 더 하면 정상 동작한다.
- 새로고침 할 때 방 나가기 처리를 해야할 것 같은데.. 잘 모르겠다.. ㅜ 일단 채점 중에서 멈춰있지는 않는 것 같다.

### ExitDialog 새로고침 후 뒤로가기 하면 취소 버튼에 포커싱

- KickDialog도 똑같이 shadcn/ui AlertDialog 컴포넌트를 쓰고 있는데, 강퇴 시에는 아무리 새로고침을 해도 취소 버튼에 포커싱되면서 아웃라인이 생기지 않음
- 왜 방 나가기 Dialog만, 그것도 새로고침을 하고 나면 그러는 거지?
- 나가기 버튼으로 나갈 때는 문제 없고 새로고침 후 뒤로가기 하면 그러는 것 같다. 뒤로가기 이벤트가 뭔가 영향을 주는 건가? 아무튼 AlertDialog 컴포넌트 자체에 처리

```jsx
<AlertDialogPrimitive.Cancel
ref={ref}
className={cn(
buttonVariants({ variant: 'outline' }), // outline 자체를 없애면 버튼 색상이 바뀜
'mt-2 sm:mt-0',
'focus:outline-none focus-visible:ring-0', // 포커스 스타일 제거
className
)}
{...props}
/>
```

### 새로고침 지옥에서 꺼내줘

- 개발 시작 단계부터 날 괴롭게 했던 새로고침.. 재입장 처리로 어떻게 넘어갔었는데, 게임 중일 때는 막아야 함
- 키보드 동작은 막을 수 있는데 브라우저 새로고침 버튼 클릭은 막을 수 없음. Alert 띄우는 게 최선인데 이 Alert도 메시지 수정 불가.
- 채점 중에서 안 넘어가는 문제가 해결되지 않았다.
- 계속 테스트해 보는데 음성 데이터 전달 중에 새로고침 하면 채점이 안 되고 결과를 못 받아와서 그런 것 같다.
- `beforeunload` 이벤트의 브라우저 기본 alert보다 먼저 혹은 동시에 CustomAlertDialog을 띄우는 것은 불가능함
- 강퇴처럼 방 목록 페이지에 왔을 때 알림을 띄우기로 함
- 이게 왜 잘 안되는 건지 모르겠다.. 강퇴랑 별다를 게 없는 거 같은데..🤯 나중에 고쳐보는 걸로
- 페이지가 새로고침되면서 상태가 초기화되기 때문에 알림이 표시되지 않음. 강퇴 알림처럼 sessionStorage에 저장하고 가져와야 함

### 화요일 데일리스크럼 이슈 공유: 대기 중인 방에 링크로 입장 시 닉네임 설정 전에 마이크 권한 요청 및 오디오 연결되는 문제

- 방 목록 페이지에서 게임 방 클릭 시에는 제대로 동작하는데, 링크 입장 시에는 음성이 먼저 연결된다는 이슈를 전달받음
- 원인
- 링크 입장 시 GamePage index.tsx의 useReconnect로 소켓 연결, 닉네임 설정, 유효성 검증, 각 서버에 join된다. (방 목록 페이지에서의 입장은 handleJoin)
- 방 목록 페이지에서 게임 방 클릭 시에는 잘 동작한다는 말이 힌트가 되어줬다.
- useReconnect에서 순서가 JoinDialog의 handleJoin의 순서와 달랐기 때문이다. 유효성 검증이 추가되고 gameSocket의 joinRoom도 비동기 함수로 바꾸고 했는데 useReconnect 훅에서 순서를 바꿔준다는 걸 잊어버렸다.
- 해결
- useReconnect에서 각 함수 호출 순서를 handleJoin과 동일하게 맞춰서 해결..!
- gameSocket.joinRoom에서 유효성 검증에 대한 에러를 발생시키고 있기 때문에 순서를 잘 생각해야 한다. 게임 중 새로고침, 게임 중인 방 링크 입장할 때는 입장 불가 알림 처리도 해야 했기 때문에 머리가 터져버리는 줄 알았다. 오죽했으면 손으로 써가면서 체크함,,😇
8 changes: 7 additions & 1 deletion fe/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<link rel="icon" type="image/png" href="https://i.imgur.com/QphCmeT.png" />
<link
rel="stylesheet"
as="style"
crossorigin
href="https://cdn.jsdelivr.net/gh/orioncactus/[email protected]/dist/web/static/pretendard.min.css"
/>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Clovapatra</title>
</head>
Expand Down
1 change: 0 additions & 1 deletion fe/public/vite.svg

This file was deleted.

4 changes: 3 additions & 1 deletion fe/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import RoomListPage from './pages/RoomListPage';
import { ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import LandingPage from './pages/LandingPage';

const queryClient = new QueryClient();

Expand All @@ -14,7 +15,8 @@ function App() {
<div className="app">
<BrowserRouter>
<Routes>
<Route path="/" element={<RoomListPage />} />
<Route path="/" element={<LandingPage />} />
<Route path="/rooms" element={<RoomListPage />} />
<Route path="/game/:roomId" element={<GamePage />} />
</Routes>
</BrowserRouter>
Expand Down
Binary file removed fe/src/assets/images/angry-pepe.png
Binary file not shown.
1 change: 0 additions & 1 deletion fe/src/assets/lottie/404.json

This file was deleted.

1 change: 0 additions & 1 deletion fe/src/assets/react.svg

This file was deleted.

7 changes: 6 additions & 1 deletion fe/src/components/common/CustomAlertDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ interface CustomAlertDialogProps {
title: string;
description?: string;
actionText?: string;
handleClick?: () => void;
}

const CustomAlertDialog = ({
Expand All @@ -22,6 +23,7 @@ const CustomAlertDialog = ({
title,
description,
actionText = '확인',
handleClick,
}: CustomAlertDialogProps) => {
return (
<AlertDialog open={open} onOpenChange={onOpenChange}>
Expand All @@ -33,7 +35,10 @@ const CustomAlertDialog = ({
)}
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogAction className="bg-primary hover:bg-primary/90">
<AlertDialogAction
className="bg-primary hover:bg-primary/90"
onClick={handleClick}
>
{actionText}
</AlertDialogAction>
</AlertDialogFooter>
Expand Down
30 changes: 0 additions & 30 deletions fe/src/components/common/NotFound.tsx

This file was deleted.

Loading

0 comments on commit 69d8570

Please sign in to comment.