Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

토이프로젝트2 4조 MAFIA 게임 #11

Open
wants to merge 185 commits into
base: main
Choose a base branch
from
Open

Conversation

noSPkeepgoing
Copy link

@noSPkeepgoing noSPkeepgoing commented Nov 18, 2023

Mafia

  • 🗓 기간: 2023.11.06 ~ 2023.11.16
  • Socket.io의 양방향 통신을 활용한 채팅게임

Overview

KakaoTalk_Video_2023-11-18-22-53-54.mp4

💾 데스크탑 앱 포맷팅

image

💿 Win x64 게임 파일 설치 링크
💿 Mac 게임 파일 설치 링크

❗ win x64버전과 mac 버전이 따로 구분되어 있습니다. os에 맞는 파일을 실행하셔야 정상적으로 작동합니다.

🔍️ <주요 기능>

  • 존재하는 모든 게임 방들의 정보를 받아 페이지에 렌더링
  • 특정 게임방에 접속 시 제공받은 api와 추가 배포한 서버 api를 활용해 게임에 필요한 데이터를 요청 및 저장
  • Socket 연결을 통한 게임 참가자들끼리의 채팅
  • 추가 서버 api를 활용한 투표 시스템
  • 투표 결과를 바탕으로 서버 데이터를 수정하고 결과를 화면에 렌더링

👭 참여 인원 및 담당 기능

팀장 | 최선파 팀원 | 남궁종민 팀원 | 정진주 팀원 | 김소정
@noSPkeepgoing @NamgungJongMin @jinjoo-jung @KSJT
  • 초기 개발 환경 세팅
  • 게임 투표 기능
  • 게임 진행 사항 및 결과 페이지
  • 추가api 작성 및 서버 호스팅
  • 로비 페이지
  • 랜덤 역할 부여 기능
  • 일렉트론 개발환경 세팅 및 데스크탑 앱 포맷팅
  • Socket 연결 및 통신
  • 게임 채팅 기능
  • 채팅방 페이지
  • JWT 토큰 발급
  • 회원가입 및 로그인 기능
  • Redux toolkit 활용한 상태 관리

🔍️ 기술 스택 및 라이브러리

