JavaSpring BootWebSocketMySQLReactPhaser.js

굴 안의 너굴이

실시간 온라인 멀티플레이 숨바꼭질 게임. 플레이어는 찾는 팀과 숨는 팀으로 나뉘어 제한된 공간에서 술래잡기를 즐길 수 있으며, 다양한 아이템을 활용하여 다이나믹한 숨바꼭질을 즐길 수 있습니다.

굴 안의 너굴이

프로젝트 개요

학교 컴퓨터실 수업 중 쉬는 시간에 친구들과 함께 즐기던 플래시 게임의 추억을 현대적으로 재현한 실시간 멀티플레이어 게임입니다.

이 프로젝트는 단순한 게임 구현을 넘어서, 300명 이상의 동시 접속자를 안정적으로 처리하는 서버 아키텍처 설계와 실시간 동기화를 위한 WebSocket 기반 통신 시스템을 구축하는 데 초점을 맞췄습니다. 특히 Server-Authority 모델을 도입하여 치팅 방지와 게임 상태 일관성을 보장하고, 이벤트 기반 브로드캐스팅을 통해 네트워크 효율성을 극대화했습니다.

백엔드 개발자로서 실시간 멀티플레이어 환경에서의 동시성 제어, 토큰 기반 인증 시스템, 상태 머신을 활용한 게임 라이프사이클 관리 등 서버 사이드 핵심 기술들을 실제로 구현하고 최적화할 수 있었던 소중한 경험이었습니다.

나의 역할

  • Server-authority 모델 도입으로 한 게임을 같이 즐기는 클라이언트들의 요청을 서버에서 통제하여 일관된 환경 유지

  • 게임 진행 라이프 사이클 구현 (게임 시작, 진행, 종료 관리)

  • WebSocket을 활용한 실시간 멀티플레이어 동기화

  • 아이템 효과 시스템 구현: 아이템 효과 로직, 적용 메커니즘, 지속 시간 관리, 우선순위 알고리즘 개발

  • 인증/인가 시스템 구현

  • 전적 집계 및 통계 시스템 개발

  • 맵 축소 전략 및 게임 밸런스 로직 개발

  • Selenium을 활용한 자동 QA 테스트 구현 (Web 기반 게임의 기능 및 성능 검증)

기술적 도전과제

높은 동시 접속자 처리

ConcurrentQueue를 활용한 비동기 요청 처리 시스템을 구축하고, 스레드 풀을 통해 CPU 자원을 최적화했습니다. 게임 로직과 네트워크 I/O를 분리하여 병목 현상을 해소하고 성능을 향상시켰습니다.

게임 상태 일관성 유지

Server-authority 모델을 도입하여 모든 게임 로직을 서버에서 처리하고, 클라이언트는 단순히 입력만 전송하도록 설계했습니다. 이를 통해 클라이언트 조작을 방지하고 모든 플레이어에게 동일한 게임 상태를 보장했습니다.

실시간 동기화 지연 및 네트워크 부하 최소화

게임 상태 변경 시 필요한 플레이어에게만 선택적 브로드캐스트하도록 최적화했습니다. 프레임 기반 업데이트 대신 이벤트 기반 업데이트를 채택하여 네트워크 트래픽을 대폭 감소시키고 지연 시간을 단축했습니다.

아이템 효과 우선순위 및 충돌 처리

여러 아이템 효과가 동시에 적용될 때의 우선순위 알고리즘을 설계했습니다. 아이템 효과 스택 관리, 지속 시간 추적, 효과 적용 순서를 정의하여 일관된 게임 밸런스를 유지했습니다. 동시 발동 시 우선순위에 따라 효과를 적용하고, 중복 효과는 효율적으로 병합하도록 구현했습니다.

Web 기반 게임의 QA 효율화

Web 기반 게임의 특성을 활용하여 Selenium을 통한 자동화 테스트를 구현했습니다. 게임 플로우, 로그인/로그아웃, 게임 생성/참여 등 주요 기능에 대한 E2E 테스트를 자동화하여 수동 테스트 시간을 대폭 단축하고 배포 전 품질을 보장했습니다.

프로젝트 성과

50ms

Locust 부하 테스트: 동시 접속자 1000명 시나리오에서 게임 상태 동기화 API p95 Latency 50ms 달성

300명+

실제 동시 접속자 300명 이상 유치

99.9%

서버 안정성 99.9% 달성, 치팅 방지를 위한 Server-Authority 아키텍처 구현

기술 선택 이유

Spring Boot

엔터프라이즈급 웹 애플리케이션 개발을 위한 검증된 프레임워크로, REST API와 WebSocket/STOMP 지원이 뛰어나며 풍부한 생태계와 안정성을 제공합니다. 특히 Spring Security를 통한 인증/인가 시스템 구현과 스레드 풀 관리 등 동시성 제어에 필요한 기능들을 효율적으로 활용할 수 있습니다.

WebSocket + STOMP

