Spring Boot 기반 서버 주도 geography game platform 포트폴리오입니다.
WorldMap은 하나의 웹사이트에서 아래 기능을 제공합니다.
- 국가 위치 찾기
- 수도 맞히기
- 국가 인구수 맞추기
- 인구 비교 퀵 배틀
- 국기 보고 나라 맞히기
- 설문 기반 국가 추천
- 실시간 랭킹과 공개
/stats - 회원 전적
/mypage - 운영용
/dashboard
핵심 차별점은 브라우저가 아니라 서버가 문제 생성, 정답 판정, 점수 계산, 진행 상태, 결과 공개 시점을 책임진다는 점입니다.
이 저장소는 단순 CRUD 포트폴리오가 아니라, 상태가 있는 서비스형 게임 백엔드를 설명하기 위한 프로젝트입니다.
- 게임 루프를
Session / Stage / Attempt로 나눈 서버 도메인 설계 - PostgreSQL source of truth + Redis leaderboard/session 전략
- Thymeleaf SSR + JSON API 혼합 구조
- guest 플레이에서 member ownership으로 이어지는 기록 귀속
- 런타임 LLM 없이도 설명 가능한 deterministic recommendation engine
test,browserSmokeTest,publicUrlSmokeTest로 나눈 검증 레일
| 영역 | 설명 |
|---|---|
| 위치 게임 | 3D 지구본 위 국가 선택, endless run, 하트 3개 |
| 수도 게임 | 4지선다 수도 맞히기 |
| 인구수 게임 | 4지선다 인구 규모 추정 |
| 인구 배틀 | 두 국가 중 인구가 더 많은 나라 선택 |
| 국기 게임 | 국기 이미지 보고 나라 맞히기 |
| 추천 | 20문항 설문 기반 상위 3개 국가 추천 |
| 랭킹 | 일간/전체 보드와 public /ranking |
| 공개 지표 | /stats에서 서비스 활동량과 daily top 3 제공 |
| 개인 기록 | /mypage에서 best run, recent play, mode performance 제공 |
| 운영 화면 | /dashboard에서 recommendation feedback과 baseline review 확인 |
flowchart LR
A["Browser<br/>SSR pages + JS interactions"] --> B["Spring Boot<br/>Controller -> Service -> Domain"]
B --> C["PostgreSQL<br/>countries, sessions, attempts,<br/>leaderboard_record, feedback"]
B --> D["Redis<br/>leaderboard read model,<br/>prod session store"]
책임 분리는 아래처럼 가져갑니다.
- 브라우저: 입력, 렌더링, 하이라이트, modal focus 같은 상호작용
- 서버: 세션 시작, Stage 진행, 정답 판정, 점수 계산, 결과 공개 조건
- PostgreSQL: 게임/추천/기록의 source of truth
- Redis: leaderboard read model과 production session backend
- 사용자가 게임 시작 페이지에 들어갑니다.
- 서버가
memberId또는guestSessionKey기준으로 새 게임 세션을 만듭니다. - 사용자가 답을 제출하면 서버가 정답 여부, 하트, 점수, 다음 Stage를 계산합니다.
- terminal 상태가 되면 leaderboard와 read model에 반영합니다.
- 결과는
GAME_OVER또는FINISHED가 된 뒤에만 열립니다.
- 사용자가
/recommendation/survey에 답합니다. - 서버가 deterministic scoring으로 상위 3개 국가를 계산합니다.
- 결과 페이지에서 explanation과 feedback token을 함께 제공합니다.
- 만족도 피드백은 이후 운영
/dashboardreview에 반영됩니다.
- terminal run이 생기면
leaderboard_record가 저장됩니다. - after-commit으로 Redis sorted set을 갱신합니다.
/ranking,/stats는 leaderboard read model을 읽고, Redis 장애 시 DB top record로 fallback합니다.
- Java 25
- Spring Boot 3.5.12
- Thymeleaf SSR
- Spring Data JPA
- PostgreSQL
- Redis
- Spring Session Data Redis
- JUnit 5 / Spring Boot Test
- Playwright browser smoke tests
- GitHub Actions verify lane
- ECS deploy preparation
- Java 25
- Docker Desktop 또는 Docker Engine
docker compose up -d
./gradlew bootRun --args='--spring.profiles.active=local'기본 진입 주소:
local 프로필에서는 PostgreSQL/Redis를 compose.yaml 기준으로 사용하고, demo bootstrap이 기본 활성화되어 바로 화면을 둘러볼 수 있습니다.
무료 static hosting 기준으로 분리 중인 demo-lite 별도 앱은 아래처럼 실행합니다.
cd demo-lite
npm install
npm run dev현재는 수도 맞히기, 국기 퀴즈, 인구 비교 배틀, 20문항 추천 결과, browser recent play summary, recent streak / 복사용 한 줄 요약까지 local-state 데모가 열려 있습니다.
현재 공개 URL:
-
#/ -
#/games/capital -
#/games/flag -
#/games/population-battle -
#/recommendation
주의:
- 현재 운영 URL은 Git-connected Cloudflare Pages 프로젝트
world-map-game-demo-lite-git입니다. - production branch는
main이고,main에 푸시되면 Pages가 자동으로 다시 빌드/배포합니다. - custom domain은 연결하지 않고 기본
pages.dev도메인을 그대로 사용합니다. - 이전
worldmap-demo-lite.pages.devdirect-upload 프로젝트는 비교/백업용 legacy 경로로만 남겨 둡니다.
공개 URL smoke:
cd demo-lite
npm run inspect:pages-git
npm run smoke:public -- https://world-map-game-demo-lite-git.pages.devGit-connected 운영 기준:
- demo-lite-verify.yml이
demo-lite변경마다npm test,npm run build,npm run verify:pages를 실행합니다. workflow_dispatch에서는 public URL을 직접 넣어npm run smoke:public까지 GitHub Actions에서 다시 돌릴 수 있습니다.- 로컬에서는
cd demo-lite && npm run inspect:pages-git으로 현재 운영 Pages 프로젝트의 Git provider, 현재 브랜치, working tree 상태를 바로 확인할 수 있습니다. - legacy direct-upload 프로젝트를 다시 점검하려면
DEMO_LITE_PAGES_PROJECT_NAME=worldmap-demo-lite npm run inspect:pages-git처럼 프로젝트명을 override하면 됩니다.
기본 회귀:
./gradlew test실제 브라우저 smoke:
./gradlew browserSmokeTest공개 URL smoke와 navigation timing:
WORLDMAP_PUBLIC_BASE_URL=https://<public-url> ./gradlew publicUrlSmokeTest현재 저장소에는 production runtime 계약과 Railway 단일 플랫폼 배포 준비, 그리고 free-tier용 demo-lite 별도 트랙 준비가 포함되어 있습니다.
application-prod.yml로 prod 전용 datasource / Redis / readiness 계약 분리verify.yml로test+browser-smoke검증 레일 분리- ECS task definition sample + render script + preflight script 제공
- Railway 런북과
demo-litescope / decomposition 문서 정리 demo-lite용 Cloudflare Pages 런북,.node-version,_headersbaseline 추가demo-lite용 public URL smoke 스크립트 추가demo-lite용 GitHub Actions verify lane 추가
현재 상태는 두 갈래입니다.
- full Spring Boot 앱: 공개 URL 미연결, 배포 준비와 검증 레일 정리 단계
demo-lite: https://world-map-game-demo-lite-git.pages.dev/ 에 Git-connected Pages 공개 URL이 열려 있고,main푸시 기준 자동 배포와npm run smoke:public반복 검증이 가능
배포 전 확인:
python3 scripts/check_prod_deploy_preflight.py --repo answndud/world_map_game빠르게 프로젝트를 이해하려면 아래 순서가 좋습니다.
- docs/DEPLOYMENT_RUNBOOK_AWS_ECS.md
- docs/DEPLOYMENT_RUNBOOK_RAILWAY.md
- docs/DEMO_LITE_SCOPE_PLAN.md
- docs/DEMO_LITE_DECOMPOSITION_PLAN.md
- docs/LOCAL_DEMO_BOOTSTRAP.md
면접이나 코드 리뷰에서 특히 설명 가치가 높은 지점은 아래입니다.
- 게임 상태를 서버가 직접 관리하는
Session / Stage / Attempt모델 - guest ownership -> member ownership으로 이어지는 기록 귀속
- terminal run만 leaderboard에 쓰고, public read model은 Redis + DB fallback으로 읽는 구조
- deterministic recommendation engine과 feedback loop
- browser smoke / public URL smoke / deploy preflight까지 이어지는 verification pipeline
- 공개 production URL은 아직 없습니다.
- 추천은 deterministic engine 중심이며 런타임 생성형 AI 호출은 없습니다.
- browser smoke는 대표 public 흐름과 terminal modal contract를 고정하지만, 전체 제품 full browser proof는 아닙니다.
- 신규 게임 3종은 public lineup의 첫 vertical slice이며 장기적인 난이도/콘텐츠 확장은 계속 남아 있습니다.
별도 라이선스 파일이 없다면 기본적으로 모든 권리는 저장소 소유자에게 있습니다.