회고) DevineEcho 프로젝트 [2024.11.14 - 2025.03.03]

 



DevineEcho 프로젝트

 

 

 

 

👨‍🏫 프로젝트 요약

 

DevineEcho는 React + Pixi.js + Spring Boot + MySQL을 활용한 Vampire Survivor 스타일의 2D 웹 게임 프로젝트입니다.

 

프로젝트 설명은 Readme 참조

 

https://github.com/DevineEcho

 

DevineEcho

2D Web Game. DevineEcho has 3 repositories available. Follow their code on GitHub.

github.com

 

 

 

 

 

📃 프로젝트 구조(아키텍쳐)

DevineEcho Architecture

 

 

 

 

1️⃣ 프론트엔드 계층

①  App.js (React Router)

사용자 요청에 따라 URL 라우팅을 처리합니다. 예를 들어 /login, /game 등 페이지를 컴포넌트로 연결합니다.

②  pages/

화면 단위의 UI 페이지가 구성되어 있습니다. 로그인, 게임, 상점 등 다양한 기능이 이곳에서 표현됩니다.

③ Pixi.js (game/)

게임 엔진 역할을 담당하는 핵심 모듈로, HTML5 Canvas 기반 2D 그래픽 렌더링과 애니메이션 처리 등을 맡습니다.

Axios (api/)프론트엔드에서 발생한 사용자 액션은 Axios를 통해 백엔드 REST API로 전달됩니다.

 

2️⃣ 백엔드 계층

Controller

클라이언트의 요청을 수신하고, JWT 인증 필터를 통과한 사용자만 비즈니스 로직으로 전달합니다. 카카오 OAuth 연동도 이 계층에서 수행됩니다.

Service
실제 게임 결과 처리, 경험치 계산, DB 저장 및 Kafka 메시지 발행과 같은 비즈니스 로직을 수행합니다.

Repositor
Spring Data JPA 기반으로 엔티티와 데이터베이스 간의 연동을 처리합니다.

④ Model
유저, 게임 결과 등 도메인 중심의 엔티티들이 정의되어 있으며, MySQL DB와 매핑됩니다.

 

 

 

🎈 데이터 흐름도

 

①  데이터 입력

사용자는 React 기반의 프론트엔드를 통해 게임을 플레이하거나 로그인, 상점 이용, 스테이지 완료 등 다양한 행동을 수행합니다.
Pixi.js 기반 게임 엔진에서 발생한 이벤트나 버튼 클릭 등의 상호작용은 Axios를 통해 API 호출로 전달됩니다.

예를 들어, 게임 클리어 시 POST /api/stage/clear, 로그인 시 GET /api/auth/kakao/callback?code=xxx 형태로 백엔드에 요청을 보냅니다.

 

②  전처리

모든 요청은 Spring Boot 백엔드의 @RestController 계층에 도달하며, 요청에 포함된 JWT 토큰은 JwtAuthenticationFilter에서 먼저 인증 검사를 거칩니다. 토큰이 유효하면 사용자 정보가 SecurityContext에 등록되어 이후 로직에서 참조 가능하고, 카카오 로그인 요청인 경우엔 인증 코드(code)를 백엔드에서 직접 카카오 서버에 전달하여 사용자 식별 정보를 가져옵니다. 이후 Controller는 요청 파라미터를 파싱하고, 해당 요청을 적절한 서비스 계층으로 전달합니다.

 

③  부분처리

Controller를 통해 전달된 요청은 Service 계층에서 처리됩니다.
예로, 스테이지 클리어 요청은 PlayerService 또는 SkillService에서 유저의 상태를 업데이트하고, 경험치 및 보상을 계산합니다.

 

④  DB 처리 (DAO & MySQL)

비즈니스 로직이 완료된 후, 서비스 계층은 repository/ 디렉토리의 Spring Data JPA 레포지토리를 통해 MySQL 데이터베이스에 접근합니다. 해당 유저의 상태(Player), 보유 아이템(Item), 스킬(Skill) 등의 정보를 저장하거나 조회합니다.

DevineEcho에서는 모든 도메인 엔티티가 model/ 디렉토리에 정의되어 있으며, JPA를 통해 명확하게 테이블과 매핑됩니다.
데이터는 사용자 ID를 기준으로 저장되며, 스테이지 클리어, 레벨업, 상점 구매 등의 결과를 반영합니다.

 

 

 

 

 

 

 

