121 lines
4.5 KiB
Markdown
121 lines
4.5 KiB
Markdown
# 프로젝트 기술 명세
|
|
|
|
## 프로젝트 개요
|
|
|
|
- 프로젝트명: Play Uniare
|
|
- 목적: Union Arena 덱을 불러와 카드 조작 중심의 로컬·온라인 플레이 제공
|
|
- 현재 단계: 프로젝트 기반 구성
|
|
- 프런트엔드: Vue 3, Vite, Tailwind CSS
|
|
- 배포 대상: UGREEN NAS의 Docker 환경
|
|
|
|
## 제품 범위
|
|
|
|
### 포함
|
|
|
|
- 기존 덱 빌더 쿼리에서 덱 불러오기
|
|
- 카드 수량만큼 독립 인스턴스 생성
|
|
- 덱 셔플과 드로우
|
|
- 카드 드래그 이동
|
|
- 카드 앞면·뒷면 전환
|
|
- 카드 탭·언탭
|
|
- 손패, 필드, 덱, 무덤, 공개 영역
|
|
- 덱 위·아래 또는 무덤으로 카드 이동
|
|
- 덱 위에서 여러 장을 공개한 후 목적지 지정
|
|
- 혼자 연습하는 로컬 모드
|
|
- 방 코드 기반 2인 세션
|
|
- 각 플레이어가 자신의 카드만 조작하는 권한 모델
|
|
|
|
### 제외
|
|
|
|
- 카드 효과와 게임 규칙 자동 판정
|
|
- 음성·텍스트 채팅
|
|
- 랭킹, 매칭, 대회 운영
|
|
- 초기 단계의 회원가입
|
|
|
|
## 덱 입력
|
|
|
|
초기에는 기존 덱 빌더 형식을 호환한다.
|
|
|
|
```text
|
|
?series=ua03&seriesName=HUNTER%C3%97HUNTER&cards=<encoded-json>
|
|
```
|
|
|
|
수신 후 다음 절차를 적용한다.
|
|
|
|
1. 쿼리 길이와 필수 필드를 검사한다.
|
|
2. JSON 디코딩 오류를 처리한다.
|
|
3. `series`, `imgSrc`, `Number`, `count`를 검증한다.
|
|
4. 카드 수량만큼 고유한 게임 카드 인스턴스를 만든다.
|
|
5. 이미지 주소는 환경변수 기반 카드 자산 원본과 조합한다.
|
|
|
|
장기적으로는 축약된 덱 코드 또는 서버의 `deckId` 방식으로 전환한다.
|
|
|
|
## 권한 모델
|
|
|
|
- 플레이어는 자기 카드만 이동·뒤집기·탭·정리할 수 있다.
|
|
- 상대 효과로 내 카드가 제거될 때에도 내가 직접 내 카드를 이동한다.
|
|
- 서버는 모든 카드 조작에서 요청 사용자와 카드 소유자를 비교한다.
|
|
- 상대 손패에는 장수만 공개하고 카드 식별 정보는 공개하지 않는다.
|
|
|
|
## 화면 좌표
|
|
|
|
- 배경 이미지는 카드 배치 가이드로 사용한다.
|
|
- 실제 영역은 배경 위의 투명한 드롭 영역으로 정의한다.
|
|
- 자유 배치 좌표는 보드 너비·높이 기준 0부터 1 사이 값으로 저장한다.
|
|
- 창 크기가 변해도 같은 상대 위치를 유지해야 한다.
|
|
|
|
## 상태 저장
|
|
|
|
- 로컬 모드: 브라우저 메모리, 추후 복구가 필요하면 localStorage 검토
|
|
- 온라인 모드: 서버가 방 상태의 최종 권위를 가진다.
|
|
- 초기 서버: Node.js와 Socket.IO, 메모리 기반 방 상태
|
|
- 운영 안정화 단계: Redis 또는 데이터베이스 저장 검토
|
|
|
|
## 포트 정책
|
|
|
|
- Vue 개발 서버는 Vite가 제시하는 포트를 사용하며 기본값은 보통 `5173`이다.
|
|
- 로컬 Socket.IO 서버 기본 포트는 `31873`이다.
|
|
- Docker 컨테이너 내부 포트는 다른 컨테이너와 같아도 충돌하지 않는다.
|
|
- NAS 호스트에 공개하는 포트는 다른 서비스와 겹치면 안 된다.
|
|
- 테스트 HTTP 호스트 포트 기본값은 `41808`, 운영 기본값은 `41809`다.
|
|
- HTTP 호스트 포트는 `.env`의 `PLAYUNIARE_TEST_HTTP_PORT`와
|
|
`PLAYUNIARE_PRODUCTION_HTTP_PORT`로 변경한다.
|
|
- 운영 브라우저는 Socket.IO 포트를 직접 호출하지 않고
|
|
`https://playuniare.sori.studio/socket.io`처럼 같은 도메인의 리버스 프록시
|
|
경로를 사용한다.
|
|
- 포트 번호는 코드에 하드코딩하지 않고 환경변수와 Compose 설정으로 관리한다.
|
|
|
|
## 환경변수 예정
|
|
|
|
```text
|
|
VITE_CARD_ASSET_BASE_URL=/card-assets
|
|
VITE_SOCKET_SERVER_URL=https://playuniare.sori.studio
|
|
```
|
|
|
|
실제 운영 값은 `.env`에 두고 Git에 커밋하지 않는다.
|
|
|
|
## NAS 카드 이미지 공유
|
|
|
|
운영 NAS에서는 카드 이미지를 새 프로젝트에 복사하지 않는다. 기존 Uniare
|
|
컨테이너가 사용하는 웹 루트의 이미지 폴더를 읽기 전용으로 공유한다.
|
|
|
|
```text
|
|
기존 Uniare 웹 루트:
|
|
/volume1/docker/projects/apps/uniare/config/www
|
|
|
|
카드 이미지 원본:
|
|
/volume1/docker/projects/apps/uniare/config/www/images
|
|
|
|
Play Uniare 컨테이너 내부:
|
|
/srv/uniare-card-images
|
|
|
|
브라우저 공개 경로:
|
|
/card-assets
|
|
```
|
|
|
|
- `config/www`는 기존 `index.html`이 존재하는 실제 웹 루트다.
|
|
- Docker bind mount는 `images` 폴더만 읽기 전용으로 연결한다.
|
|
- Play Uniare는 기존 카드 이미지를 읽을 수 있지만 수정하거나 삭제할 수 없다.
|
|
- 카드 이미지 URL은 `/card-assets/<series>/<fileName>` 형식을 사용한다.
|
|
- 같은 Play Uniare 도메인으로 제공되므로 별도의 CORS 설정이 필요하지 않다.
|