diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..e9ce97d --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,62 @@ +# CLAUDE.md + +## Commands + +```bash +go run . # 로컬 실행 +go build -o server . # 빌드 +docker build -t a301-server . # Docker 빌드 +``` + +## Tech Stack + +- **Go** + **Fiber v2** (StreamRequestBody: true — 대용량 업로드용) +- **GORM** + **MySQL** (AutoMigrate 사용) +- **Redis** — JWT 블랙리스트 +- **JWT** — `golang-jwt/jwt v5` + +## Project Purpose + +"One of the plans" 게임 플랫폼 백엔드. +인증 / 공지사항 / 게임 파일(game.zip + launcher.exe) 업로드·서빙 담당. + +## Project Structure + +``` +internal/ +├── auth/ # User 모델, JWT 발급·검증, 블랙리스트(Redis) +├── announcement/ # Announcement CRUD +└── download/ # Info 조회, 파일 업로드(스트리밍), 파일 서빙 +pkg/ +├── config/ # 환경변수 → Config 구조체 +├── database/ # ConnectMySQL(), ConnectRedis() +└── middleware/ # Auth (JWT 검증), AdminOnly +routes/routes.go # 모든 라우트 등록 +``` + +## Key Patterns + +- **계층 구조**: `Handler → Service → Repository`. 각 도메인 폴더에 4파일(handler, service, repository, model). +- **파일 업로드**: `Fiber StreamRequestBody: true` + `io.Copy`로 raw body를 직접 디스크에 스트리밍. 메모리에 파일 올리지 않음. +- **SHA256 자동 추출**: 게임 zip 업로드 시 zip 내 `A301.exe`를 스트리밍으로 읽어 해시 계산. +- **CORS**: `AllowMethods`에 `PATCH` 포함 필수 (유저 권한 변경 엔드포인트). +- **초기 admin 계정**: 서버 시작 시 `EnsureAdmin()`으로 존재 확인 후 없으면 생성. + +## Environment Variables + +필수 운영 설정: +``` +BASE_URL=https://a301.api.tolelom.xyz +GAME_DIR=/data/game +JWT_SECRET=<강력한 랜덤값> +ADMIN_USERNAME=admin +ADMIN_PASSWORD=<강력한 비밀번호> +``` + +## File Storage + +게임 파일은 `GAME_DIR`(`/data/game`)에 저장: +- `/data/game/game.zip` — 게임 본체 +- `/data/game/launcher.exe` — 런처 + +Docker 볼륨 `game_data:/data/game` 마운트로 컨테이너 재시작 후에도 유지. diff --git a/README.md b/README.md new file mode 100644 index 0000000..02bf8f2 --- /dev/null +++ b/README.md @@ -0,0 +1,97 @@ +# One of the plans — Backend Server + +Go 기반 REST API 서버. 유저 인증, 공지사항, 게임 파일 배포를 담당합니다. + +## 기술 스택 + +- **Go** + **Fiber v2** — HTTP 프레임워크 +- **GORM** + **MySQL** — ORM / 주 데이터베이스 +- **Redis** — JWT 블랙리스트 (로그아웃 처리) +- **JWT** (`golang-jwt/jwt v5`) — 인증 + +## 실행 + +```bash +# 로컬 (MySQL, Redis 필요) +go run . + +# Docker +docker build -t a301-server . +docker run -p 8080:8080 --env-file .env a301-server +``` + +## 환경 변수 + +| 변수 | 설명 | 기본값 | +|------|------|--------| +| `APP_PORT` | 서버 포트 | `8080` | +| `DB_HOST` | MySQL 호스트 | `localhost` | +| `DB_PORT` | MySQL 포트 | `3306` | +| `DB_USER` | MySQL 사용자 | `root` | +| `DB_PASSWORD` | MySQL 비밀번호 | `""` | +| `DB_NAME` | 데이터베이스 이름 | `a301` | +| `REDIS_ADDR` | Redis 주소 | `localhost:6379` | +| `REDIS_PASSWORD` | Redis 비밀번호 | `""` | +| `JWT_SECRET` | JWT 서명 키 | `secret` | +| `JWT_EXPIRY_HOURS` | JWT 만료 시간(시) | `24` | +| `ADMIN_USERNAME` | 초기 관리자 계정 | `admin` | +| `ADMIN_PASSWORD` | 초기 관리자 비밀번호 | `admin1234` | +| `BASE_URL` | 외부 접근 URL (파일 URL 생성용) | `http://localhost:8080` | +| `GAME_DIR` | 게임 파일 저장 경로 | `/data/game` | + +## API 엔드포인트 + +### Auth +| 메서드 | 경로 | 설명 | +|--------|------|------| +| POST | `/api/auth/register` | 회원가입 | +| POST | `/api/auth/login` | 로그인 → JWT 반환 | +| POST | `/api/auth/logout` | 로그아웃 (토큰 블랙리스트) | + +### Users (관리자 전용) +| 메서드 | 경로 | 설명 | +|--------|------|------| +| GET | `/api/users/` | 전체 유저 목록 | +| PATCH | `/api/users/:id/role` | 유저 권한 변경 | +| DELETE | `/api/users/:id` | 유저 삭제 | + +### Announcements +| 메서드 | 경로 | 설명 | +|--------|------|------| +| GET | `/api/announcements/` | 공지사항 목록 | +| POST | `/api/announcements/` | 공지 생성 (관리자) | +| PUT | `/api/announcements/:id` | 공지 수정 (관리자) | +| DELETE | `/api/announcements/:id` | 공지 삭제 (관리자) | + +### Download +| 메서드 | 경로 | 설명 | +|--------|------|------| +| GET | `/api/download/info` | 게임/런처 메타데이터 (버전, 크기, SHA256) | +| GET | `/api/download/file` | `game.zip` 다운로드 | +| GET | `/api/download/launcher` | `launcher.exe` 다운로드 | +| POST | `/api/download/upload/game` | 게임 zip 업로드 (관리자) | +| POST | `/api/download/upload/launcher` | launcher.exe 업로드 (관리자) | + +업로드 엔드포인트는 raw body 스트리밍으로 대용량 파일을 메모리 없이 디스크에 직접 저장합니다. +게임 zip 업로드 시 내부 `A301.exe`의 SHA256 해시를 자동 추출합니다. + +## 프로젝트 구조 + +``` +. +├── main.go +├── routes/routes.go +├── internal/ +│ ├── auth/ # handler, service, repository, model +│ ├── announcement/ +│ └── download/ +└── pkg/ + ├── config/ # 환경 변수 로드 + ├── database/ # MySQL, Redis 연결 + └── middleware/ # JWT 인증, AdminOnly +``` + +## Docker / 배포 + +`/data/game` 볼륨에 `game.zip`과 `launcher.exe`가 저장됩니다. +`docker-compose.yml`에 named volume `game_data:/data/game` 마운트 필요.