🕵️‍♀️ 맡은 파트 (모두)

단독으로 기획부터 설계까지 진행한 1인 프로젝트입니다.

 

 

 

 

🤔 개발후기

 

🥇 WHY?

처음 이 게임을 기획하고 개발하려고 했을 때 가장 먼저 고민했던 것은 "어떤 기술 스택을 사용할 것인가?" 였습니다. 기술 스택의 선택은 개발 속도뿐만 아니라 유지보수성과 확장성에도 큰 영향을 미치는 요소이기 때문이었습니다.

백엔드에서는 Spring Boot를 선택했습니다. 기존에 사용해 본 경험이 있어 빠른 개발이 가능했고, Spring Security와 JWT를 활용한 인증 시스템을 구현하기에 적합했기 때문입니다. 또한, 데이터 일관성을 유지하고 관리하기 위해 JPA를 사용했으며, RESTful API 설계를 통해 프론트엔드와의 원활한 데이터 교환을 목표로 했습니다. 데이터베이스는 MySQL을 사용했습니다. 플레이어, 아이템, 스킬 간의 관계가 복잡하게 얽혀 있는 만큼 관계형 데이터베이스가 적절하다고 판단했습니다. Redis와 같은 NoSQL을 사용하지 않은 이유는, 휘발성 저장 방식이기 때문에 스테이지 클리어시 저장해야하는 중요한 데이터가 손실될 위험이 있었기 때문입니다.

프론트엔드는 React를 선택했습니다. React는 컴포넌트 기반의 구조로 UI를 재사용하기 쉽고, 상태 관리가 용이하여 게임과 같은 인터랙티브한 애플리케이션을 개발하기에 적합했습니다. 게임 개발 라이브러리로는 Pixi.js를 사용했습니다. Phaser.js와 비교했을 때, Pixi.js는 WebGL 기반으로 최적화가 잘 되어 있고, 불필요한 물리 엔진이나 씬 관리 기능이 없어 더 가볍고 유연한 개발이 가능했습니다. 특히 로그라이크 장르 특성상, 다수의 적과 스킬이 빠르게 화면에 등장하고 소멸하는데, Pixi.js의 고성능 렌더링이 이 요구 사항을 충족하는 데 유리했습니다.

 

🥈 SO ?

개발을 진행하면서 가장 크게 얻은 점은 프론트엔드와 백엔드의 흐름을 직접 설계하고 최적화하는 과정에서의 성장이었습니다. 1인 개발을 하면서 기획, 개발, UI 디자인, API 설계까지 전반적인 과정을 경험할 수 있었고, 단순히 기능을 구현하는 것이 아니라 “이 기능이 사용자의 경험을 어떻게 개선할 것인가?”를 고민하는 과정이었습니다. API 설계 시 프론트엔드가 원하는 데이터를 더 효율적으로 제공할 방법을 고민하며 데이터 흐름을 설계했고, 백엔드의 역할에 대한 이해도 더욱 깊어졌습니다. 앞으로는 OAuth 로그인 로직을 개선하여 로그인 유지 기능을 추가하고, 스킬 및 아이템을 다양화하여 더 많은 플레이 스타일을 지원하며, 현재 5개의 스테이지에서 이벤트 스테이지와 챌린지 모드를 추가하는 등 게임의 완성도를 더욱 높일 계획입니다. 또한, AWS 환경에서 CI/CD를 적용하여 지속적인 배포와 트래픽 관리까지 고려하는 단계로 확장할 것이며, 이를 통해 단순한 개발 경험을 넘어 실무적인 시스템 운영까지 경험해 보고자 합니다.

 

🥉 SERIOUS ?

물론 개발 과정에서 여러 어려움도 있었습니다. 가장 큰 문제 중 하나는 Kakao OAuth 로그인 구현 문제였습니다. API를 통해 카카오 회원 인증까지는 성공했으나, Local Storage에 토큰이 정상적으로 저장되지 않는 문제가 발생했습니다. 처음에는 CORS 문제인지, 인증 코드가 정상적으로 전달되지 않는 문제인지 원인을 찾기 어려웠습니다. 디버깅을 통해 API 응답을 분석하고, Spring Security에서 CORS 정책을 수정했으며, React의 useEffect() 타이밍을 조정하여 문제를 해결했습니다. 또한, window.history.replaceState()를 사용해 OAuth 인증 후 URL에서 인증 코드가 중복 요청되는 문제를 방지했습니다.

