headscale-tailscale-replace.../FLASK_ADMIN_DEVELOPMENT_PLAN.md
시골약사 35ecd4748e PharmQ SaaS 구독 서비스 관리 시스템 완전 구현
📋 기획 및 설계:
- PharmQ SaaS 서비스 기획서 작성
- 구독 서비스 라인업 정의 (클라우드PC, AI CCTV, CRM)
- DB 스키마 설계 및 API 아키텍처 설계

🗄️ 데이터베이스 구조:
- service_products: 서비스 상품 마스터 테이블
- pharmacy_subscriptions: 약국별 구독 현황 테이블
- subscription_usage_logs: 서비스 이용 로그 테이블
- billing_history: 결제 이력 테이블
- 샘플 데이터 자동 생성 (21개 구독, 월 118만원 매출)

🔧 백엔드 API 구현:
- 구독 현황 통계 API (/api/subscriptions/stats)
- 약국별 구독 조회 API (/api/pharmacies/subscriptions)
- 구독 상세 정보 API (/api/pharmacy/{id}/subscriptions)
- 구독 생성/해지 API (/api/subscriptions)

🖥️ 프론트엔드 UI 구현:
- 대시보드 구독 현황 카드 (월 매출, 구독 수, 구독률 등)
- 약국 목록에 구독 상태 아이콘 및 월 구독료 표시
- 약국 상세 페이지 구독 서비스 섹션 추가
- 실시간 구독 생성/해지 기능 구현

 주요 특징:
- 서비스별 색상 코딩 및 이모지 아이콘 시스템
- 실시간 업데이트 (구독 생성/해지 즉시 반영)
- 반응형 디자인 (모바일/태블릿 최적화)
- 툴팁 기반 상세 정보 표시

📊 현재 구독 현황:
- 총 월 매출: ₩1,180,000
- 구독 약국: 10/14개 (71.4%)
- AI CCTV: 6개 약국, CRM: 10개 약국, 클라우드PC: 5개 약국

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-11 19:48:12 +09:00

508 lines
22 KiB
Markdown

# 🌐 Flask + Jinja2 Headplane 고도화 관리자 페이지 개발 계획
## 📋 프로젝트 개요
### 개발 목표
기존 Headplane UI를 포크하지 않고, **Flask + Jinja2**로 별도 관리자 페이지를 구축하여 Headscale 데이터베이스와 직접 연동하는 고도화된 관리 시스템 개발
### 핵심 컨셉
- **기존 Headplane**: 기본 기능 유지 (3000번 포트)
- **Flask Admin**: 고도화된 관리 기능 (5000번 포트)
- **데이터 통합**: 동일한 SQLite DB 공유로 실시간 동기화
- **팜큐 특화**: 약국 관리에 최적화된 UI/UX
## 🏗️ 아키텍처 설계
### 시스템 구조
```
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Headplane UI │ │ Flask Admin │ │ Headscale API │
│ (포트: 3000) │ │ (포트: 5000) │ │ (포트: 8070) │
│ 기본 기능 │ │ 고도화 기능 │ │ 백엔드 API │
└─────────────────┘ └──────────────────┘ └─────────────────┘
│ │ │
└───────────────────────┼───────────────────────┘
┌──────────────────┐
│ SQLite Database │
│ (공유 데이터) │
└──────────────────┘
```
### 포트 구성
- **Headscale API**: 8070 (기존 유지)
- **Headplane UI**: 3000 (기존 유지)
- **Flask Admin**: 5000 (신규 추가)
## 📂 Flask 프로젝트 구조
```
farmq-admin/
├── app.py # Flask 애플리케이션 메인
├── config.py # 설정 파일
├── requirements.txt # Python 의존성
├── models/
│ ├── __init__.py
│ ├── headscale_models.py # SQLAlchemy 모델 (재사용)
│ └── pharmacy_models.py # 팜큐 확장 모델
├── routes/
│ ├── __init__.py
│ ├── dashboard.py # 메인 대시보드
│ ├── pharmacy.py # 약국 관리
│ ├── machines.py # 머신 관리 (고도화)
│ ├── users.py # 사용자 관리 (고도화)
│ ├── monitoring.py # 실시간 모니터링
│ └── api.py # REST API 엔드포인트
├── templates/
│ ├── base.html # 기본 레이아웃
│ ├── dashboard/
│ │ ├── index.html # 메인 대시보드
│ │ └── stats.html # 통계 대시보드
│ ├── pharmacy/
│ │ ├── list.html # 약국 목록
│ │ ├── detail.html # 약국 상세
│ │ ├── create.html # 약국 등록
│ │ └── edit.html # 약국 수정
│ ├── machines/
│ │ ├── list.html # 머신 목록 (고도화)
│ │ ├── detail.html # 머신 상세 (하드웨어 정보)
│ │ └── monitoring.html # 실시간 모니터링
│ └── users/
│ ├── list.html # 사용자 목록 (약국 정보 포함)
│ └── detail.html # 사용자 상세
├── static/
│ ├── css/
│ │ ├── bootstrap.min.css # Bootstrap 5
│ │ ├── custom.css # 커스텀 스타일
│ │ └── dashboard.css # 대시보드 전용 스타일
│ ├── js/
│ │ ├── bootstrap.min.js # Bootstrap JS
│ │ ├── chart.min.js # Chart.js 라이브러리
│ │ ├── dashboard.js # 대시보드 JS
│ │ └── monitoring.js # 실시간 모니터링 JS
│ └── img/
│ ├── logo.png # 팜큐 로고
│ └── icons/ # 아이콘들
├── utils/
│ ├── __init__.py
│ ├── database.py # DB 연결 유틸리티
│ ├── auth.py # 인증 관련
│ ├── monitoring.py # 모니터링 데이터 수집
│ └── proxmox.py # Proxmox API 연동
└── docker/
├── Dockerfile # Flask 앱용 도커파일
└── docker-compose.yml # 통합 컨테이너 구성
```
## 🎨 UI/UX 설계
### 디자인 컨셉
- **Modern Dashboard**: Bootstrap 5 기반 반응형 디자인
- **팜큐 브랜딩**: 약국 관리에 특화된 색상/아이콘 사용
- **Korean-First**: 한국어 우선 인터페이스
- **Mobile Responsive**: 모바일/태블릿 완벽 지원
### 메인 대시보드 레이아웃
```
┌────────────────────────────────────────────────────────────┐
│ 🏥 팜큐 약국 관리 시스템 [관리자: admin] [로그아웃] │
├────────────────────────────────────────────────────────────┤
│ [대시보드] [약국관리] [머신관리] [사용자관리] [모니터링] [설정] │
├────────────────────────────────────────────────────────────┤
│ 📊 전체 현황 │
│ ┌──────────┬──────────┬──────────┬──────────────────────┐ │
│ │총 약국 수 │온라인 │오프라인 │평균 CPU 온도 │ │
│ │ 100 │ 95 │ 5 │ 62°C │ │
│ └──────────┴──────────┴──────────┴──────────────────────┘ │
│ │
│ 🚨 실시간 알림 📈 성능 차트 │
│ ┌─────────────────────────┐ ┌────────────────────┐ │
│ │• 부산해운약국: CPU 85°C │ │ [CPU 사용률 차트] │ │
│ │• 대구중앙약국: 디스크95% │ │ [메모리 사용률] │ │
│ │• 서울약국: 연결 끊김 │ │ [네트워크 트래픽] │ │
│ └─────────────────────────┘ └────────────────────┘ │
│ │
│ 📋 약국별 상태 (실시간) │
│ ┌─────────────┬────────┬────────┬────────┬──────────────┐ │
│ │약국명 │상태 │CPU온도 │메모리 │마지막 접속 │ │
│ ├─────────────┼────────┼────────┼────────┼──────────────┤ │
│ │서울중앙약국 │🟢 온라인│ 65°C │ 80% │ 2분 전 │ │
│ │부산해운약국 │🟡 경고 │ 85°C │ 60% │ 5분 전 │ │
│ │대구중앙약국 │🔴 위험 │ 70°C │ 95% │ 10분 전 │ │
│ └─────────────┴────────┴────────┴────────┴──────────────┘ │
└────────────────────────────────────────────────────────────┘
```
## 🎯 핵심 기능 명세
### 1. 통합 대시보드
```python
# routes/dashboard.py
@app.route('/')
def dashboard():
stats = {
'total_pharmacies': get_pharmacy_count(),
'online_machines': get_online_machines_count(),
'offline_machines': get_offline_machines_count(),
'avg_cpu_temp': get_average_cpu_temperature(),
'alerts': get_active_alerts(),
'recent_activities': get_recent_activities()
}
return render_template('dashboard/index.html', stats=stats)
```
### 2. 약국 관리 시스템
#### 2-1. 약국 목록 페이지
```html
<!-- templates/pharmacy/list.html -->
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header d-flex justify-content-between">
<h5>🏥 약국 관리</h5>
<button class="btn btn-primary" onclick="location.href='/pharmacy/create'">
<i class="fas fa-plus"></i> 새 약국 등록
</button>
</div>
<div class="card-body">
<table class="table table-hover">
<thead>
<tr>
<th>약국명</th>
<th>사업자번호</th>
<th>담당자</th>
<th>연결된 머신</th>
<th>상태</th>
<th>마지막 접속</th>
<th>액션</th>
</tr>
</thead>
<tbody>
{% for pharmacy in pharmacies %}
<tr>
<td>
<strong>{{ pharmacy.pharmacy_name }}</strong><br>
<small class="text-muted">{{ pharmacy.address }}</small>
</td>
<td>{{ pharmacy.business_number }}</td>
<td>
{{ pharmacy.manager_name }}<br>
<small class="text-muted">{{ pharmacy.phone }}</small>
</td>
<td>
<span class="badge bg-info">{{ pharmacy.machine_count }}대</span>
</td>
<td>
{% if pharmacy.is_online %}
<span class="badge bg-success">🟢 온라인</span>
{% else %}
<span class="badge bg-danger">🔴 오프라인</span>
{% endif %}
</td>
<td>{{ pharmacy.last_seen_humanized }}</td>
<td>
<div class="btn-group btn-group-sm">
<a href="/pharmacy/{{ pharmacy.id }}" class="btn btn-outline-primary">상세</a>
<a href="/pharmacy/{{ pharmacy.id }}/edit" class="btn btn-outline-warning">수정</a>
<a href="/pharmacy/{{ pharmacy.id }}/monitoring" class="btn btn-outline-info">모니터링</a>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
```
### 3. 고도화된 머신 관리
#### 3-1. 머신 상세 페이지 (하드웨어 정보 포함)
```html
<!-- templates/machines/detail.html -->
<div class="container-fluid">
<div class="row">
<!-- 기본 정보 -->
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h5>🖥️ 머신 기본 정보</h5>
</div>
<div class="card-body">
<dl class="row">
<dt class="col-sm-4">머신명:</dt>
<dd class="col-sm-8">{{ machine.given_name }}</dd>
<dt class="col-sm-4">호스트명:</dt>
<dd class="col-sm-8">{{ machine.hostname }}</dd>
<dt class="col-sm-4">IP 주소:</dt>
<dd class="col-sm-8">
<code>{{ machine.ipv4 }}</code>
</dd>
<dt class="col-sm-4">소속 약국:</dt>
<dd class="col-sm-8">
<a href="/pharmacy/{{ machine.pharmacy.id }}">
{{ machine.pharmacy.pharmacy_name }}
</a>
</dd>
<dt class="col-sm-4">마지막 접속:</dt>
<dd class="col-sm-8">
{% if machine.is_online() %}
<span class="badge bg-success">🟢 온라인</span>
{% else %}
<span class="badge bg-danger">🔴 {{ machine.last_seen_humanized }}</span>
{% endif %}
</dd>
</dl>
</div>
</div>
</div>
<!-- 하드웨어 사양 -->
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h5>⚙️ 하드웨어 사양</h5>
</div>
<div class="card-body">
{% if machine.specs %}
<dl class="row">
<dt class="col-sm-4">CPU:</dt>
<dd class="col-sm-8">{{ machine.specs.cpu_model }} ({{ machine.specs.cpu_cores }}코어)</dd>
<dt class="col-sm-4">RAM:</dt>
<dd class="col-sm-8">{{ machine.specs.ram_gb }}GB</dd>
<dt class="col-sm-4">Storage:</dt>
<dd class="col-sm-8">{{ machine.specs.storage_gb }}GB</dd>
<dt class="col-sm-4">GPU:</dt>
<dd class="col-sm-8">{{ machine.specs.gpu_model or '없음' }}</dd>
</dl>
{% else %}
<p class="text-muted">하드웨어 정보가 등록되지 않았습니다.</p>
<a href="/machines/{{ machine.id }}/specs" class="btn btn-outline-primary btn-sm">
하드웨어 정보 등록
</a>
{% endif %}
</div>
</div>
</div>
</div>
<!-- 실시간 모니터링 -->
<div class="row mt-4">
<div class="col-12">
<div class="card">
<div class="card-header">
<h5>📊 실시간 모니터링</h5>
</div>
<div class="card-body">
{% if machine.latest_monitoring %}
<div class="row">
<div class="col-md-3">
<div class="text-center">
<canvas id="cpuChart" width="100" height="100"></canvas>
<h6 class="mt-2">CPU 사용률</h6>
<span class="h4 text-primary">{{ machine.latest_monitoring.cpu_usage }}%</span>
</div>
</div>
<div class="col-md-3">
<div class="text-center">
<canvas id="memoryChart" width="100" height="100"></canvas>
<h6 class="mt-2">메모리 사용률</h6>
<span class="h4 text-info">{{ machine.latest_monitoring.memory_usage }}%</span>
</div>
</div>
<div class="col-md-3">
<div class="text-center">
<div class="display-4 text-warning">🌡️</div>
<h6>CPU 온도</h6>
<span class="h4 text-warning">{{ machine.latest_monitoring.cpu_temperature }}°C</span>
</div>
</div>
<div class="col-md-3">
<div class="text-center">
<div class="display-4 text-success">💾</div>
<h6>디스크 사용률</h6>
<span class="h4 text-success">{{ machine.latest_monitoring.disk_usage }}%</span>
</div>
</div>
</div>
{% else %}
<div class="alert alert-info">
<i class="fas fa-info-circle"></i>
아직 모니터링 데이터가 없습니다. 잠시 후 다시 확인해주세요.
</div>
{% endif %}
</div>
</div>
</div>
</div>
</div>
<script>
// 실시간 업데이트를 위한 JavaScript
function updateMonitoring() {
fetch(`/api/machines/{{ machine.id }}/monitoring`)
.then(response => response.json())
.then(data => {
// 차트 업데이트 로직
updateCharts(data);
});
}
// 5초마다 업데이트
setInterval(updateMonitoring, 5000);
</script>
```
### 4. 실시간 모니터링 시스템
```python
# routes/monitoring.py
from flask import Blueprint, jsonify
from utils.monitoring import collect_monitoring_data
from utils.proxmox import ProxmoxAPI
monitoring_bp = Blueprint('monitoring', __name__)
@monitoring_bp.route('/api/monitoring/realtime')
def realtime_monitoring():
"""실시간 모니터링 데이터 API"""
data = {
'total_machines': get_total_machines(),
'online_count': get_online_machines_count(),
'alerts': get_active_alerts(),
'performance': get_performance_summary()
}
return jsonify(data)
@monitoring_bp.route('/api/machines/<int:machine_id>/monitoring')
def machine_monitoring(machine_id):
"""특정 머신 모니터링 데이터"""
monitoring_data = collect_monitoring_data(machine_id)
return jsonify(monitoring_data)
```
## 🔧 기술 스택
### Backend
- **Flask 3.0**: 웹 프레임워크
- **SQLAlchemy 2.0**: ORM (기존 모델 재사용)
- **Jinja2**: 템플릿 엔진
- **Flask-Login**: 사용자 인증
- **APScheduler**: 백그라운드 작업 (모니터링 데이터 수집)
### Frontend
- **Bootstrap 5**: CSS 프레임워크
- **Chart.js**: 차트 라이브러리
- **Font Awesome**: 아이콘
- **jQuery**: DOM 조작
- **Socket.io**: 실시간 통신
### 데이터베이스
- **SQLite**: 기존 Headscale DB 공유
- **확장 테이블**: PharmacyInfo, MachineSpecs, MonitoringData
### 배포
- **Docker**: 컨테이너화
- **Nginx**: 리버스 프록시 (옵션)
## 📅 개발 로드맵
### Phase 1: 기본 프레임워크 구축 (1-2일)
- [ ] Flask 애플리케이션 기본 구조 생성
- [ ] SQLAlchemy 모델 연동 (기존 모델 재사용)
- [ ] Bootstrap 기반 기본 템플릿 구성
- [ ] 라우팅 구조 설계
### Phase 2: 핵심 기능 구현 (3-4일)
- [ ] 메인 대시보드 구현
- [ ] 약국 관리 CRUD 기능
- [ ] 머신 관리 고도화 (하드웨어 정보 포함)
- [ ] 사용자 관리 확장 (약국 정보 연동)
### Phase 3: 실시간 기능 (2-3일)
- [ ] 모니터링 데이터 수집 시스템
- [ ] 실시간 차트 및 알림
- [ ] WebSocket 기반 라이브 업데이트
- [ ] Proxmox API 연동
### Phase 4: 통합 및 최적화 (2-3일)
- [ ] 기존 Headplane과 데이터 동기화 테스트
- [ ] Docker 컨테이너화
- [ ] 성능 최적화
- [ ] 사용자 테스트 및 피드백 반영
### Phase 5: 배포 및 운영 (1-2일)
- [ ] Docker Compose 통합 구성
- [ ] 프로덕션 배포
- [ ] 모니터링 및 로깅 설정
- [ ] 사용자 교육 자료 작성
## 💰 예상 리소스
### 개발 시간
- **총 개발 기간**: 8-12일
- **개발자**: 1명 (풀타임)
- **일일 작업량**: 6-8시간
### 기술적 요구사항
- **Python 3.8+**
- **메모리**: 최소 512MB (Flask 앱)
- **디스크**: 추가 100MB (정적 파일 포함)
## 🚀 시작하기
### 1단계: 개발 환경 준비
```bash
# Flask 프로젝트 디렉터리 생성
mkdir farmq-admin
cd farmq-admin
# Python 가상환경 생성
python3 -m venv flask-venv
source flask-venv/bin/activate
# 필수 패키지 설치
pip install flask sqlalchemy jinja2 flask-login apscheduler
```
### 2단계: 기본 구조 생성
```bash
# 프로젝트 구조 생성
mkdir -p {routes,templates,static/{css,js,img},utils,models}
touch app.py config.py requirements.txt
```
### 3단계: 첫 번째 구현
- 기본 Flask 앱 생성
- SQLAlchemy 연동
- 간단한 대시보드 페이지
## 🎯 성공 지표
### 기능적 목표
- [ ] 100개 약국 데이터 완벽 관리
- [ ] 실시간 모니터링 정확도 95% 이상
- [ ] 기존 Headplane과 데이터 100% 동기화
- [ ] 페이지 로딩 시간 2초 이내
### 사용성 목표
- [ ] 관리 업무 효율성 70% 향상
- [ ] 모바일 접근성 완벽 지원
- [ ] 한국어 UI 100% 완성
- [ ] 사용자 만족도 4.8/5.0 이상
이제 이 계획을 바탕으로 Flask 관리자 페이지 개발을 시작하시겠습니까?
---
**📅 작성일**: 2025-09-09
**👤 작성자**: Claude Code Assistant
**🎯 목표**: Headplane UI 고도화를 위한 Flask 기반 관리자 시스템