🧨선택 이유

  • React

    우리가 만들려는 게임의 특성 상 단일 앱으로의 특성을 가지고 있기 때문에 SPA형태가 유저 경험을 향상시킬 수 있을 것이라 생각 했고, SPA 단점인 SEO의 단점에 있어서도 페이지 별 웹 노출도가 필요 없을 것이라고 생각해서 React를 적용했다.

  • Typescript

    패스트캠퍼스에서 제공해주는 API의 응답 데이터들에 대한 스키마가 정해져있고, 불러올 데이터들의 타입을 내가 임의로 설정할 수 없게 하고, 그로 인해 오류의 가능성을 낮추기 위해 프로젝트에 타입스크립트를 적용했다.

  • Scss Module

    CSS-in-JS는 스타일의 직렬화 과정에서 추가 CPU 리소스를 소모하기 때문에 성능에 영향을 준다는 점, 번들 크기를 늘린다는 점, css 프로퍼티를 사용하는 각 요소에 대해 Emotion의 내부 컴포넌트가 React DevTools를 어지럽힌다는 점을 근거로 CSS-in-JS의 이점을 유지하면서 성능적으로는 일반 CSS와 유사한 ‘styling system’을 고민하게 되었다.

    CSS-in-JS의 이점인 지역 스코프, 배치의 자율성을 그대로 가져가면서 성능의 이점을 최대화한 시스템은 css module이었다. 그러나 코드 중복을 줄이는 등의 확장 기능의 부족으로 인해 Sass Module을 선택하게 되었다.

    Sass Module은 기본적으로 런타임 비용 없이 지역 스코프의 CSS Module 스타일과 Sass의 빌드 시간 장점을 누릴 수 있다. 뿐만 아니라 중첩 규칙과 Mixin, 간편한 상수 선언과 사용을 통해 효율적인 개발 환경을 구성할 수 있다고 생각했다.

  • Vite

    React 프로젝트의 대표적 생성 방식인 CRA와 비교하여 모듈 사이즈가 작고 커스텀 빌드가 쉽다는 것이 선택에 이유가 되었다. 우리 프로젝트의 경우 Electron을 적용하여 빌드를 하기 때문에 세팅이 쉬워야 했고, 모듈 사이즈의 축소는 데스크탑 앱 빌드 과정을 빠르게 해준다고 생각했다. 추가로 기존 CRA와 비교하여 src 데이터들 자체의 빌드 또한 매우 빠르다는 것이 선택의 이유였다.

  • Electron

    페이지 이동을 통해 게임의 이벤트들과 결과들을 출력하는 우리 프로젝트의 특성 상 새로고침이나 뒤로가기 등의 유저의 예상치 못한 행동들을 막는 것에 데스크탑 앱으로 빌드하는 것이 장점이 있다고 생각했다. 뿐만아니라 게임의 특성 상 정보 페이지가 아니라 하나의 단일 어플리케이션으로써 기능하기 때문에 데스크탑 앱으로 접근하는 것이 유저 경험에 도움이 될 것이라고 생각했다.

  • GitHub

    프로젝트의 버전 관리를 위해 선택하게 되었다. 접근성도 좋고, 이슈발생, pr생성 등 문서화에 용이하기 때문에 선택하게 되었다.

  • Gitflow

    깃 브랜치 충돌을 최소화하고, 브랜치 분기를 강제하여 메인 브랜치에서 일어날 수 있는 혹시 모를 이슈에 기민하게 대응할 수 있도록 했다.

  • PocketHost

    기존 제공받은 api만으로는 게임을 구현하는데 있어서 필요한 데이터들을 온전히 처리할 수가 없었다. 따라서 noSQL 구조로 새로운 데이터들을 담을 공간으로 추가적인 api를 배포하고 사용함으로써 추가적인 데이터를 주고 받으며 프로젝트를 진행할 수 있었다.

  • Redux/Toolkit

    리덕스를 사용하다 보면 여러 라이브러리들을 설치하게 된다. 하지만 Redux-Toolkit에는 이런 많은 라이브러리들이 내장되어 있어서 많은 라이브러리들의 의존성을 줄일 수 있어서 적용했다.

  • Socket.io

    모든 브라우저에서 동일한 기술을 적용하기 위해 사용하게 되었다. 또한 백엔드와의 원활한 통신을 위해 적용하였다.

    client가 요청을 보내고 server가 응답하면 연결이 바로 종료되는 기존 Rest API와는 달리 port로 실시간 양방향 통신을 하고 계속 연결을 유지하는 연결 지향형 통신이기에 Socket.io를 이용하였다.

🎨 프로토타입 디자인

image

📄 페이지 별 디자인 및 주요 기능

로그인

image

회원가입

image

image

로비

image

대기실

image

역할 부여

image

채팅

image

마피아 투표

image

투표 결과

image

게임 결과

image

😭 보완할 점

  1. 소켓으로 더 다양한 데이터를 양방향 통신

    • 주어진 api만으로는 기존 구상했던 계획의 다양한 특수직업의 설정과 그 투표들을 바로 반영할 수가 없었다. 멘토님의 조언 중 제공된 api로 string을 속여 넘기는 방식을 말씀해주셨는데 권장되는 방식은 아니라고 하셨다. nodeJS를 공부하여 웹서버를 직접 작성하고, 소켓을 연결하여 기획을 완전하게 구현한 앱을 다시 만들어봐야겠다.
  2. api 통신을 하는 코드들이 사람들마다 제각각이다. 리팩토링 때 api 폴더 내에 객체 안에 정리하는 방식으로 깔끔하게 저장하고, 같은 방식으로 모두가 사용함으로써 코드 스타일을 맞춰야겠다.

  3. 추가 noSQL api와 제공받은 api를 통해 같은 로직에 들어갈 통신들을 이용하게 되면서 어느 한쪽이 안되더라도 다른 한쪽이 되면 사이드 이펙트가 일어났다. 리팩토링시 수정해야한다.

