254 lines
9.9 KiB
Markdown
254 lines
9.9 KiB
Markdown
# Play Uniare AI 작업 지침
|
|
|
|
## 1. 문서 목적
|
|
|
|
이 파일은 사람과 AI 작업자가 같은 기준으로 프로젝트를 이해하고 변경하기
|
|
위한 최상위 작업 규칙이다. 작업 시작 전에 이 파일과 `docs/`의 관련 문서를
|
|
반드시 읽는다.
|
|
|
|
## 2. 프로젝트 목표
|
|
|
|
- 기존 UA Deck Builder가 전달한 덱 데이터로 카드 시뮬레이터를 제공한다.
|
|
- 게임 규칙을 자동 판정하지 않는다.
|
|
- 사용자가 카드 이동, 뒤집기, 탭, 덱·손패·무덤 이동을 직접 수행한다.
|
|
- 혼자 연습하는 로컬 모드와 방 코드 기반 2인 세션을 제공한다.
|
|
- 각 플레이어는 자신이 소유한 카드만 조작한다.
|
|
- 상대 효과로 내 카드가 제거되는 경우에도 내 카드 소유자가 직접 처리한다.
|
|
|
|
## 3. 기술 기준
|
|
|
|
- 프런트엔드: Vue 3 Composition API와 `<script setup>`
|
|
- 빌드 도구: Vite
|
|
- 스타일: Tailwind CSS 우선
|
|
- 상태 관리: Pinia
|
|
- 화면 이동: Vue Router
|
|
- 실시간 통신: Node.js와 Socket.IO
|
|
- 배포: Docker Compose와 Nginx
|
|
- 운영 환경: UGREEN NAS
|
|
|
|
새 라이브러리를 추가하기 전에는 기존 기술로 해결 가능한지 확인하고, 추가
|
|
이유와 영향을 `docs/history.md`에 기록한다.
|
|
|
|
## 4. 작업 시작 절차
|
|
|
|
1. `AGENTS.md`를 읽는다.
|
|
2. `docs/spec.md`, `docs/map.md`, `docs/todo.md`를 읽는다.
|
|
3. `git status`로 기존 변경 사항을 확인한다.
|
|
4. 관련 코드와 기존 패턴을 확인한다.
|
|
5. 작업 범위를 작게 정하고 구현한다.
|
|
6. 빌드와 관련 검증을 수행한다.
|
|
7. 변경 성격에 맞는 문서를 업데이트한다.
|
|
8. 작업 결과 형식에 맞춰 보고한다.
|
|
|
|
## 5. 코드 작성 규칙
|
|
|
|
### 5.1 공통
|
|
|
|
- 기존 패턴을 우선하며 최소 범위만 수정한다.
|
|
- 하나의 컴포넌트는 하나의 분명한 역할을 갖는다.
|
|
- 반복되는 값은 상수, 설정 또는 데이터 모델로 분리한다.
|
|
- 서버 주소, 이미지 원본 주소, 포트, 비밀값을 코드에 하드코딩하지 않는다.
|
|
- 임시 이름과 의미 없는 자리표시자 이름을 사용하지 않는다.
|
|
- 검증 없이 작업을 완료 처리하지 않는다.
|
|
|
|
### 5.2 네이밍
|
|
|
|
- 의미가 드러나는 영문 이름을 사용한다.
|
|
- 축약어를 남용하지 않는다.
|
|
- `temp`, `tmp`, `test1`, `data1`, `foo`, `bar`, `aaa` 같은 임시 이름을
|
|
금지한다.
|
|
- Vue 컴포넌트 파일은 PascalCase를 사용한다.
|
|
- 함수와 변수는 camelCase를 사용한다.
|
|
- 상수는 의미가 분명한 경우 UPPER_SNAKE_CASE를 사용한다.
|
|
- 이벤트 이름은 발생한 사실을 나타내는 kebab-case를 사용한다.
|
|
- 불리언 값은 `is`, `has`, `can`, `should` 접두어를 우선한다.
|
|
|
|
### 5.3 Vue
|
|
|
|
- Composition API와 `<script setup>`을 사용한다.
|
|
- 화면 컴포넌트는 `src/views/`, 재사용 컴포넌트는 `src/components/`에 둔다.
|
|
- 비즈니스 상태를 컴포넌트 내부에 중복 저장하지 않는다.
|
|
- props를 직접 변경하지 않는다.
|
|
- 외부 효과와 구독은 컴포넌트 해제 시 반드시 정리한다.
|
|
|
|
### 5.4 스타일
|
|
|
|
- Tailwind CSS 유틸리티를 기본으로 사용한다.
|
|
- 반복되는 디자인 패턴은 컴포넌트로 추출한다.
|
|
- 임의 픽셀값은 게임 보드 좌표처럼 필요한 경우에만 사용하고 이유를
|
|
문서화한다.
|
|
- 카드 위치는 화면 픽셀이 아니라 보드 기준 정규화 좌표 또는 영역 기반으로
|
|
저장한다.
|
|
- 인라인 `style`은 드래그 좌표, 회전처럼 동적 계산이 필요한 경우에만
|
|
허용한다.
|
|
|
|
### 5.5 주석
|
|
|
|
- 함수와 클래스 앞에는 한국어 JSDoc 문서화 주석을 작성한다.
|
|
- 주석은 코드가 무엇을 하는지 반복하기보다 이유, 제약, 입력·출력을 설명한다.
|
|
- 복잡한 타입은 `@typedef`, 함수 입력은 `@param`, 반환은 `@returns`를 쓴다.
|
|
|
|
```js
|
|
/**
|
|
* 덱 빌더에서 전달된 카드 목록을 실제 카드 인스턴스로 확장한다.
|
|
*
|
|
* @param {ImportedDeckCard[]} importedCards 수량이 포함된 덱 카드 목록
|
|
* @returns {GameCard[]} 고유 식별자가 부여된 카드 인스턴스 목록
|
|
*/
|
|
function createGameCardInstances(importedCards) {
|
|
return []
|
|
}
|
|
```
|
|
|
|
## 6. 상태 관리 원칙
|
|
|
|
### 6.1 상태 구분
|
|
|
|
- 서버 권위 상태: 방, 플레이어, 카드 소유권, 카드 영역, 덱 순서
|
|
- 공유 게임 상태: 필드 카드 좌표, 앞뒷면, 탭 상태, 무덤, 공개 영역
|
|
- 개인 비공개 상태: 내 손패 카드 식별 정보
|
|
- 로컬 UI 상태: 선택 카드, 드래그 중 여부, 메뉴 열림, 확대 상태
|
|
|
|
서버 권위 상태를 UI 컴포넌트의 로컬 상태만으로 확정하지 않는다.
|
|
|
|
### 6.2 카드 모델
|
|
|
|
카드는 덱 원본 정보와 플레이 중 인스턴스를 구분한다.
|
|
|
|
```js
|
|
{
|
|
instanceId: 'player-1-card-17',
|
|
ownerId: 'player-1',
|
|
cardNumber: 'EX01BT/HTR-2-001',
|
|
imageFileName: 'EX01BT_HTR-2-001.png',
|
|
zone: 'deck',
|
|
position: { x: 0.5, y: 0.5 },
|
|
isFaceUp: false,
|
|
isTapped: false,
|
|
stackOrder: 17
|
|
}
|
|
```
|
|
|
|
- `instanceId`는 같은 카드 여러 장을 구분하는 고유값이다.
|
|
- 소유권은 게임 시작 후 임의로 변경하지 않는다.
|
|
- 카드 조작 요청은 요청자와 `ownerId`가 같은지 서버에서 확인한다.
|
|
- 상대 손패에는 카드 번호와 이미지 정보를 전송하지 않는 방향을 우선한다.
|
|
|
|
### 6.3 실시간 이벤트
|
|
|
|
- 상태 전체를 매번 전송하기보다 명시적인 이벤트와 필요한 변경값을 전송한다.
|
|
- 이벤트 이름은 `card-moved`, `card-flipped`, `deck-shuffled`처럼 작성한다.
|
|
- 재접속 시에는 서버의 최신 전체 스냅샷으로 복구한다.
|
|
- 같은 이벤트가 중복 수신되어도 상태가 망가지지 않도록 설계한다.
|
|
|
|
## 7. 데이터 처리 원칙
|
|
|
|
- 기존 덱 빌더 쿼리는 초기 덱 불러오기 용도로만 사용한다.
|
|
- 외부 입력은 신뢰하지 않고 스키마 검사 후 사용한다.
|
|
- 카드 이미지 URL은 환경변수의 원본 주소와 파일 경로를 조합한다.
|
|
- NAS 운영 환경에서는
|
|
`/volume1/docker/projects/apps/uniare/config/www/images`를 컨테이너에 읽기
|
|
전용으로 연결하고 `/card-assets` 경로로 제공한다.
|
|
- 기존 Uniare의 `config/www/images`에는 쓰기 작업을 수행하지 않는다.
|
|
- NAS 카드 파일 소유자 UID가 `1000`이므로 Nginx 워커는 `cardreader`
|
|
사용자(UID 1000)로 실행한다. 이 기준을 바꾸기 전에는 실제 NAS 파일
|
|
소유자를 다시 확인한다.
|
|
- 로컬 Socket.IO 서버 기본 포트는 `31873`을 사용한다.
|
|
- 운영 환경에서는 Socket.IO 포트를 브라우저에 직접 노출하지 않고 같은
|
|
도메인의 `/socket.io` 경로로 리버스 프록시한다.
|
|
- 컨테이너 내부 포트 중복은 허용되지만 NAS 호스트 공개 포트 중복은 금지한다.
|
|
- 운영 HTTP 호스트 포트는 Compose에 숫자를 직접 추가하지 않고
|
|
`PLAYUNIARE_PRODUCTION_HTTP_PORT` 환경변수로 관리한다.
|
|
- 기능 검증은 로컬에서 수행하고 NAS에는 운영 컨테이너만 배포한다.
|
|
- 운영 데이터가 생기면 마이그레이션 코드는 Git으로 관리하고, 백업과 재실행
|
|
안전성을 확인한 뒤 실행한다.
|
|
- NAS에서 즉석 데이터 변경 명령을 사용한 경우 같은 변경을 정식
|
|
마이그레이션 코드와 문서로 남긴다.
|
|
- URL 길이 문제를 고려해 장기적으로 덱 코드 또는 `deckId` 방식을 도입한다.
|
|
- URL, 로그, Git에 사용자 토큰이나 비밀값을 남기지 않는다.
|
|
- 오류가 있는 카드 한 장 때문에 전체 덱 불러오기가 중단되지 않도록 오류
|
|
목록을 사용자에게 명확히 보여준다.
|
|
|
|
## 8. 문서 업데이트 기준
|
|
|
|
- 기능 변경 → `docs/spec.md`
|
|
- 버그 수정 → `docs/update.md`
|
|
- 이슈 발견 → `docs/todo.md`
|
|
- 구조·기술·의사결정 변경 → `docs/history.md`
|
|
- 화면 변경 → `docs/map.md`
|
|
- 배포 변경 → `docs/deploy.md`
|
|
- 개발 명령 변경 → `docs/development.md`
|
|
- 데이터 구조·마이그레이션 변경 → `docs/migrations.md`
|
|
|
|
문서 업데이트 누락을 금지한다.
|
|
|
|
## 9. 금지 사항
|
|
|
|
- 기존 스타일과 구조를 확인하지 않은 변경
|
|
- 요청 범위를 벗어난 대규모 리팩터링
|
|
- 서버 주소, 포트, API 키와 비밀번호 하드코딩
|
|
- `.env`, 인증서, 개인키, NAS 계정 정보 커밋
|
|
- 조작 권한 검증을 클라이언트에만 의존
|
|
- 상대의 비공개 손패 정보를 클라이언트로 전송
|
|
- 테스트 또는 빌드 검증 없이 완료 처리
|
|
- 관련 문서 업데이트 누락
|
|
|
|
## 10. 의사결정 원칙
|
|
|
|
1. 기존 패턴 우선
|
|
2. 최소 수정
|
|
3. 유지보수 용이성
|
|
4. 구조 파악 용이성
|
|
5. 사용자가 직접 운영할 수 있는 단순성
|
|
6. 비공개 정보와 카드 소유권의 안전성
|
|
|
|
## 11. 단계별 개발 계획
|
|
|
|
### 1단계: 로컬 싱글 플레이
|
|
|
|
- 대기실과 덱 URL 등록
|
|
- 덱 쿼리 파싱과 검증
|
|
- 카드 인스턴스 생성
|
|
- 첫 손패, 멀리건, 라이프 세팅
|
|
- 덱 셔플과 드로우
|
|
- 카드 이동, 뒤집기, 탭
|
|
- 손패, 필드, 무덤, 공개 영역
|
|
- 덱 위·아래 이동과 위에서 N장 공개
|
|
|
|
### 2단계: 2인 세션
|
|
|
|
- 로비와 방 생성·참가 완료
|
|
- 플레이어 좌석 할당 완료
|
|
- Socket.IO 서버와 NAS 리버스 프록시 완료
|
|
- 실시간 카드 이벤트 동기화
|
|
- 상대 손패 비공개 처리
|
|
- 연결 종료와 재접속 복구
|
|
|
|
### 3단계: 운영 안정화
|
|
|
|
- NAS Docker 배포
|
|
- 상태 저장소 도입 검토
|
|
- 모바일·태블릿 조작 개선
|
|
- 오류 로그와 상태 복구
|
|
- 관전자와 게임 기록은 별도 검토
|
|
|
|
구체적인 미완료 항목은 `docs/todo.md`에서 관리한다.
|
|
|
|
## 12. 작업 결과 보고 형식
|
|
|
|
- 수정 내용
|
|
- 변경 파일
|
|
- 검증 내용
|
|
- 문서 반영 여부
|
|
- 남은 이슈
|
|
|
|
## 13. 최종 체크리스트
|
|
|
|
- [ ] `AGENTS.md`와 관련 `docs/` 확인
|
|
- [ ] 코드 수정 완료
|
|
- [ ] 네이밍과 JSDoc 규칙 확인
|
|
- [ ] 빌드 또는 관련 검증 수행
|
|
- [ ] 변경 성격에 맞는 문서 반영
|
|
- [ ] 민감 정보 포함 여부 확인
|
|
- [ ] 남은 이슈를 `docs/todo.md`에 기록
|