ecole42

red_tetris

red_tetris

red_tetris는 ecole42의 프로젝트로, 풀스택 JavaScript로 구현된 멀티플레이어 테트리스 게임. 클라이언트는 함수형 프로그래밍 스타일(React), 서버는 객체지향 프로그래밍 스타일(Node.js, Express)로 구현해야하는 제한조건이 있다. Socket.IO를 활용한 실시간 멀티플레이어 게임, 페널티 시스템, 실시간 채팅, 방 시스템 등을 구현하며, 테스트 커버리지는 70% 이상을 달성해야한다

React
Express.js
Socket.IO
JavaScript

데모

라이브 데모

주의: 서버가 sleep 상태라서 로드되는데 시간이 걸린다.

개요

Red Tetris는 풀스택 JavaScript로 구현된 멀티플레이어 테트리스 게임으로, ecole42 커리큘럼의 일부다. 이 프로젝트는 JavaScript의 함수형 프로그래밍, 프로토타입 지향 설계, 동적 타입, 비동기 작업을 배우는데에 목적이 있다.

프로젝트 요구사항

  • 클라이언트 측: 함수형 프로그래밍 스타일로 작성되어야 한다
  • 서버 측: 객체지향 프로그래밍 스타일로 작성되어야 한다
  • 테스트 커버리지: 문장(statements), 함수(functions), 라인(lines)의 최소 70%, 분기(branches)의 최소 50%

주요 기능

  • 🎮 멀티플레이어 테트리스 - 최대 3명의 플레이어가 동시에 플레이 가능
  • 💬 실시간 채팅 - 게임 중 다른 플레이어와 소통
  • 🗺️ 다양한 맵 - 다양한 스테이지 구성 선택 가능
  • 페널티 시스템 - 여러 줄을 지워 상대방에게 페널티 전송
  • 🎯 방 시스템 - 게임 방 생성 및 참가
  • 🎵 사운드 효과 - 게임 액션에 대한 몰입감 있는 오디오 피드백
  • 📊 점수 추적 - 모든 플레이어의 실시간 점수 업데이트

기술 스택

프론트엔드

  • React (v17.0.1) - UI 프레임워크
  • React Router DOM (v5.2.0) - 클라이언트 사이드 라우팅
  • Styled Components (v5.2.0) - CSS-in-JS 스타일링
  • Semantic UI React (v2.0.0) - UI 컴포넌트 라이브러리
  • Socket.io Client (v2.3.1) - 실시간 통신

백엔드

  • Node.js - 런타임 환경
  • Express (v4.17.1) - 웹 프레임워크
  • Socket.io (v2.3.0) - WebSocket 서버
  • Lodash (v4.17.20) - 유틸리티 라이브러리

개발 도구

  • Webpack (v5.1.3) - 모듈 번들러
  • Babel - JavaScript 컴파일러
  • Jest (v26.6.1) - 테스팅 프레임워크
  • React Testing Library (v11.1.0) - 컴포넌트 테스팅
  • Nodemon (v2.0.6) - 개발 서버 자동 재시작

프로젝트 구조

red_tetris/
├── src/
│   ├── client/              # 프론트엔드 React 애플리케이션
│   │   ├── components/      # React 컴포넌트
│   │   │   ├── MyTetris.jsx      # 플레이어 자신의 게임 보드
│   │   │   ├── OthersTetris.jsx  # 다른 플레이어들의 게임 보드
│   │   │   ├── Chat.jsx          # 채팅 컴포넌트
│   │   │   ├── Room.jsx          # 메인 게임 방 컴포넌트
│   │   │   └── ...
│   │   ├── pages/          # 페이지 컴포넌트
│   │   │   ├── Home.jsx    # 랜딩 페이지 (방 생성)
│   │   │   └── Tetris.jsx  # 게임 페이지
│   │   ├── hooks/          # 커스텀 React 훅
│   │   │   ├── useSocketEvent.js
│   │   │   ├── useCheckRoom.js
│   │   │   └── useInterval.js
│   │   └── gameHelper.js   # 클라이언트 사이드 게임 유틸리티
│   │
│   └── server/              # 백엔드 Node.js 애플리케이션
│       ├── classes/         # OOP 클래스
│       │   ├── Game.js      # 게임 방 로직
│       │   ├── Player.js    # 플레이어 상태 및 액션
│       │   ├── Piece.js    # 테트리스 조각 정의
│       │   └── SocketManager.js  # Socket 이벤트 핸들러
│       ├── api.js           # REST API 라우트
│       ├── gameHelper.js    # 서버 사이드 게임 유틸리티
│       ├── ROOMS.js         # 방 저장소 (Map)
│       └── index.js         # 서버 진입점
│
├── test/                    # 테스트 파일
├── config/                  # Webpack 설정
└── public/                  # 정적 자산