실시간 양방향 통신이 필수적인 멀티플레이어 게임에서, WebSocket은 낮은 지연시간과 지속적인 연결을 제공합니다. STOMP 프로토콜을 활용하여 토픽 기반 발행-구독 패턴을 구현하고, Room/Game/Player/Team 단위로 세분화된 메시지 브로드캐스팅을 가능하게 했습니다. 토큰 기반 인증을 STOMP 헤더에 적용하여 보안성을 확보했습니다.

MySQL

관계형 데이터베이스로 사용자 정보, 방 정보, 전적 데이터 등 구조화된 데이터를 안정적으로 저장하고 관리합니다. 트랜잭션 지원을 통해 데이터 일관성을 보장하며, 인덱싱을 활용한 빠른 조회 성능을 제공합니다.

Java (ConcurrentQueue, Thread Pool)

Java의 동시성 컬렉션과 Executor 프레임워크를 활용하여 멀티스레드 환경에서 안전하고 효율적인 비동기 요청 처리를 구현했습니다. ConcurrentQueue를 통해 스레드 안전한 작업 큐를 구축하고, Thread Pool을 통해 CPU 자원을 최적화하여 높은 동시성을 달성했습니다.

Phaser.js

브라우저 기반 게임 개발에 특화된 JavaScript 프레임워크로, 렌더링, 물리 엔진, 입력 처리 등의 복잡한 게임 로직을 간소화합니다. 친근한 도트 그래픽 스타일을 제공하며, WebSocket과 연동하여 서버의 게임 상태를 실시간으로 시각화할 수 있습니다.

시스템 아키텍처

클라이언트-서버 상호작용 아키텍처

클라이언트-서버 상호작용 아키텍처

방 참가부터 게임 시작까지의 클라이언트-서버 통신 플로우: HTTP를 통한 초기 인증 및 토큰 발급, STOMP over WebSocket을 통한 실시간 게임 상태 동기화

게임 플로우 아키텍처

게임 플로우 아키텍처

게임의 전체 플로우: 방 생성 및 입장, 레디 상태 관리, 게임 시작 및 진행(숨기/찾기), 승패 판정까지의 게임 라이프사이클

KPT 회고

Keep

Server-Authority 모델을 통한 중앙 집중식 게임 로직 관리로 여러 클라이언트가 동시에 요청해도 일관된 게임 상태를 유지할 수 있었습니다. 이벤트 기반 브로드캐스팅과 선택적 메시지 전송을 통해 네트워크 부하를 최소화하고 p95 Latency 50ms를 달성했습니다.

랜덤성 알고리즘, 상태 머신, 토큰 기반 인증, 비동기 처리 등 다양한 기술을 한 프로젝트 안에서 실제로 구현해볼 수 있어서 값진 학습 경험이었습니다.

Problem

기술적 구현과 성능 최적화에 집중하는 과정에서 게임 플레이 메커니즘의 독창성이나 사용자 경험의 차별화에 대한 고민이 부족했습니다.

게임의 핵심 재미 요소와 차별화 포인트를 초기에 명확히 정의하지 못했고, 프로젝트 초반부터 사용자 테스트와 피드백을 수집하는 프로세스가 부재했습니다.

Try

게임 기획 단계에서 '왜 이 게임이 재미있을까?'라는 질문을 던지고, 경쟁사 분석과 게임플레이 루프 설계에 더 많은 시간을 투자하겠습니다.

기술 스택 선택 전에 게임의 핵심 재미 요소를 먼저 정의하고, 그에 맞는 최적의 기술을 선택하는 '게임플레이 중심 개발 방법론'을 적용해보고 싶습니다.

프로토타입 단계에서부터 지인들과 함께 플레이테스트를 진행하고, '재미'를 정량적으로 측정할 수 있는 지표를 도입하여 지속적으로 개선하는 사이클을 만들겠습니다.

프로젝트 정보

프로젝트 출처
삼성 청년 SW 아카데미 11기 공통 프로젝트
기간
2024.07 - 2024.08
팀 규모
3FE 2BE
담당 역할
Backend Developer

기술 스택

JavaSpring BootWebSocketMySQLReactPhaser.js

스크린샷

메인

메인

로그인 화면

로그인 화면

방 생성

방 생성

선택 방 입장

선택 방 입장

랜덤 방 입장

랜덤 방 입장

아이템(방향버섯 : 숨은 플레이어의 방향을 알려준다.)

아이템(방향버섯 : 숨은 플레이어의 방향을 알려준다.)

아이템(바나나 : 5초간 이동속도가 감소함.)

아이템(바나나 : 5초간 이동속도가 감소함.)

아이템(벌통 : 벌통을 발견한 술래는 3초간 움직일 수 없다.)

아이템(벌통 : 벌통을 발견한 술래는 3초간 움직일 수 없다.)

아이템(독버섯 : 방향키를 반대로 바꾼다.)

아이템(독버섯 : 방향키를 반대로 바꾼다.)