- unsafe 타입 단언 → safe assertion (chain handler 11곳, auth Logout) - Repository 에러 시 nil 반환으로 통일 (chain, auth, announcement) - string ID → uint 파싱으로 타입 안전성 확보 (auth, announcement) - CORS AllowHeaders에 Idempotency-Key, X-API-Key 추가 - /verify 엔드포인트 rate limiter 적용 - Redis 호출에 context timeout 적용 (auth, idempotency 미들웨어) - chain handler 에러 응답에서 내부 정보 노출 방지 - f.Close() 에러 검사 추가 (download service 2곳) - 공지사항 Delete 404 응답 추가 - 회원가입 롤백 시 Delete 에러 로깅 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
5.3 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Commands
go run . # 로컬 실행
go build -o server . # 빌드
docker build -t a301-server . # Docker 빌드
Tech Stack
- Go + Fiber v2 (StreamRequestBody: true — 대용량 업로드용, Body Limit 4GB)
- GORM + MySQL (AutoMigrate 사용)
- Redis — JWT 세션 저장(
session:{userID},refresh:{userID}) + 멱등성 캐시 - JWT —
golang-jwt/jwt v5, Access + Refresh 토큰 로테이션
Project Purpose
"One of the plans" 게임 플랫폼 백엔드. 인증 / 공지사항 / 게임 파일 업로드·서빙 / 블록체인(TOL Chain) 연동 담당.
Project Structure
internal/
├── auth/ # User 모델, JWT 발급·검증, 세션 관리(Redis)
├── announcement/ # Announcement CRUD
├── download/ # Info 조회, 파일 업로드(스트리밍), 파일 서빙
└── chain/ # 블록체인 지갑·거래·마켓·인벤토리 (5파일: handler, service, repository, model, client)
pkg/
├── config/ # 환경변수 → Config 구조체
├── database/ # ConnectMySQL(), ConnectRedis()
└── middleware/ # Auth, AdminOnly, ServerAuth, Idempotency
routes/routes.go # 모든 라우트 등록
Key Patterns
- 계층 구조:
Handler → Service → Repository. 각 도메인 폴더에 4~5파일. - 파일 업로드:
Fiber StreamRequestBody: true+io.Copy로 raw body를 직접 디스크에 스트리밍. 메모리에 파일 올리지 않음. - SHA256 자동 추출: 게임 zip 업로드 시 zip 내
A301.exe를 스트리밍으로 읽어 해시 계산. - CORS:
AllowMethods에PATCH포함 필수 (유저 권한 변경 엔드포인트).AllowOrigins:https://a301.tolelom.xyz. - 초기 admin 계정: 서버 시작 시
EnsureAdmin()으로 존재 확인 후 없으면 생성. - DI 패턴:
main.go에서 생성자 함수로 Repo → Service → Handler 주입. - 콜백 연결:
authSvc.SetWalletCreator()— 회원가입 시 자동 지갑 생성.chainSvc.SetUserResolver()— username → userID 변환.
Middleware
- Auth:
Authorization: Bearer <jwt>검증 + Redis 세션 확인.c.Locals("userID", "username", "role")설정. - AdminOnly:
role == "admin"확인, 아니면 403. - ServerAuth:
X-API-Key헤더 검증. 게임 서버 → API 서버 내부 통신용. - Idempotency:
Idempotency-Key헤더로 중복 요청 방지. Redis 캐시 TTL 10분. 블록체인 트랜잭션 이중 지출 방지용.
JWT 토큰 로테이션
- Access Token:
JWT_SECRET으로 서명, 기본 24시간 만료, Redissession:{userID}에 저장. - Refresh Token:
REFRESH_SECRET으로 서명, 7일 만료, Redisrefresh:{userID}에 저장. - Refresh 시: 이전 토큰 무효화 + 새 Access/Refresh 쌍 발급 (로테이션).
- Logout: Redis에서 session + refresh 키 모두 삭제.
Rate Limiting
- Auth 엔드포인트: IP당 10 req/min
- 일반 API: IP당 60 req/min
블록체인 연동 (internal/chain/)
TOL Chain 노드와 JSON-RPC 2.0 통신.
- UserWallet 모델: ed25519 키페어 생성, 개인키는 AES-256-GCM 암호화 후 DB 저장.
- client.go: Chain 노드 RPC 호출 (10초 타임아웃).
- service.go: 지갑 생성/암호화, 트랜잭션 서명, 마켓/인벤토리 로직.
- 내부 API: 게임 서버가 username 기반으로 보상 지급 (
/api/internal/chain/*).
Routes
인증: POST /api/auth/{register,login,refresh,logout,verify} (register/login/refresh는 rate limit)
유저 관리 (admin): GET /api/users/, PATCH /api/users/:id/role, DELETE /api/users/:id
공지사항: GET /api/announcements/, POST|PUT|DELETE /api/announcements/:id (CUD는 admin)
다운로드: GET /api/download/{info,file,launcher}, POST /api/download/upload/{game,launcher} (upload는 admin)
체인 조회 (JWT): GET /api/chain/{wallet,balance,assets,asset/:id,inventory,market,market/:id}
체인 트랜잭션 (JWT + Idempotency): POST /api/chain/{transfer,asset/transfer,market/list,market/buy,market/cancel,inventory/equip,inventory/unequip}
체인 관리자 (JWT + Admin + Idempotency): POST /api/chain/admin/{mint,reward,template}
내부 API (X-API-Key + Idempotency): POST /api/internal/chain/{reward,mint}, GET /api/internal/chain/{balance,assets,inventory} (username 쿼리 파라미터)
Environment Variables
APP_PORT=8080
DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, DB_NAME
REDIS_ADDR, REDIS_PASSWORD
JWT_SECRET, REFRESH_SECRET, JWT_EXPIRY_HOURS(기본24)
ADMIN_USERNAME, ADMIN_PASSWORD
BASE_URL=https://a301.api.tolelom.xyz
GAME_DIR=/data/game
CHAIN_NODE_URL=http://localhost:8545
CHAIN_ID=tolchain-dev
OPERATOR_KEY_HEX # 오퍼레이터 개인키 (블록체인 트랜잭션 서명용)
WALLET_ENCRYPTION_KEY # 64자 hex = 32바이트 AES-256 키 (지갑 암호화)
INTERNAL_API_KEY # 게임 서버 인증용 API 키
File Storage
게임 파일은 GAME_DIR(/data/game)에 저장:
/data/game/game.zip— 게임 본체/data/game/launcher.exe— 런처
Docker 볼륨 game_data:/data/game 마운트로 컨테이너 재시작 후에도 유지.