설치

필수 요구사항

  • Node.js (v14 이상)
  • npm 또는 yarn

설정

# 저장소 클론
git clone https://github.com/woolimi/red_tetris.git
cd red_tetris

# 의존성 설치
npm install
# 또는
yarn install

사용 방법

개발 모드

핫 리로드가 가능한 개발 서버 실행:

# 개발 모드로 클라이언트 빌드
npm run dev:build

# 서버 시작 (nodemon 사용)
npm run server

# 다른 터미널에서 클라이언트 개발 서버 시작
npm run client

클라이언트는 http://localhost:8080에서, 서버는 http://localhost:5000에서 사용 가능

프로덕션 빌드

# 프로덕션용 빌드
npm run build

# 프로덕션 서버 시작
npm start

환경 변수

루트 디렉토리에 .env 파일 생성:

PORT=5000
DOMAIN=http://localhost:8080
MODE=dev  # 프로덕션의 경우 'prod'

게임 플레이 방법

  1. 방 생성/참가: 홈 페이지에서 방 이름과 사용자 이름 입력
  2. 플레이어 대기: 최대 3명의 플레이어가 방에 참가 가능
  3. 준비 완료: 준비되면 준비 버튼 클릭
  4. 게임 시작: 모든 플레이어가 준비되면 방장이 게임 시작 가능
  5. 플레이: 화살표 키로 조각 이동 및 회전
    • - 조각 회전
    • / - 좌우 이동
    • - 소프트 드롭
    • Space - 하드 드롭
  6. 승리: 마지막까지 살아남은 플레이어가 승리!

게임 규칙

  • 줄을 지워 점수 획득 (1줄: 10점, 2줄: 30점, 3줄: 60점, 4줄: 120점)
  • 2줄 이상을 지우면 다른 플레이어에게 페널티 전송 (쓰레기 줄 추가)
  • 마지막까지 남은 플레이어가 게임 승리

테스팅

커버리지와 함께 테스트 실행:

npm run coverage

테스트 커버리지 요구사항:

  • 문장(Statements): ≥70%
  • 함수(Functions): ≥70%
  • 라인(Lines): ≥70%
  • 분기(Branches): ≥50%

API 엔드포인트

REST API

  • POST /api/room - 방 생성 또는 입장 검증

    {
      "roomName": "string",
      "userName": "string"
    }
    
  • GET /api/room - 방 가용성 확인

    ?roomName=string&userName=string
    

Socket.io 이벤트

클라이언트 → 서버

  • ROOM:ADD_PLAYER - 방 참가
  • PLAYER:READY - 플레이어 준비 완료 표시
  • GAME:START - 게임 시작 (방장만 가능)
  • PLAYER:MOVE - 조각 좌우 이동
  • PLAYER:ROTATE - 조각 회전
  • PLAYER:DROPDOWN - 조각 아래로 떨어뜨리기
  • CHAT - 채팅 메시지 전송
  • GAME:CHANGE_MAP - 맵 변경 (방장만 가능)

서버 → 클라이언트

  • ROOM:PLAYERS - 플레이어 목록 업데이트
  • ROOM:OWNER - 방장 업데이트
  • GAME:START - 게임 시작됨
  • PLAYER:MOVE - 플레이어 이동
  • PLAYER:ROTATE - 플레이어 회전
  • PLAYER:DROPDOWN - 플레이어가 조각을 떨어뜨림
  • PLAYER:GAMEOVER - 플레이어 패배
  • GAME:FINISH - 게임 종료
  • CHAT - 채팅 메시지 수신

아키텍처

클라이언트 아키텍처 (함수형 프로그래밍)

  • 함수형 컴포넌트: 모든 React 컴포넌트는 훅을 사용하는 함수형 컴포넌트
  • 커스텀 훅: 재사용 가능한 로직을 커스텀 훅으로 추출
  • Context API: React Context를 사용한 상태 관리
  • 불변 업데이트: 상태 업데이트는 함수형 프로그래밍 원칙을 따름

서버 아키텍처 (객체지향 프로그래밍)

  • 클래스: Game, Player, Piece, SocketManager가 클래스로 구현됨
  • 캡슐화: private 메서드 및 속성
  • 상속: 게임 엔티티를 위한 클래스 기반 구조
  • 다형성: 메서드 오버라이딩 및 동적 디스패치