- 개요, 조사(BGA·한국 인기 보드게임·UI/UX), 아키텍처, 실시간 프로토콜, 안정성·보안, 계정, 로비·방, UI/UX, 데이터 모델, 게임 엔진, 테스트, 배포·운영, 로드맵(M0~M9), 사용자 결정 항목 - 게임별 규칙·엔진 설계·UI·테스트 체크리스트 26종 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7.2 KiB
7.2 KiB
06. 로비와 방
1. 목표
- 방 만들기: 첫 화면에서 게임 카드 누르기 → "방 만들기" 두 번이면 대기실, 코드와 링크가 바로 보인다.
- 방 참여: 링크를 누르면 바로 대기실(처음이면 닉네임 한 칸). 코드를 받았으면 첫 화면 "코드로 참여"에 숫자 6개.
- 글을 몰라도 쓸 수 있게 큰 아이콘 + 짧은 글자.
2. 화면과 주소
| 주소 | 화면 |
|---|---|
/ |
홈: 위쪽에 큰 버튼 두 개 [방 만들기] [코드로 참여], 그 아래 "진행 중인 게임으로 돌아가기"(있을 때만), 그 아래 게임 카드 목록 |
/g/:gameId |
게임 소개: 한 줄 설명, 인원, 시간, 난이도, [방 만들기] [빠른 시작] [규칙 보기], 열린 공개 방 목록 |
/r/:code |
방(대기실 ↔ 게임 화면 ↔ 결과 화면이 같은 주소에서 전환) |
/j |
코드 입력 전용 화면(숫자 키패드) |
/me |
계정 |
/rules/:gameId |
규칙 설명(그림 포함) |
초대 링크는 https://<도메인>/r/123456. 짧고 읽기 쉬워서 말로 불러 줘도 된다.
3. 방 코드
- 6자리 숫자(000000 제외, 같은 숫자 6개·연속 숫자 제외). 숫자만 쓰는 이유: 어르신·어린이가 키패드로 입력하기 가장 쉽고, 말로 전달하기 쉽다.
- 화면에는
123 456처럼 3자리씩 띄어 보여 준다. 입력은 띄어쓰기·하이픈 무시. - 사용 중인 코드와 겹치지 않게 무작위 발급. 방이 끝나고 24시간 동안은 같은 코드 재사용 금지(옛 링크로 엉뚱한 방에 들어가는 것 방지).
- 코드 입력 화면: 6칸 큰 숫자 칸, 휴대폰 숫자 키패드(
inputmode="numeric"), 6자리가 채워지면 자동으로 입장 시도. 클립보드에 6자리 숫자나 초대 링크가 있으면 "붙여넣기" 버튼을 크게 표시.
4. 방 만들기
- 게임 선택(홈 카드 또는 홈의 [방 만들기] → 게임 고르기 화면).
- 바로 대기실 생성. 모든 옵션은 기본값으로 이미 정해져 있다(인원은 게임 기본 인원, 공개 여부는 "친구만(비공개)").
- 대기실에서 방장이 바꿀 수 있는 것: 게임 모드/옵션(시간 제한 포함 — 게임마다 다름), 최대 인원(게임의 최소~최대 범위 안), 공개/비공개, 관전 허용, 채팅 허용.
- 옵션은 "기본 설정" 몇 개만 보이고 나머지는 "자세한 설정" 접기 안에 둔다.
5. 대기실 화면 (위에서 아래 순서, 모바일 세로 기준)
- 초대 카드(가장 눈에 띄게): 큰 글씨 코드
123 456- [코드 복사] [링크 복사] [공유하기](모바일: 공유 시트 → 카카오톡 등) [QR 보기](같은 공간의 가족이 폰으로 찍어서 입장)
- 복사하면 버튼이 1.5초간 "복사했어요 ✓"로 바뀜 + 진동(지원 기기).
- 공유 문구: "OO님이 오목 방에 초대했어요! 코드 123 456 · https://<도메인>/r/123456"
- 자리 목록: 게임 인원만큼 자리 칸. 각 칸: 프로필, 닉네임, 방장 왕관, 준비 체크, 연결 상태 점(초록/노랑/회색). 빈자리는 점선 "+ 초대하기"(누르면 초대 카드로 스크롤).
- 게임 설정 요약: "오목 · 렌주룰 · 한 수 30초" + 방장에게만 [설정 바꾸기].
- 아래 고정 버튼(엄지 닿는 곳):
- 방장: [게임 시작] — 최소 인원이 안 되면 비활성 + "1명 더 필요해요" 안내. 모두 준비가 아니어도 시작 가능하되 "준비 안 된 사람이 있어요. 시작할까요?" 확인.
- 나머지: [준비하기] / [준비 취소].
- 채팅(접을 수 있음), 관전자 수.
방장 기능: 내보내기, 방장 넘기기, 자리 순서 섞기(선 정하기), 게임 바꾸기(같은 방 유지 — 친구들끼리 여러 게임 이어서 하기). 방장이 나가면 가장 먼저 들어온 사람이 방장.
6. 링크로 들어오기
/r/123456접속.- 로그인 안 됨 → 같은 화면 위에 작은 창: 방 정보("오목 · 방장 OO · 1/2명") + 닉네임 칸(추천 이름 채워짐) + [이 이름으로 입장] + 작게 [디스코드로 로그인].
- 입장 → 빈자리가 있으면 자동으로 자리에 앉는다. 없으면 관전자로 들어가고 "자리가 나면 앉을 수 있어요".
- 방이 없거나 끝났으면: "이 방은 끝났어요" + [같은 게임 새 방 만들기] [홈으로].
7. 빠른 시작
- 게임 상세의 [빠른 시작]: 같은 게임의 공개 대기실 중 사람이 가장 많은(가득 차지 않은) 방에 들어간다. 없으면 공개 방을 새로 만들고 기다린다.
- 기다리는 동안 "다른 사람을 기다리는 중… (공개 방)" + [친구 초대하기] 버튼.
8. 게임 중
- 위쪽 상태 줄: 지금 할 일 문장("내 차례예요" / "OO님 차례예요"), 남은 시간 링.
- 메뉴(⋯): 규칙 보기, 소리, 글자 크기, 무르기 요청(지원 게임), 무승부 제안(지원 게임), 기권, 나가기.
- 나가기를 누르면: "게임 중에 나가면 OO 처리돼요. 정말 나갈까요?"(게임별: 2인 대전은 기권패, 카드 게임은 다이 후 자리 비움 등).
- 관전자는 [자리 나면 참가] 대기 가능(다음 판부터).
9. 게임 끝
- 결과 화면: 순위, 점수, 핵심 장면 요약(예: "흑 5목 완성"), [한 판 더] [게임 바꾸기] [나가기].
- [한 판 더]는 투표: 자리에 앉은 사람 모두 누르면 같은 설정으로 즉시 새 게임(선/딜러는 규칙에 따라 교대). 안 누르는 사람이 있으면 그 사람이 [관전하기]로 일어나거나 방장이 [게임 시작]으로 바로 시작할 수 있다.
- 기록: 끝난 게임은
game_results에 저장, 방 안에서 "이번 방 전적"(예: OO 3승 2패) 표시.
10. 공개 방 목록
- 게임 상세 화면에서만 보인다(홈을 복잡하게 하지 않음). 정렬: 곧 시작할 방(빈자리 1개) 우선.
- 각 줄: 방 이름(기본 "OO님의 방"), 인원, 모드, [참여].
11. 서버 방 모델
type RoomStatus = 'lobby' | 'playing' | 'finished' | 'paused' | 'broken';
interface Room {
code: string; // 6자리
id: string; // 내부 ULID
hostId: UserId;
gameId: GameId;
options: unknown; // 게임 optionsSchema로 검증된 값
visibility: 'private' | 'public';
maxPlayers: number; // 게임 min~max 범위
graceSec: number; // 연결 끊김 유예(기본 60초). 턴 시간은 게임 옵션
allowSpectators: boolean;
chat: { enabled: boolean; filter: boolean };
seats: Array<{ userId: UserId; ready: boolean } | null>;
spectators: Set<UserId>;
presence: Map<UserId, { connected: boolean; since: number; autoCount: number }>;
status: RoomStatus;
seq: number;
game?: { state: unknown; rng: RngState; deadline: number | null; startedAt: number; seedHash: string };
rematchVotes: Set<UserId>;
sessionStats: Map<UserId, { wins: number; played: number }>;
createdAt: number; lastActiveAt: number;
}
- 한 사용자는 동시에 한 방에만 플레이어로 있을 수 있다(다른 방에 들어가면 이전 방 대기실 자리에서 빠짐. 이전 방이 게임 중이면 "진행 중인 게임이 있어요. 그래도 이동할까요?").
- 제한: 서버 전체 방 2,000개, 사용자당 동시에 만든 방 3개.