15 KiB
15 KiB
chocoadmin 프로젝트 계획서
1. 프로젝트 개요
| 항목 | 내용 |
|---|---|
| 서비스명 | chocoadmin |
| 목적 | chocomae 웹 서비스(mouse-typing)의 관리자 기능을 독립 웹 서비스로 분리 |
| 기존 서비스 경로 | /Users/jisangs/work/jinaju/git/web/mouse-typing |
| 신규 서비스 경로 | /Users/jisangs/work/jinaju/git/web/chocoadmin |
| 기존 운영 환경 | AWS EC2 t3a.medium 인스턴스 1개 |
| 사용 DB | 기존 chocomae DB (MariaDB 10.11.13) 그대로 사용 |
2. 핵심 개발 방향
- 기존
chocomaeDB를 그대로 사용한다. DB 스키마는 임의로 변경하지 않는다. - 관리자 UI와 서버 로직만 신규 Next.js 서비스로 분리한다.
- 기존 테이블 구조와 상태값을 그대로 존중하고, 기존 서비스의 비즈니스 규칙을 먼저 파악한 뒤 동일하게 구현한다.
- 승인·취소·거절 같은 변경 액션은 반드시 서버 사이드에서 권한 검증 → 트랜잭션 → 로그 기록 순서로 처리한다.
- 중복 처리 방지를 위해 모든 변경 API는 현재 상태를 조건으로 먼저 검사한다.
3. 기술 스택
| 구분 | 기술 |
|---|---|
| 런타임 | Node.js LTS |
| 프레임워크 | Next.js 16 (App Router) |
| 언어 | TypeScript |
| 패키지 매니저 | pnpm |
| UI / CSS | Tailwind CSS + shadcn/ui |
| Table | TanStack Table (React Table v8) |
| DB 클라이언트 | mysql2 (MariaDB 호환) |
| ORM | Prisma (기존 DB introspection 방식으로 활용) |
| 유효성 검증 | Zod |
| 인증 | NextAuth.js v5 (기존 admin 테이블 활용) |
| 환경변수 관리 | .env.local / .env.production |
Prisma vs Drizzle ORM
두 가지 모두 MariaDB를 지원하나, 이 프로젝트에서는 Prisma를 우선 사용한다.
- 기존 DB를
prisma db pull(introspection)로 그대로 가져올 수 있어 초기 세팅이 빠름 - TypeScript 타입 자동 생성으로 컬럼명 오타를 컴파일 단계에서 잡을 수 있음
- 세밀한 SQL 제어가 필요한 구간은
$queryRaw/$executeRaw로 raw SQL 병행 가능
4. 개발 환경 및 배포 환경
4-1. 개발 환경
| 항목 | 내용 |
|---|---|
| 하드웨어 | 맥미니 |
| IDE | IntelliJ IDEA |
| 실행 방법 | IntelliJ 터미널에서 pnpm dev |
| 포트 | 3000 |
| DB (개발) | 맥미니 로컬 MariaDB (localhost:3306) |
| 환경변수 | .env.local |
4-2. 배포(서비스) 환경
| 항목 | 내용 |
|---|---|
| 플랫폼 | Synology NAS DS920+ (RAM 20GB) — Docker |
| 실행 방법 | Synology Container Manager (docker compose up) |
| DB (서비스) | AWS EC2 MariaDB (chocomae 서비스와 동일 인스턴스) |
| DB 접근 | AWS 보안그룹에서 NAS 외부 IP만 3306 포트 허용 |
| DB 계정 | chocoadmin 전용 최소 권한 계정으로 분리 |
| 환경변수 | .env.production 또는 Container Manager 환경변수 설정 |
4-3. Dockerfile / docker-compose (배포용)
# Dockerfile
FROM node:22-alpine
RUN corepack enable && corepack prepare pnpm@latest --activate
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
COPY . .
RUN pnpm build
CMD ["pnpm", "start"]
# docker-compose.yml
services:
chocoadmin:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DATABASE_URL=mysql://USER:PASS@AWS_EC2_HOST:3306/chocomae
- NEXTAUTH_SECRET=...
- NEXTAUTH_URL=http://NAS_IP:3000
restart: unless-stopped
5. 데이터베이스 주요 테이블
스키마: docs/db-reference/schema.sql
| 테이블 | 설명 | 주요 컬럼 |
|---|---|---|
maestro |
마에스트로(강사) 계정 | MaestroID, Name, Email, AccountType, ActivateStatus, AvailableActivateDateTime, PlayerCount |
maestro_extension |
연장 신청 | MaestroExtensionID, MaestroID, AccountType, RequestedDateTime, Status |
maestro_upgrade |
업그레이드 신청 | MaestroUpgradeID, MaestroID, RegisteredAccountType, RequestedAccountType, RequestedDateTime, Status |
maestro_log |
처리 이력 로그 | MaestroLogID, MaestroID, Type, LogDateTime, Remark |
admin |
관리자 계정 | AdminID, Name, Password, Email, AccountType, ActivateStatus |
player |
학생 계정 | PlayerID, MaestroID, Name, EnterCode |
상태값 코드표
maestro.AccountType
| 값 | 의미 |
|---|---|
| 1 | 20명 (1만원) |
| 2 | 50명 (2만원) |
| 3 | 100명 (3만원) |
| 4 | 500명 (4만원) |
| 5 | 1,000명 (5만원) |
maestro.ActivateStatus
| 값 | 의미 |
|---|---|
| 0 | 미승인 |
| 1 | 체험 |
| 2 | 활성화 |
| 100 | 등록취소 |
maestro_extension.Status / maestro_upgrade.Status
| 값 | 의미 |
|---|---|
| 1 | 요청 |
| 2 | 취소/거절 |
| 3 | 적용 완료 |
6. 애플리케이션 구조
chocoadmin/
├── app/
│ ├── (auth)/
│ │ └── login/
│ │ └── page.tsx # 관리자 로그인
│ ├── (admin)/
│ │ ├── layout.tsx # 공통 사이드바 + 헤더
│ │ ├── maestros/
│ │ │ ├── page.tsx # 마에스트로 전체 목록
│ │ │ └── [maestroId]/
│ │ │ └── page.tsx # 마에스트로 상세 정보
│ │ ├── extension-requests/
│ │ │ └── page.tsx # 연장 신청 목록 + 승인/취소
│ │ └── upgrade-requests/
│ │ └── page.tsx # 업그레이드 신청 목록 + 승인/거절
│ └── api/
│ ├── auth/[...nextauth]/
│ ├── maestros/
│ │ ├── route.ts # GET: 목록
│ │ └── [id]/route.ts # GET: 상세, PATCH: 상태 변경
│ ├── extension-requests/
│ │ └── [id]/route.ts # PATCH: 승인/취소
│ └── upgrade-requests/
│ └── [id]/route.ts # PATCH: 승인/거절
├── components/
│ ├── ui/ # shadcn/ui 컴포넌트
│ ├── data-table/ # TanStack Table 공통 컴포넌트
│ ├── layout/ # 사이드바, 헤더
│ ├── forms/
│ └── dialogs/ # 승인/취소 확인 다이얼로그
├── lib/
│ ├── db.ts # Prisma Client 싱글톤
│ ├── auth.ts # NextAuth 설정
│ ├── validators/ # Zod 스키마
│ └── constants.ts # 상태값 상수
├── types/
│ └── index.ts
├── prisma/
│ └── schema.prisma # DB introspection 결과
├── docs/
│ └── db-reference/
│ └── schema.sql
├── .env.local # gitignore
├── .env.production # gitignore
├── Dockerfile
└── docker-compose.yml
7. 주요 화면 기능 명세
7-1. 공통 레이아웃
- 로그인 화면 (미인증 시
/login리다이렉트) - 좌측 사이드바 네비게이션
- 공통 확인 다이얼로그 (승인/취소/거절 전 확인)
- 처리 성공/실패 토스트 알림
7-2. 마에스트로 전체 목록 (/maestros)
- 전체 목록 조회 (서버 사이드 페이지네이션)
- 검색: 이름, 이메일, MaestroID
- 필터: ActivateStatus (미승인 / 체험 / 활성화 / 등록취소)
- 필터: AccountType (20명 / 50명 / 100명 / 500명 / 1,000명)
- 정렬: 가입일, 사용 가능일
- 컬럼: ID / 이름 / 이메일 / 계정 유형 / 상태 / 학생 수 / 사용 가능일 / 상세보기
7-3. 마에스트로 상세 정보 (/maestros/[maestroId])
- 기본 계정 정보 (이름, 이메일, 계정 유형, 상태, 만료일, 약관 동의일)
- 플레이어(학생) 목록 요약
- 연장 신청 이력
- 업그레이드 신청 이력
- 관리자 처리 로그 (
maestro_log)
7-4. 연장 신청 목록 (/extension-requests)
- 연장 신청 목록 조회 (기본 필터: Status=1 요청 건)
- 필터: 상태 (요청 / 취소 / 적용)
- 컬럼: 신청ID / 마에스트로명 / 계정유형 / 신청일시 / 상태 / 승인 / 취소
승인 처리 순서:
maestro_extension.Status = 1인지 확인 (중복 처리 방지)- 트랜잭션 시작
maestro_extension.Status → 3maestro.AvailableActivateDateTime연장,maestro.ActivateStatus → 2(기존 서비스 로직 확인 후 동일 적용)maestro_log기록- 트랜잭션 커밋
취소 처리 순서:
maestro_extension.Status = 1인지 확인- 트랜잭션 시작
maestro_extension.Status → 2maestro_log기록- 트랜잭션 커밋
7-5. 업그레이드 신청 목록 (/upgrade-requests)
- 업그레이드 신청 목록 조회 (기본 필터: Status=1 요청 건)
- 필터: 상태 (요청 / 취소 / 적용)
- 컬럼: 신청ID / 마에스트로명 / 현재등급 / 요청등급 / 신청일시 / 상태 / 승인 / 거절
승인 처리 순서:
maestro_upgrade.Status = 1인지 확인 (중복 처리 방지)- 트랜잭션 시작
maestro_upgrade.Status → 3maestro.AccountType → RequestedAccountType변경 (PlayerCount 갱신 정책은 기존 서비스 확인 후 동일 적용)maestro_log기록- 트랜잭션 커밋
거절 처리 순서:
maestro_upgrade.Status = 1인지 확인- 트랜잭션 시작
maestro_upgrade.Status → 2maestro_log기록- 트랜잭션 커밋
8. 보안 고려사항
- 관리자 로그인은 NextAuth 서버 세션 기반으로 구현한다.
- 기존
admin.Password저장 방식(평문/해시/자체 암호화)을 먼저 확인한 뒤 동일 방식 또는 해시 업그레이드를 결정한다. - 승인·취소·거절 액션은 Next.js Server Action 또는 API Route에서 CSRF 보호를 적용한다.
- DB 연결 정보는
.env파일로 관리하며 Git에 커밋하지 않는다. - 배포 DB 계정은 chocoadmin 전용 계정으로 분리하고 최소 권한(SELECT + 필요한 테이블만 UPDATE)을 적용한다.
- AWS EC2 보안그룹에서 MariaDB 포트(3306)를 NAS 외부 IP로만 허용한다.
- 관리자 전용 서비스이므로 외부에 직접 노출하지 않고 VPN 또는 NAS 내부 포트로 접근하는 방식을 권장한다.
9. 개발 단계 계획
Phase 0. 기존 관리자 코드 조사
기존 서비스 비즈니스 규칙을 파악해 재현 실수를 방지한다.
mouse-typing관리자 라우트와 처리 로직 분석 (src/web/admin/,src/web/server/admin/)- 연장 승인 시
AvailableActivateDateTime계산 방식 확인 (몇 개월/년 연장인지) - 업그레이드 승인 시
PlayerCount갱신 여부 확인 admin.Password검증 방식 확인 (평문 / MD5 / bcrypt 등)maestro_log기록 형식(Type,Remark) 확인- 조사 결과를
docs/business-rules.md에 문서화
Phase 1. 프로젝트 초기화
pnpm create next-app(Next.js 16, TypeScript, App Router, Tailwind CSS)- shadcn/ui 초기화 (
pnpm dlx shadcn@latest init) - TanStack Table 설치 (
pnpm add @tanstack/react-table) - Prisma 설치 및 MariaDB introspection (
pnpm add prisma,prisma db pull) - Zod 설치 (
pnpm add zod) - NextAuth.js v5 설치
- ESLint / Prettier 설정
.env.local환경변수 구조 정의- IntelliJ에서
pnpm dev실행 확인
Phase 2. DB 연결 및 타입 구성
- Prisma Client 싱글톤 (
lib/db.ts) - 상태값 상수 정의 (
lib/constants.ts) - 공통 유틸 작성 (날짜 포맷, AccountType 레이블 변환 등)
- 개발 DB에서
maestro,maestro_extension,maestro_upgrade조회 확인
Phase 3. 인증 및 공통 레이아웃
- 로그인 페이지 (
/login) - NextAuth Credentials Provider —
admin테이블 기반 검증 - 인증 프록시 (
proxy.ts) — 비로그인 시/login리다이렉트 - 공통 레이아웃 (
(admin)/layout.tsx) — 사이드바, 헤더 - 로그아웃 기능
Phase 4. 마에스트로 목록 및 상세
- 마에스트로 목록 API (
GET /api/maestros) — 검색·필터·페이지네이션 포함 - TanStack Table 기반 목록 화면
- 마에스트로 상세 API (
GET /api/maestros/[id]) - 상세 화면 — 연장/업그레이드 이력, 학생 목록 요약, 처리 로그
Phase 5. 연장 신청 관리
- 연장 신청 목록 API + 화면
- 승인/취소 확인 다이얼로그
- 승인 API (
PATCH /api/extension-requests/[id]) — 트랜잭션 + maestro_log - 취소 API — 트랜잭션 + maestro_log
Phase 6. 업그레이드 신청 관리
- 업그레이드 신청 목록 API + 화면
- 승인/거절 확인 다이얼로그
- 승인 API (
PATCH /api/upgrade-requests/[id]) — 트랜잭션 + maestro_log - 거절 API — 트랜잭션 + maestro_log
Phase 7. 배포 환경 구성
- Dockerfile (프로덕션용 pnpm 빌드)
docker-compose.yml(Synology NAS Container Manager용)- AWS EC2 보안그룹 인바운드 설정 (NAS IP → 3306 허용) —
docs/deployment.md에 절차 문서화 - Synology NAS에서 컨테이너 실행 테스트 —
docs/deployment.md에 절차 문서화 - 운영 DB read-only 리허설 후 변경 기능 활성화 —
docs/deployment.md에 절차 문서화
Phase 8. 검증 및 안정화
- 승인/취소/거절 트랜잭션 시나리오 테스트
- 중복 처리 방지 (이미 처리된 건 재처리 시 에러 확인)
- 비인증 접근 차단 확인
- Docker 재시작 후 정상 동작 확인
10. MVP 범위
1차 MVP (위 Phase 0~7):
- 관리자 로그인
- 마에스트로 전체 목록 및 상세 정보 보기
- 연장 신청 목록 / 승인 / 취소
- 업그레이드 신청 목록 / 승인 / 거절
- 관리자 액션 로그 기록
- Docker 기반 NAS 배포
MVP 이후 확장 후보:
- 마에스트로 상태 직접 변경
- 학생 목록 상세 관리
- 데이터 내보내기 (CSV)
- 처리 통계 대시보드
- 감사 로그 전용 화면
- 관리자 계정 관리
11. 구현 전 확인이 필요한 사항
기존 mouse-typing 서비스 코드(src/web/server/admin/)에서 반드시 확인해야 할 비즈니스 규칙들이다.
- 연장 승인 시
AvailableActivateDateTime을 정확히 얼마나 연장하는가? (1년? 계정 유형별 다름?) : 계정 유형별로 차이 없고, 1년 연장 - 업그레이드 승인 시
PlayerCount를 즉시 변경하는가, 아니면AccountType만 변경하는가? : AccountType만 변경 admin.Password는 어떤 방식으로 저장/검증되는가? (평문, MD5, bcrypt 등) : MariaDB의 Password() 함수를 이용해서 저장/검증됨maestro_log의Type컬럼에 어떤 값들이 사용되는가? (Remark형식 포함) : 다음과 같은 값들이 사용됨
- add_maestro
- update_maestro
- add_maestro
- register_maestro
- update_maestro_name
- extension_maestro
- upgrade_maestro
- update_maestro_email
- 운영 MariaDB가 외부 IP 접속을 허용할 수 있는 네트워크 구조인가? : 외부 IP 접속을 허용하고 있다
작성일: 2026-05-26