또한, 게임 데이터 저장 방식에서도 개선이 필요했습니다. 초기에 플레이어의 스킬 업그레이드와 경험치가 즉시 DB에 반영되지 않아, 스테이지 클리어 후 데이터가 올바르게 저장되지 않는 문제가 있었습니다. API 요청 구조가 불명확하여, 프론트엔드에서 데이터를 어떤 방식으로 저장해야 하는지 혼란이 발생하기도 했습니다. 이 문제를 해결하기 위해, 프론트엔드에서 메모리에 데이터를 저장하고, 스테이지 클리어 시 일괄적으로 DB에 반영하는 방식으로 변경했습니다. API 요청 구조를 개선하여 불필요한 데이터 전송을 줄이고, JSON 응답 구조를 명확히 정의하여 API 연동 문제를 해결했습니다.

프론트엔드에서도 UI 문제를 해결해야 했습니다. 상점 UI가 로드되지 않는 문제가 발생했는데, 다른 js와의 충돌 때문이었습니다. Pixi.js 컨테이너가 활성화된 상태에서 상점 UI가 렌더링되면서, 게임 화면이 덮어씌워지는 문제가 발생한 것입니다. 이를 해결하기 위해, 상점에 진입하면 Pixi 컨테이너를 display: none; 처리하고, 상점에서 나가면 다시 활성화하는 방식으로 UI를 개선했습니다. 또한, 아이템 데이터가 로드되기 전에 빈 화면이 표시되는 문제도 있었기 때문에, useEffect()를 활용해 로딩 상태를 추가하고, 아이템 데이터가 준비되었을 때만 UI를 렌더링하도록 수정했습니다.

 



 

 

 

🍙 가장 신경쓴 부분

 

이 프로젝트에서 가장 공을 들였던 백엔드 기능은 카카오 OAuth 로그인 연동 및 JWT 기반 인증 시스템 구축이었습니다.

 

요즘 대부분의 모바일/웹 게임은 "카카오로 시작하기", "카카오 계정으로 로그인" 같은 기능을 기본적으로 제공합니다.
복잡한 회원가입 없이, 전 국민이 사용하는 카카오 계정만으로 로그인할 수 있다는 점은 진입장벽을 낮추고 사용자 경험을 향상시키는 핵심 기능이라고 생각하였습니다.

 

저도 이러한 흐름을 반영하고자, 백엔드에서 카카오 OAuth와 직접 연동하여 로그인 시스템을 구현했고,
성공적으로 사용자 식별 → JWT 발급 → 인증 필터 → 보안 처리까지 인증 시스템 전반을 설계하고 구축했습니다.

 

DevineEcho 카카오 로그인 flowchart

 

 

JWT 토큰을 직접 발급하고 검증하는 로직을 통해 불필요한 세션 없이 인증 상태를 유지하는 방식을 도입하였고, Spring Security의 필터 체인을 커스터마이징하여 JwtAuthenticationFilter를 삽입함으로써 토큰 기반 인증 흐름을 완성했습니다. 이 과정에서는 JWT가 만료되었거나 유효하지 않은 경우를 고려한 예외 처리와 응답 메시지 정의도 직접 구성하여 보안적인 측면에서도 신경을 많이 썼습니다.

무엇보다도 실제 카카오 API 명세서를 참고하며, OAuth 인증 코드 기반으로 access_token을 발급받고, 이를 통해 사용자 정보를 조회하는 전체 흐름을 백엔드 로직으로 구현했습니다. 이후 사용자 정보를 기반으로 DB에 유저를 생성하거나 조회하고, 이를 통해 JWT를 생성한 뒤 프론트엔드로 전달하는 과정까지 모두 설계하고 연결했습니다. 이러한 경험을 통해 단순한 로그인 기능 구현을 넘어서, OAuth 인증과 JWT, 그리고 Spring Security 필터 체인을 활용한 전문적인 인증 시스템 구축 역량을 쌓을 수 있었으며, 이는 실제 서비스 백엔드에서 사용자 인증 흐름을 직접 책임질 수 있는 개발자로 성장하는 데 큰 밑거름이 되었다고 생각합니다.