17 KiB
기존 관리자 비즈니스 규칙
작성일: 2026-06-09
1. 개요
이 문서는 기존 mouse-typing 관리자 기능을 조사해 신규 chocoadmin에서 재현해야 할 비즈니스 규칙을 정리한 것이다.
조사 대상:
- 기존 서비스:
/Users/jisangs/work/jinaju/git/web/mouse-typing - 관리자 화면:
src/web/admin/ - 관리자 서버:
src/web/server/admin/ - 공통 로그 유틸:
src/web/server/lib/maestro_log.php - 계정 표시/계산 유틸:
src/web/js/lib/account_info.js,src/web/js/maestro_available_date.js
중요 결론:
- 관리자 비밀번호는 MariaDB
PASSWORD()함수로 검증한다. - 연장 승인은 기존 만료일 기준 1년 연장하되, 만료된 계정은 오늘 기준 1년 연장한다.
- 기존 연장 승인 서버는 날짜를 직접 계산하지 않고 화면에서 전달한
new_available_date를 저장한다. - 업그레이드 승인은
AccountType,ActivateStatus,AvailableActivateDateTime만 변경하고PlayerCount는 변경하지 않는다. - 기존 관리자에는 연장 취소/업그레이드 거절 버튼이 없다. 승인 처리 중 같은 마에스트로의 다른 요청을
Status=2로 닫는 동작만 있다. - 기존 변경 처리에는 명시적 트랜잭션이 없다.
2. 기존 관리자 파일 맵
| 기존 화면 | 서버 파일 | 역할 | 신규 chocoadmin 매핑 |
|---|---|---|---|
admin/login.html |
server/admin/login.php |
관리자 로그인 | /login, NextAuth Credentials Provider |
admin/admin_all_list.html |
server/admin/maestro_all_list.php |
전체 마에스트로 목록 조회 | /maestros, GET /api/maestros |
admin/admin_register_list.html |
server/admin/maestro_registered_list.php, server/admin/register_maestro.php |
미승인 마에스트로 조회 및 등록 승인 | MVP 외 또는 상세 보조 규칙 |
admin/admin_extension_list.html |
server/admin/maestro_extension_list.php, server/admin/extension_maestro.php |
연장 요청 조회 및 승인 | /extension-requests, PATCH /api/extension-requests/[id] |
admin/admin_upgrade_list.html |
server/admin/maestro_upgrade_list.php, server/admin/upgrade_maestro.php |
업그레이드 요청 조회 및 승인 | /upgrade-requests, PATCH /api/upgrade-requests/[id] |
admin/admin_expiration_list.html |
없음 | 정적 골격만 존재, 실제 조회 로직 없음 | MVP 제외 |
admin/admin_send_email.html |
server/mail/send_mail_test.php |
테스트 메일 발송 화면 | MVP 제외 |
admin/admin_header.html |
없음 | 관리자 메뉴 링크 | 공통 사이드바/헤더 |
3. 상태값 코드표
maestro.AccountType
| 값 | 의미 | 정원 | 금액 |
|---|---|---|---|
| 1 | 20명 | 20 | 10,000 |
| 2 | 50명 | 50 | 20,000 |
| 3 | 100명 | 100 | 30,000 |
| 4 | 500명 | 500 | 40,000 |
| 5 | 1,000명 | 1,000 | 50,000 |
| 100 | 학생체험 | - | - |
| 101 | 마에체험 | - | - |
maestro.ActivateStatus
| 값 | 기존 표시 | 의미 |
|---|---|---|
| 0 | 미승인 / 입금대기 | 가입 후 관리자 승인 전 |
| 1 | 체험 | 체험 계정 |
| 2 | 활성화 | 유료 활성 계정 |
| 100 | 등록 취소 / 환불 | 등록 취소 또는 환불 상태 |
maestro_extension.Status
| 값 | 기존 표시 | 의미 |
|---|---|---|
| 1 | 요청 | 연장 요청 |
| 2 | 취소 | 닫힌 요청 |
| 3 | 업그레이드 적용 | 코드상 공통 표시 문구이나 실제 의미는 연장 적용 |
maestro_upgrade.Status
| 값 | 기존 표시 | 의미 |
|---|---|---|
| 1 | 요청 | 업그레이드 요청 |
| 2 | 취소 | 닫힌 요청 |
| 3 | 업그레이드 적용 | 업그레이드 적용 |
4. 로그인/관리자 인증 규칙
기존 흐름:
login.html에서admin_name,password를server/admin/login.php로 POST한다.get_admin_id($adminName)에서admin.Name = ?조건으로 관리자 존재 여부를 먼저 확인한다.login($adminName, $password)에서admin.Name = ? AND admin.Password = PASSWORD(?)조건으로 검증한다.- 응답 데이터로
adminID,accountType,activateStatus를 반환한다.
실패 조건:
| 조건 | error_code | message |
|---|---|---|
Name에 해당하는 관리자 없음 |
not_registered_id |
등록되지 않은 서비스 관리자 아이디입니다. |
| 비밀번호 검증 결과 없음 | no_data 또는 wrong_password |
로그인하지 못했습니다. / 비밀번호가 틀렸습니다. |
ActivateStatus === 0 |
not_activated |
서비스 관리자 계정이 아직 활성화되지 않았습니다. |
신규 구현 규칙:
- 기존 계정 호환을 위해 최초 구현은 MariaDB
PASSWORD()함수를 이용해 검증한다. - NextAuth 세션에는 최소
adminID,accountType,activateStatus를 포함한다. ActivateStatus = 0관리자는 로그인시키지 않는다.PASSWORD()는 보안상 낡은 방식이므로, 해시 업그레이드는 별도 마이그레이션 과제로 분리한다.
5. 마에스트로 목록 조회 규칙
전체 목록
기존 서버: server/admin/maestro_all_list.php
검색어가 없을 때:
- 테이블:
maestro - 컬럼:
MaestroID,Name,AccountType,ActivateStatus,AvailableActivateDateTime,AcceptClausesDateTime,PlayerCount - 정렬:
MaestroID DESC
검색어가 있을 때:
- 조건:
Name LIKE CONCAT('%', ?, '%') - 정렬:
MaestroID DESC - 주의: 기존 검색 쿼리는
AvailableActivateDateTime을 조회하지 않는데 화면은 해당 값을 사용한다. 신규 구현에서는 전체/검색 결과 모두 동일 컬럼을 반환해야 한다.
기존 화면 표시:
- 상태 텍스트는
accountStatus(accountType, activateStatus)로 계산한다. AvailableActivateDateTime이0으로 시작하면 빈 문자열로 표시한다.- 비활성화 버튼은 disabled 상태이며 동작하지 않는다.
신규 구현 규칙:
Name,Email,MaestroID검색을 지원하되 기존 기본 정렬은MaestroID DESC로 시작한다.- 전체/검색 결과의 반환 컬럼 차이를 만들지 않는다.
미승인 등록 목록
기존 서버: server/admin/maestro_registered_list.php
- 테이블:
maestro - 조건:
ActivateStatus = 0 - 검색 조건:
Name LIKE CONCAT('%', ?, '%') AND ActivateStatus = 0 - 컬럼:
MaestroID,Name,AccountType,AcceptClausesDateTime - 정렬:
MaestroID DESC
6. 등록/활성화 처리 규칙
기존 서버: server/admin/register_maestro.php
처리 순서:
maestro.ActivateStatus = 1로 변경한다.maestro.AvailableActivateDateTime = '2022-07-31 23:59:59'로 변경한다.player에 테스트 플레이어Name='마에스트로',EnterCode='',AccountType=1을 추가한다.- 추가된 테스트 플레이어를
maestro.MaestroTestID에 저장한다. app.Status = 1인 앱을 모두active_app에 추가한다.- 샘플 학생 4명을
player.AccountType = 0으로 추가한다. player.AccountType = 0학생 수를 세어maestro.PlayerCount에 저장한다.- 등록 완료 메일을 발송한다.
maestro_log에register_maestro로그를 기록한다.
주의:
- 코드에는
DATE_ADD(NOW(), INTERVAL 1 YEAR)와DATE_ADD(NOW(), INTERVAL 14 DAY)가 주석으로 남아 있지만 실제 실행 쿼리는 고정일2022-07-31 23:59:59다. - 현재 MVP의 핵심 변경 기능은 연장/업그레이드이므로 등록 승인은 별도 범위로 둘 수 있다.
7. 연장 신청 조회/승인 규칙
요청 생성
기존 서버: server/maestro/request_extension_maestro.php
maestro_extension에AccountType,RequestedDateTime = NOW(),Status = 1,MaestroID를 INSERT한다.- 같은 마에스트로의 기존 요청 중복 여부는 검사하지 않는다.
- INSERT 후
MaestroID기준 전체 연장 요청 수가 1개 이상인지 단순 확인한다. - 입금 안내 메일을 발송한다.
관리자 목록 조회
기존 서버: server/admin/maestro_extension_list.php
검색어가 없을 때:
- 테이블:
maestro_extension E,maestro M - 조건:
E.Status < 2 AND E.MaestroID = M.MaestroID - 컬럼:
E.MaestroExtensionID,E.MaestroID,M.Name,E.AccountType,E.RequestedDateTime,M.AvailableActivateDateTime,E.Status - 정렬:
E.MaestroExtensionID DESC
검색어가 있을 때:
- 조건:
M.Name LIKE CONCAT('%', ?, '%') AND E.MaestroID = M.MaestroID - 주의: 검색 쿼리에는
E.Status < 2조건이 없다. 신규 구현에서는 기본 정책에 맞게 상태 필터를 명시적으로 제공해야 한다.
관리자 승인
기존 화면: admin/admin_extension_list.html
availableActivateDateTime의 날짜 부분을 기준으로 새 만료일을 계산한다.- 계산 유틸:
src/web/js/maestro_available_date.js - 현재 만료일이 지났으면 오늘 기준 1년 후 날짜를 사용한다.
- 현재 만료일이 지나지 않았으면 기존 만료일 기준 1년 후 날짜를 사용한다.
- 서버에는
new_available_date문자열을 POST한다.
기존 서버: server/admin/extension_maestro.php
처리 순서:
maestro.ActivateStatus = 2,maestro.AvailableActivateDateTime = DATE_FORMAT(?, '%Y-%m-%d')로 변경한다.- 같은
MaestroID의maestro_extension.Status = 1요청을 모두Status = 2로 변경한다. - 선택한
MaestroExtensionID요청을Status = 3으로 변경한다. - 연장 완료 메일을 발송한다.
maestro_log에extension_maestro로그를 기록한다.
로그:
Type:extension_maestroRemark:{maestro_name}({registered_account_type})
신규 구현 규칙:
- 날짜 계산은 클라이언트가 아니라 서버에서 수행한다.
- 기존 규칙과 동일하게 만료 전이면 기존 만료일 기준 +1년, 만료 후면 현재일 기준 +1년으로 계산한다.
AvailableActivateDateTime저장 시 기존 서버는 날짜만 저장하므로 시간은 DB 기본 파싱 결과를 고려해야 한다. 신규 구현에서는 일관성을 위해YYYY-MM-DD 00:00:00또는 기존 호환 형식을 명시한다.- 승인 전 선택한 요청이
Status = 1인지 확인한다. - 트랜잭션 안에서
maestro,maestro_extension,maestro_log를 함께 처리한다. - 같은 마에스트로의 다른
Status = 1요청을Status = 2로 닫은 뒤 선택 요청을Status = 3으로 적용하는 기존 동작을 재현한다.
8. 업그레이드 신청 조회/승인 규칙
요청 생성
기존 서버: server/maestro/request_upgrade_maestro.php
maestro_upgrade에RegisteredActivateStatus,RegisteredAccountType,RequestedAccountType,RequestedDateTime = NOW(),Status = 1,MaestroID를 INSERT한다.- 같은 마에스트로의 기존 요청 중복 여부는 검사하지 않는다.
- INSERT 후
MaestroID기준 전체 업그레이드 요청 수가 1개 이상인지 단순 확인한다. - 체험 계정이면 체험 업그레이드 입금 안내 메일, 그 외에는 일반 업그레이드 입금 안내 메일을 발송한다.
관리자 목록 조회
기존 서버: server/admin/maestro_upgrade_list.php
검색어가 없을 때:
- 테이블:
maestro_upgrade U,maestro M - 조건:
U.Status < 2 AND U.MaestroID = M.MaestroID - 컬럼:
U.MaestroUpgradeID,U.MaestroID,M.Name,U.RegisteredActivateStatus,U.RegisteredAccountType,U.RequestedAccountType,U.RequestedDateTime,M.AvailableActivateDateTime,U.Status - 정렬:
U.MaestroUpgradeID DESC
검색어가 있을 때:
- 조건:
M.Name LIKE CONCAT('%', ?, '%') AND U.MaestroID = M.MaestroID - 주의: 검색 쿼리에는
U.Status < 2조건이 없다. 신규 구현에서는 상태 필터를 명시적으로 제공해야 한다.
관리자 승인
기존 화면: admin/admin_upgrade_list.html
Status = 1인 요청만 승인 버튼을 표시한다.- 체험 계정(
RegisteredActivateStatus = 1)은 기존 요금제를trialAccountType으로 표시하고 추가 금액은 요청 요금제 전체 금액으로 계산한다. - 그 외 계정은 추가 금액을
RequestedAccountType금액 -RegisteredAccountType금액으로 계산한다.
기존 서버: server/admin/upgrade_maestro.php
처리 순서:
maestro.AccountType = upgrade_account_type으로 변경한다.maestro.ActivateStatus = 2로 변경한다.maestro.AvailableActivateDateTime = DATE_ADD(NOW(), INTERVAL 1 YEAR)로 변경한다.- 같은
MaestroID의maestro_upgrade.Status = 1요청을 모두Status = 2로 변경한다. - 선택한
MaestroUpgradeID요청을Status = 3으로 변경한다. - 체험 계정이면 체험 업그레이드 완료 메일, 그 외에는 일반 업그레이드 완료 메일을 발송한다.
maestro_log에upgrade_maestro로그를 기록한다.
로그:
Type:upgrade_maestroRemark:{registered_account_type} -> {upgrade_account_type}
확정 사항:
PlayerCount는 변경하지 않는다.AvailableActivateDateTime은 기존 만료일 기준이 아니라 승인 시점NOW()기준 1년 후로 설정한다.
신규 구현 규칙:
- 승인 전 선택한 요청이
Status = 1인지 확인한다. - 트랜잭션 안에서
maestro,maestro_upgrade,maestro_log를 함께 처리한다. - 같은 마에스트로의 다른
Status = 1요청을Status = 2로 닫은 뒤 선택 요청을Status = 3으로 적용하는 기존 동작을 재현한다. PlayerCount는 업그레이드 승인에서 변경하지 않는다.
9. 취소/거절 규칙
기존 관리자 UI/서버에서 확인된 사실:
- 연장 신청에 대한 별도 취소 버튼이나 취소 API는 없다.
- 업그레이드 신청에 대한 별도 거절 버튼이나 거절 API는 없다.
Status = 2는 승인 처리 중 같은 마에스트로의 다른 미처리 요청을 닫기 위해 사용된다.- 화면 유틸
status()는Status = 2를 "취소"로 표시하지만, 관리자가 명시적으로 취소/거절하는 흐름은 구현되어 있지 않다.
신규 구현 판단:
docs/plan/project-plan.md의 취소/거절 기능은 기존 관리자 재현이 아니라 신규 보완 기능이다.- 취소/거절 API를 만들 경우
Status = 1인 단일 요청만Status = 2로 변경하고maestro_log에 별도 로그를 남기는 방식으로 정의해야 한다. - 기존
maestro_log.Type에는 취소/거절 전용 타입이 없으므로 신규 타입을 도입할지 기존 타입에Remark로 표현할지 결정이 필요하다.
권장 신규 로그 타입:
cancel_extension_maestroreject_upgrade_maestro
10. maestro_log 기록 규칙
공통 함수: src/web/server/lib/maestro_log.php
INSERT INTO maestro_log (Type, MaestroID, LogDateTime, Remark)
VALUES (?, ?, NOW(), ?)
확인된 로그 타입:
| Type | 발생 위치 | Remark 형식 |
|---|---|---|
add_maestro |
server/maestro/add_maestro.php |
{maestro_name} / {email} / {account_type} |
register_maestro |
server/admin/register_maestro.php |
{name} / {email} |
extension_maestro |
server/admin/extension_maestro.php |
{maestro_name}({registered_account_type}) |
upgrade_maestro |
server/admin/upgrade_maestro.php |
{registered_account_type} -> {upgrade_account_type} |
update_maestro_name |
server/maestro/update_maestro_info.php |
{previous_name} -> {new_name} |
update_maestro_email |
server/maestro/update_maestro_info.php |
{previous_email} -> {new_email} |
확인 결과:
update_maestro타입은 코드 검색에서 확인되지 않았다.- 로그에는 관리자 ID나 관리자 이름이 포함되지 않는다.
- 로그 시간은 DB 서버의
NOW()를 사용한다. Remark컬럼은char(100)이므로 신규 구현에서도 길이 초과에 주의한다.
11. 신규 chocoadmin 구현 시 반드시 지켜야 할 규칙
- 운영 DB 스키마는 변경하지 않는다.
- 관리자 로그인은 기존
admin.Name과admin.Password = PASSWORD(?)호환 검증을 지원한다. - 모든 변경 API는 서버에서 현재 상태를 다시 조회하고
Status = 1인지 확인한다. - 승인/취소/거절 같은 변경 작업은 트랜잭션으로 묶는다.
- 연장 승인은 서버에서 새 만료일을 계산한다.
- 업그레이드 승인은
PlayerCount를 변경하지 않는다. - 연장/업그레이드 승인 시 같은 마에스트로의 다른 요청을
Status = 2로 닫고 선택 요청을Status = 3으로 적용한다. - 기존 목록 검색 쿼리의 상태 필터 누락은 그대로 복제하지 말고 명시적 필터로 보완한다.
- 메일 발송은 트랜잭션 커밋 이후 수행하는 것이 안전하다. 기존 코드는 DB 변경 후 메일을 발송한다.
12. 기존 코드에는 없지만 신규 구현에서 보완할 사항
- 명시적 트랜잭션: 기존 관리자 변경 로직에는
BEGIN,COMMIT,ROLLBACK이 없다. - 중복 처리 방지: 기존 승인 서버는 요청의 현재
Status를 먼저 검증하지 않는다. - 서버 사이드 날짜 계산: 기존 연장 승인은 클라이언트 계산값을 신뢰한다.
- 검색 필터 일관성: 연장/업그레이드 검색 쿼리에
Status < 2조건이 빠져 있다. - 목록 컬럼 일관성: 전체 마에스트로 검색 쿼리에
AvailableActivateDateTime이 빠져 있다. - 취소/거절 정의: 기존에는 별도 액션이 없으므로 신규 기능으로 명세화해야 한다.
- 감사성 강화: 기존
maestro_log에는 관리자 식별자가 없으므로 세션 기반 감사 로그가 필요하면 별도 설계가 필요하다. 단, DB 스키마 변경 없이 구현하려면Remark에 관리자 정보를 포함하는 방식만 가능하다.