All checks were successful
Server CI/CD / deploy (push) Successful in 36s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
63 lines
2.0 KiB
Markdown
63 lines
2.0 KiB
Markdown
# 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` 마운트로 컨테이너 재시작 후에도 유지.
|