noSPkeepgoing and others added 30 commits November 8, 2023 15:59
Set each method
- get
- post
- patch
- delete
Generalize styles for each browser
✨Feat: add pocketRequest.ts in api
게임 내 헤더, 투표페이지 생성
Add scss for header styling
- theme colors in variables
- lobby header styles
- user image in header
Create ChatPage
Add optional parameter 'id' in post method
Markup & Styling
Add assets
Move components to components folder
Add modal for creat rooms
Fix error way to import absolute path
- tsconfig.json
- vite.config.json
Copy link
Member

@iamidlek iamidlek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4조 분들 구현 하시느라 고생하셨습니다!

한정된 api로 마피아 게임을 생각하시고 구현하시고
피그마로 어떤 플로우로 진행될지 구상을 하시고 작업에 들어가서 좋았습니다.
폴더 구조나 전체적인 구성을 잘 해주신 것 같습니다. 일렉트론을 적용해 보신 것도 인상 깊네요.

다만 비동기 처리에 있어서 예외 처리가 미흡한 부분이 있고
그렇다 보니 실제 동작 시에 버그가 있을 것 같습니다.
(코드에서 발견되는 중복되는 부분은 코멘트 한 번 남기고 생략하였습니다.)

비동기 요청의 경우 하나의 try catch 스코프 안에서 두 가지 요청이 있다 보니
처음 요청이 성공하고 두번째 요청이 실패하는 케이스에 대한 대처가 되지 않을 것 같습니다. api 요청에 관한 부분을 잘 나누어서 작성해 주셨는데 type 지정이 되어 있지 않아서 아쉬웠습니다. 패키지에 axios를 install 하시고 사용하지 않으신 이유가 있으신가요?
모든 처리를 useEffect로 하신 점 등이 아쉬운 것 같습니다.
useMemo 등 computed 된 값을 이용하는 방법도 고려되면 좋을 것 같습니다.

지금 프로젝트 리펙토링 혹은 다음 프로젝트 등 에서
예외 처리 관련하여 더욱 신경을 써주시면 좋을 것 같고
더 클린한 코드 컨벤션을 유지하시면서 작성하시면 좋을 것 같습니다.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

빈 파일은 제거하는 것이 좋을 것 같습니다.

import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import { store } from '@store/index';
import App from './App';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

다른 부분과 동일하게 절대 경로 사용으로 맞추는 것이 좋을 것 같습니다.

Comment on lines +21 to +24
const response = await fastRequest.searchUserInfo(
userId,
localStorage.getItem('access_token') as string,
);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

access_token이 localStorage에 없으면 요청을 보내지 않는 것이
더 좋을 것 같습니다.

localStorage.getItem('access_token')

Comment on lines +35 to +37
const result = await login(id, password);
const { accessToken, refreshToken } = result;
const user = await getSelfInfo(id);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

login 요청이 실패해도 getSelfInfo 가 실행되는 것은
좋지 않은 것 같습니다.
login 요청이 성공한 경우에 실행되는 것이 맞을 것 같습니다.

const [isModalOpen, setIsModalOpen] = useState(false);
const character = useAppSelector((state) => state.selectedGhost);

const register = async (event: React.MouseEvent<HTMLButtonElement>) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

register 쪽도 입력된 데이터에 따라 validation 순서 및 중복 체크 등
회원 가입 로직 순서 변경과 처리하는 내용이 분리되어야 할 필요가 있어 보입니다.

@@ -0,0 +1,7 @@
import '@styles/components/button.module.scss';

const Button = () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

사용되지 않는 파일인 것 같습니다.

Comment on lines +52 to +55
const response = await fetch(
`https://full-oil.pockethost.io/api/collections/ghosts/records`,
{ cache: 'no-store' },
);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분만 api로 빠져있지 않은 것 같습니다.

<GhostItem
key={ghost.id}
ghost={ghost}
isSelected={isSelected === ghost.id ? true : false}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isSelected === ghost.id 의 결과 반환 되는 값이 boolean 입니다.
삼항 연산자를 사용하지 않아도 됩니다.

return res.json();
};

const fastRequest = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

모든 응답 값의 type이 지정되어 있지 않습니다.
응답을 받은 곳에서 응답 값을 추론하여 사용하기 어려울 것 같습니다.

* See https://playwright.dev/docs/test-configuration.
*/
const config: PlaywrightTestConfig = {
testDir: "./e2e",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

테스트 작성된 파일이 없는 것 같습니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants