From bf87175f515287fd25d175843915ffa6178025eb Mon Sep 17 00:00:00 2001 From: Wind Date: Tue, 10 Feb 2026 12:23:22 +0900 Subject: [PATCH] AssetPilot OrangePi 5 Pluse Server-First Commit --- .TemporaryDocument/DOCKER_QUICKSTART.md | 227 ++++++++++ .TemporaryDocument/MIGRATION_GUIDE.md | 368 +++++++++++++++ .TemporaryDocument/QUICKSTART.md | 126 ++++++ .TemporaryDocument/asset_pilot_docker.tar.gz | Bin 0 -> 19909 bytes .../asset_pilot_orangepi.tar.gz | Bin 0 -> 17667 bytes .TemporaryDocument/assetpilot.ico | Bin 0 -> 237700 bytes .TemporaryDocument/claude.md | 130 ++++++ .TemporaryDocument/필요 Linux명령들 모음.md | 21 + .gitignore | 4 + asset_pilot_docker/.gitignore | 59 +++ asset_pilot_docker/.venv/bin/Activate.ps1 | 247 ++++++++++ asset_pilot_docker/.venv/bin/activate | 70 +++ asset_pilot_docker/.venv/bin/activate.csh | 27 ++ asset_pilot_docker/.venv/bin/activate.fish | 69 +++ asset_pilot_docker/.venv/bin/dotenv | 8 + asset_pilot_docker/.venv/bin/normalizer | 8 + asset_pilot_docker/.venv/bin/pip | 8 + asset_pilot_docker/.venv/bin/pip3 | 8 + asset_pilot_docker/.venv/bin/pip3.12 | 8 + asset_pilot_docker/.venv/bin/python | 1 + asset_pilot_docker/.venv/bin/python3 | 1 + asset_pilot_docker/.venv/bin/python3.12 | 1 + asset_pilot_docker/.venv/bin/uvicorn | 8 + asset_pilot_docker/.venv/bin/watchfiles | 8 + asset_pilot_docker/.venv/bin/websockets | 8 + .../site/python3.12/greenlet/greenlet.h | 164 +++++++ asset_pilot_docker/.venv/lib64 | 1 + asset_pilot_docker/.venv/pyvenv.cfg | 5 + asset_pilot_docker/DOCKER_GUIDE.md | 420 ++++++++++++++++++ asset_pilot_docker/Dockerfile | 34 ++ asset_pilot_docker/README.md | 159 +++++++ asset_pilot_docker/app/calculator.py | 59 +++ asset_pilot_docker/app/database.py | 29 ++ asset_pilot_docker/app/fetcher.py | 113 +++++ asset_pilot_docker/app/fetcher.py.claude | 142 ++++++ asset_pilot_docker/app/models.py | 55 +++ asset_pilot_docker/docker-compose.yml | 67 +++ asset_pilot_docker/import_csv.py | 74 +++ asset_pilot_docker/init_db.py | 128 ++++++ asset_pilot_docker/main.py | 268 +++++++++++ asset_pilot_docker/requirements.txt | 12 + asset_pilot_docker/start.sh | 117 +++++ asset_pilot_docker/static/css/style.css | 353 +++++++++++++++ asset_pilot_docker/static/js/app.js | 309 +++++++++++++ asset_pilot_docker/templates/index.html | 136 ++++++ 45 files changed, 4060 insertions(+) create mode 100644 .TemporaryDocument/DOCKER_QUICKSTART.md create mode 100644 .TemporaryDocument/MIGRATION_GUIDE.md create mode 100644 .TemporaryDocument/QUICKSTART.md create mode 100644 .TemporaryDocument/asset_pilot_docker.tar.gz create mode 100644 .TemporaryDocument/asset_pilot_orangepi.tar.gz create mode 100644 .TemporaryDocument/assetpilot.ico create mode 100644 .TemporaryDocument/claude.md create mode 100644 .TemporaryDocument/필요 Linux명령들 모음.md create mode 100644 .gitignore create mode 100644 asset_pilot_docker/.gitignore create mode 100644 asset_pilot_docker/.venv/bin/Activate.ps1 create mode 100644 asset_pilot_docker/.venv/bin/activate create mode 100644 asset_pilot_docker/.venv/bin/activate.csh create mode 100644 asset_pilot_docker/.venv/bin/activate.fish create mode 100755 asset_pilot_docker/.venv/bin/dotenv create mode 100755 asset_pilot_docker/.venv/bin/normalizer create mode 100755 asset_pilot_docker/.venv/bin/pip create mode 100755 asset_pilot_docker/.venv/bin/pip3 create mode 100755 asset_pilot_docker/.venv/bin/pip3.12 create mode 120000 asset_pilot_docker/.venv/bin/python create mode 120000 asset_pilot_docker/.venv/bin/python3 create mode 120000 asset_pilot_docker/.venv/bin/python3.12 create mode 100755 asset_pilot_docker/.venv/bin/uvicorn create mode 100755 asset_pilot_docker/.venv/bin/watchfiles create mode 100755 asset_pilot_docker/.venv/bin/websockets create mode 100644 asset_pilot_docker/.venv/include/site/python3.12/greenlet/greenlet.h create mode 120000 asset_pilot_docker/.venv/lib64 create mode 100644 asset_pilot_docker/.venv/pyvenv.cfg create mode 100644 asset_pilot_docker/DOCKER_GUIDE.md create mode 100644 asset_pilot_docker/Dockerfile create mode 100644 asset_pilot_docker/README.md create mode 100644 asset_pilot_docker/app/calculator.py create mode 100644 asset_pilot_docker/app/database.py create mode 100644 asset_pilot_docker/app/fetcher.py create mode 100644 asset_pilot_docker/app/fetcher.py.claude create mode 100644 asset_pilot_docker/app/models.py create mode 100644 asset_pilot_docker/docker-compose.yml create mode 100755 asset_pilot_docker/import_csv.py create mode 100755 asset_pilot_docker/init_db.py create mode 100644 asset_pilot_docker/main.py create mode 100644 asset_pilot_docker/requirements.txt create mode 100755 asset_pilot_docker/start.sh create mode 100644 asset_pilot_docker/static/css/style.css create mode 100644 asset_pilot_docker/static/js/app.js create mode 100644 asset_pilot_docker/templates/index.html diff --git a/.TemporaryDocument/DOCKER_QUICKSTART.md b/.TemporaryDocument/DOCKER_QUICKSTART.md new file mode 100644 index 0000000..0004e58 --- /dev/null +++ b/.TemporaryDocument/DOCKER_QUICKSTART.md @@ -0,0 +1,227 @@ +# 🐳 Asset Pilot Docker 빠른 시작 + +## 1️⃣ 파일 전송 (Orange Pi로) + +```bash +# Windows PowerShell 또는 Linux/Mac 터미널에서 +scp asset_pilot_docker.tar.gz orangepi@192.168.1.100:~/ +``` + +--- + +## 2️⃣ Orange Pi에서 설치 + +```bash +# SSH 접속 +ssh orangepi@192.168.1.100 + +# 압축 해제 +tar -xzf asset_pilot_docker.tar.gz +cd asset_pilot_docker + +# 자동 설치 (Docker가 없으면 자동으로 설치함) +bash start.sh +``` + +**설치 스크립트가 자동으로 처리:** +- ✅ Docker 설치 확인 및 설치 +- ✅ 비밀번호 설정 +- ✅ 컨테이너 빌드 및 실행 +- ✅ 데이터베이스 초기화 + +--- + +## 3️⃣ 접속 + +``` +http://[Orange_Pi_IP]:8000 +``` + +예: `http://192.168.1.100:8000` + +--- + +## 📦 Docker 컨테이너 구조 + +``` +┌─────────────────────────────────────────┐ +│ Orange Pi 5 Plus (Ubuntu) │ +│ │ +│ ┌──────────────────────────────────┐ │ +│ │ Docker Network │ │ +│ │ │ │ +│ │ ┌────────────┐ ┌────────────┐ │ │ +│ │ │ PostgreSQL │ │ App │ │ │ +│ │ │ Container │ │ Container │ │ │ +│ │ │ │ │ │ │ │ +│ │ │ Port 5432 │←→│ FastAPI │ │ │ +│ │ │ │ │ Port 8000 │ │ │ +│ │ └────────────┘ └────────────┘ │ │ +│ │ ↓ ↓ │ │ +│ │ [Volume] [Volume] │ │ +│ │ postgres_data app_logs │ │ +│ └──────────────────────────────────┘ │ +│ ↑ │ +│ Port 8000 (외부 접근) │ +└─────────────────────────────────────────┘ +``` + +--- + +## 🔧 주요 명령어 + +### 컨테이너 관리 +```bash +# 전체 시작 +docker compose up -d + +# 전체 중지 +docker compose down + +# 상태 확인 +docker compose ps + +# 로그 보기 (실시간) +docker compose logs -f +``` + +### 특정 컨테이너만 제어 +```bash +# 앱만 재시작 +docker compose restart app + +# DB만 재시작 +docker compose restart postgres + +# 앱 로그만 보기 +docker compose logs -f app +``` + +--- + +## 💾 Windows 데이터 가져오기 + +기존 `user_assets.csv` 파일이 있다면: + +```bash +# 1. CSV 파일을 컨테이너로 복사 +docker cp user_assets.csv asset_pilot_app:/app/ + +# 2. 가져오기 실행 +docker compose exec app python import_csv.py user_assets.csv +``` + +--- + +## 🔄 백업 및 복원 + +### 백업 생성 +```bash +# 데이터베이스 백업 +docker compose exec postgres pg_dump -U asset_user asset_pilot > backup_$(date +%Y%m%d).sql +``` + +### 백업 복원 +```bash +# 백업 파일 복원 +cat backup_20260210.sql | docker compose exec -T postgres psql -U asset_user -d asset_pilot +``` + +--- + +## 🛠️ 문제 해결 + +### 컨테이너가 시작되지 않음 +```bash +# 로그 확인 +docker compose logs + +# 특정 서비스 로그 +docker compose logs app +docker compose logs postgres +``` + +### Docker가 설치되지 않음 +```bash +# Docker 자동 설치 +curl -fsSL https://get.docker.com -o get-docker.sh +sudo sh get-docker.sh +sudo usermod -aG docker $USER +newgrp docker # 또는 로그아웃 후 재로그인 +``` + +### 포트가 이미 사용 중 +```bash +# docker-compose.yml 파일 편집 +nano docker-compose.yml + +# ports 섹션 수정 +# "8001:8000" # 8000 대신 8001 사용 +``` + +--- + +## 🗑️ 완전 삭제 + +```bash +# 컨테이너 + 볼륨 모두 삭제 +docker compose down -v + +# 이미지도 삭제 +docker rmi asset_pilot_docker-app postgres:16-alpine +``` + +--- + +## 📱 모바일/태블릿 접속 + +1. 같은 Wi-Fi에 연결 +2. 브라우저에서 `http://[IP]:8000` 접속 +3. **홈 화면에 추가** → 앱처럼 사용! + +--- + +## 🔐 보안 팁 + +```bash +# .env 파일 권한 설정 +chmod 600 .env + +# 방화벽 설정 +sudo ufw allow 8000/tcp +sudo ufw enable + +# PostgreSQL 외부 접근 차단 (기본값 유지) +# docker-compose.yml에서 5432 포트를 127.0.0.1:5432:5432로 변경 +``` + +--- + +## ✅ 설치 확인 체크리스트 + +- [ ] Docker 설치됨 (`docker --version`) +- [ ] 프로젝트 압축 해제됨 +- [ ] `.env` 파일 비밀번호 설정됨 +- [ ] `docker compose up -d` 실행됨 +- [ ] 컨테이너 실행 중 (`docker compose ps`) +- [ ] DB 초기화 완료 +- [ ] 웹 접속 가능 (`http://[IP]:8000`) + +--- + +## 🎯 장점 요약 + +| 기능 | 일반 설치 | Docker 설치 | +|------|----------|------------| +| 설치 복잡도 | 중간 | 매우 쉬움 | +| 환경 격리 | 없음 | 완벽 | +| 백업/복원 | 수동 | 간단 | +| 업데이트 | 복잡 | 쉬움 | +| 이식성 | 낮음 | 높음 | +| 롤백 | 어려움 | 쉬움 | + +--- + +**모든 준비 완료! 투자 모니터링을 시작하세요! 💰** + +상세한 내용은 `DOCKER_GUIDE.md` 참조 diff --git a/.TemporaryDocument/MIGRATION_GUIDE.md b/.TemporaryDocument/MIGRATION_GUIDE.md new file mode 100644 index 0000000..405bedd --- /dev/null +++ b/.TemporaryDocument/MIGRATION_GUIDE.md @@ -0,0 +1,368 @@ +# Asset Pilot - Windows → Orange Pi 5 Plus 전환 가이드 + +## 📋 개요 + +**목적**: Windows PyQt5 데스크톱 애플리케이션을 Orange Pi 5 Plus (Ubuntu 24.04) 기반 웹 애플리케이션으로 전환 + +**주요 변경사항**: +- PyQt5 GUI → FastAPI + HTML/JavaScript 웹 인터페이스 +- CSV 파일 저장 → PostgreSQL 데이터베이스 +- Windows 토스트 알림 → 웹 푸시 알림 (선택적) +- 로컬 실행 → 네트워크 기반 접근 가능 + +--- + +## 🔧 시스템 요구사항 + +### 하드웨어 +- Orange Pi 5 Plus (ARM64 아키텍처) +- 최소 2GB RAM (4GB 권장) +- 최소 8GB 저장공간 + +### 소프트웨어 +- Ubuntu 24.04 LTS (Joshua Riek 버전) +- PostgreSQL 14+ +- Python 3.10+ +- Nginx (선택적, 프로덕션 배포용) + +--- + +## 📦 설치 단계 + +### 1단계: 시스템 패키지 설치 + +```bash +# 시스템 업데이트 +sudo apt update && sudo apt upgrade -y + +# PostgreSQL 설치 +sudo apt install -y postgresql postgresql-contrib + +# Python 및 개발 도구 설치 +sudo apt install -y python3 python3-pip python3-venv python3-dev +sudo apt install -y build-essential libpq-dev + +# Nginx 설치 (선택적) +sudo apt install -y nginx +``` + +### 2단계: PostgreSQL 설정 + +```bash +# PostgreSQL 서비스 시작 +sudo systemctl start postgresql +sudo systemctl enable postgresql + +# 데이터베이스 및 사용자 생성 +sudo -u postgres psql << EOF +CREATE DATABASE asset_pilot; +CREATE USER asset_user WITH ENCRYPTED PASSWORD 'your_secure_password'; +GRANT ALL PRIVILEGES ON DATABASE asset_pilot TO asset_user; +\q +EOF +``` + +### 3단계: 애플리케이션 설치 + +```bash +# 작업 디렉토리 생성 +mkdir -p ~/asset_pilot_web +cd ~/asset_pilot_web + +# 제공된 파일 압축 해제 +unzip asset_pilot_orangepi.zip +cd asset_pilot_orangepi + +# Python 가상환경 생성 +python3 -m venv venv +source venv/bin/activate + +# 의존성 패키지 설치 +pip install --upgrade pip +pip install -r requirements.txt +``` + +### 4단계: 환경 변수 설정 + +`.env` 파일 생성: + +```bash +cat > .env << 'EOF' +# 데이터베이스 설정 +DATABASE_URL=postgresql://asset_user:your_secure_password@localhost/asset_pilot + +# 서버 설정 +APP_HOST=0.0.0.0 +APP_PORT=8000 +DEBUG=False + +# 데이터 수집 간격 (초) +FETCH_INTERVAL=5 +EOF +``` + +### 5단계: 데이터베이스 초기화 + +```bash +# 가상환경 활성화 상태에서 +python init_db.py +``` + +### 6단계: 서비스 등록 (자동 실행) + +```bash +# systemd 서비스 파일 복사 +sudo cp asset_pilot.service /etc/systemd/system/ + +# 서비스 파일 편집 (경로 확인) +sudo nano /etc/systemd/system/asset_pilot.service + +# 서비스 활성화 +sudo systemctl daemon-reload +sudo systemctl enable asset_pilot.service +sudo systemctl start asset_pilot.service + +# 상태 확인 +sudo systemctl status asset_pilot.service +``` + +--- + +## 🌐 웹 인터페이스 접근 + +### 로컬 네트워크에서 접근 + +1. Orange Pi의 IP 주소 확인: + ```bash + ip addr show | grep inet + ``` + +2. 웹 브라우저에서 접속: + ``` + http://[Orange_Pi_IP]:8000 + ``` + 예: `http://192.168.1.100:8000` + +### Nginx 리버스 프록시 설정 (선택적) + +프로덕션 환경에서는 Nginx를 통한 접근 권장: + +```bash +sudo nano /etc/nginx/sites-available/asset_pilot +``` + +다음 내용 입력: + +```nginx +server { + listen 80; + server_name your_domain_or_ip; + + location / { + proxy_pass http://127.0.0.1:8000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location /api/stream { + proxy_pass http://127.0.0.1:8000/api/stream; + proxy_http_version 1.1; + proxy_set_header Connection ""; + proxy_buffering off; + proxy_cache off; + } +} +``` + +활성화: + +```bash +sudo ln -s /etc/nginx/sites-available/asset_pilot /etc/nginx/sites-enabled/ +sudo nginx -t +sudo systemctl restart nginx +``` + +--- + +## 📊 데이터 마이그레이션 + +### Windows 앱에서 데이터 내보내기 + +기존 Windows 앱의 `user_assets.csv` 파일을 Orange Pi로 복사: + +```bash +# Windows에서 SCP로 전송 (예시) +scp user_assets.csv orangepi@192.168.1.100:~/asset_pilot_web/ +``` + +### 데이터 가져오기 + +```bash +cd ~/asset_pilot_web/asset_pilot_orangepi +source venv/bin/activate +python import_csv.py ../user_assets.csv +``` + +--- + +## 🔍 모니터링 및 관리 + +### 로그 확인 + +```bash +# 실시간 로그 보기 +sudo journalctl -u asset_pilot.service -f + +# 최근 100줄 로그 +sudo journalctl -u asset_pilot.service -n 100 +``` + +### 서비스 관리 + +```bash +# 시작 +sudo systemctl start asset_pilot.service + +# 중지 +sudo systemctl stop asset_pilot.service + +# 재시작 +sudo systemctl restart asset_pilot.service + +# 상태 확인 +sudo systemctl status asset_pilot.service +``` + +### 데이터베이스 백업 + +```bash +# 백업 생성 +pg_dump -U asset_user -h localhost asset_pilot > backup_$(date +%Y%m%d).sql + +# 복원 +psql -U asset_user -h localhost asset_pilot < backup_20260210.sql +``` + +--- + +## 🔐 보안 권장사항 + +1. **방화벽 설정**: + ```bash + sudo ufw allow 8000/tcp # 또는 Nginx 사용 시 80/tcp + sudo ufw enable + ``` + +2. **PostgreSQL 외부 접근 차단**: 기본 설정 유지 (localhost만 허용) + +3. **강력한 비밀번호 사용**: `.env` 파일의 데이터베이스 비밀번호 변경 + +4. **HTTPS 설정** (선택적): + - Let's Encrypt 인증서 사용 + - Nginx SSL 설정 + +--- + +## 🆘 문제 해결 + +### 서비스가 시작되지 않음 + +```bash +# 로그 확인 +sudo journalctl -u asset_pilot.service -n 50 + +# 수동 실행으로 오류 확인 +cd ~/asset_pilot_web/asset_pilot_orangepi +source venv/bin/activate +python main.py +``` + +### 데이터베이스 연결 오류 + +```bash +# PostgreSQL 상태 확인 +sudo systemctl status postgresql + +# 연결 테스트 +psql -U asset_user -h localhost -d asset_pilot +``` + +### 포트 충돌 + +```bash +# 8000번 포트 사용 중인 프로세스 확인 +sudo lsof -i :8000 +``` + +--- + +## 📱 모바일 접근 + +### 홈 화면에 추가 (PWA 스타일) + +1. 모바일 브라우저에서 접속 +2. 브라우저 메뉴 → "홈 화면에 추가" +3. 앱처럼 사용 가능 + +--- + +## 🔄 업데이트 절차 + +```bash +cd ~/asset_pilot_web/asset_pilot_orangepi +source venv/bin/activate + +# 최신 코드 적용 +git pull # 또는 새 파일 복사 + +# 의존성 업데이트 +pip install -r requirements.txt --upgrade + +# 데이터베이스 마이그레이션 (필요시) +python migrate_db.py + +# 서비스 재시작 +sudo systemctl restart asset_pilot.service +``` + +--- + +## 📞 지원 + +문제 발생 시: +1. 로그 확인: `sudo journalctl -u asset_pilot.service -n 100` +2. 데이터베이스 상태 확인: `sudo systemctl status postgresql` +3. 네트워크 연결 확인: `ping 8.8.8.8` + +--- + +## 🎯 주요 차이점 요약 + +| 기능 | Windows 앱 | Orange Pi 웹앱 | +|------|-----------|---------------| +| UI | PyQt5 | HTML/JavaScript | +| 저장소 | CSV 파일 | PostgreSQL | +| 접근성 | 로컬 실행 | 네트워크 접근 | +| 알림 | Windows 토스트 | 브라우저 알림 | +| 멀티 기기 | 불가 | 가능 | +| 자동 시작 | Windows 작업 스케줄러 | systemd | + +--- + +## ✅ 체크리스트 + +설치 완료 확인: +- [ ] PostgreSQL 설치 및 실행 +- [ ] 데이터베이스 생성 +- [ ] Python 가상환경 생성 +- [ ] 의존성 패키지 설치 +- [ ] 환경 변수 설정 +- [ ] 데이터베이스 초기화 +- [ ] 서비스 등록 및 시작 +- [ ] 웹 브라우저 접속 확인 +- [ ] 데이터 수집 동작 확인 +- [ ] 기존 데이터 마이그레이션 (선택적) + +모든 항목 완료 시 시스템 사용 준비 완료! 🎉 diff --git a/.TemporaryDocument/QUICKSTART.md b/.TemporaryDocument/QUICKSTART.md new file mode 100644 index 0000000..db88adc --- /dev/null +++ b/.TemporaryDocument/QUICKSTART.md @@ -0,0 +1,126 @@ +# Asset Pilot - Orange Pi 빠른 시작 가이드 + +## 🚀 5분 안에 시작하기 + +### 1️⃣ 파일 전송 + +Orange Pi에 `asset_pilot_orangepi.tar.gz` 파일을 전송: + +```bash +# Windows에서 (PowerShell) +scp asset_pilot_orangepi.tar.gz orangepi@192.168.1.100:~/ + +# Linux/Mac에서 +scp asset_pilot_orangepi.tar.gz orangepi@192.168.1.100:~/ +``` + +### 2️⃣ Orange Pi에서 설치 + +```bash +# SSH 접속 +ssh orangepi@192.168.1.100 + +# 압축 해제 +tar -xzf asset_pilot_orangepi.tar.gz +cd asset_pilot_orangepi + +# 자동 설치 스크립트 실행 +bash install.sh +``` + +스크립트가 다음을 자동으로 처리합니다: +- PostgreSQL 설치 및 설정 +- Python 가상환경 생성 +- 필요한 패키지 설치 +- 데이터베이스 초기화 +- 서비스 등록 + +### 3️⃣ 접속 + +웹 브라우저에서: +``` +http://[Orange_Pi_IP]:8000 +``` + +예: `http://192.168.1.100:8000` + +--- + +## 📱 스마트폰에서 접속 + +1. 같은 Wi-Fi 네트워크에 연결 +2. 브라우저에서 `http://[IP]:8000` 접속 +3. "홈 화면에 추가" → 앱처럼 사용! + +--- + +## 🔧 주요 명령어 + +```bash +# 서비스 상태 확인 +sudo systemctl status asset_pilot + +# 로그 실시간 보기 +sudo journalctl -u asset_pilot -f + +# 서비스 재시작 +sudo systemctl restart asset_pilot + +# 서비스 중지 +sudo systemctl stop asset_pilot +``` + +--- + +## 📊 Windows 데이터 가져오기 + +기존 `user_assets.csv` 파일이 있다면: + +```bash +# CSV 파일을 Orange Pi로 복사 +scp user_assets.csv orangepi@192.168.1.100:~/ + +# Orange Pi에서 가져오기 +cd ~/asset_pilot_orangepi +source venv/bin/activate +python import_csv.py ../user_assets.csv +``` + +--- + +## ❓ 문제 해결 + +### 접속이 안 될 때 + +1. 서비스 확인: + ```bash + sudo systemctl status asset_pilot + ``` + +2. 방화벽 확인: + ```bash + sudo ufw allow 8000/tcp + ``` + +3. IP 주소 확인: + ```bash + ip addr show + ``` + +### 데이터가 수집되지 않을 때 + +로그 확인: +```bash +sudo journalctl -u asset_pilot -n 100 +``` + +--- + +## 📚 더 자세한 정보 + +- **전체 가이드**: MIGRATION_GUIDE.md +- **프로젝트 문서**: README.md (프로젝트 내) + +--- + +**준비 완료! 이제 자산을 모니터링하세요! 💰** diff --git a/.TemporaryDocument/asset_pilot_docker.tar.gz b/.TemporaryDocument/asset_pilot_docker.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..2ab56e705ad91bb07706922ca5f68ac8b1e9e29c GIT binary patch literal 19909 zcmV(*K;FL}iwFP!000001MEC&bKBN(`OIH&0{4!{lmtmp50}?WBfk-V8X!zpLA36bmKG%W`oiz7Kv zX~-&Nr8P}8MR?H#Rjfm`h~`yU6#xQZm}Syb6>1nc!_*oLDzP%E&dIu_)~RYbtr2qe z%*5o|<0mGB<3}UtI*ZRuoEY~iG@*l?I->C!?c^r`nwO#;-|_}dd@!sT*Qt!a|1PFK!Np3EI4xtyZaM1@w4aSU=!Q<`;; zV}#^ z&1DJKm=Oe_N?#@D0!I_c=j*!{p^`>_p2Ibt3Cr?Zsdk4nHDYR~~=uK*v$Lfqe@8%}wF|Gp5-9rn9j<1Ds?% z$U9gP6ucBy@IdE%4KKMLm{ti5s>_;GCPPp$73yr%U^vRA%V5aMgpuQ@zthQt(o~qk z3A~NMRCQUJrm5e0nmTxXr6|BJC3H{r$FTC&$##0HDpdfZ-K*?ziC0G;)8D+Ko43u1rr(!O`Cz5K|!v1r}6&ogS| zI!+wKm^Zwinvt5)wK`1VCX()cRWwl&oKH?M%#NZ0hP^)TRjGlGVp4&s)99OaRN^(g z?o~8kQis{OF2b-#r4Ety-IeVpFNyW^s=c^^(~Wg|H5F)a!#Qv|P?aiwx=nUTw%^6-+VcIs+g)DT+`69_W`Wi{Y{QpA1b+ zr6f8<9OK}Eq%+QB0rKgkEGRxU^Xo7nrn$d-v-BWAPr}M|W7WR*CC~GmGjFs1z{w3f zr$fZPvt&Q;l*#|@$dpu~GERs4lqIw_qg5vLCe8S8A;i9}cH(x)|4{wQH@9!ZsuBBs zh+=$D41ArMBC?Bj2@(}04TDXpIFw~NvH!e!Edll2mh~SuxkPg9))u(DowQCkntK{& zeBee{k<((+)F8O8%VveSYgvL{rj({J<9$e^P^to^FyeFqK@lmr6yCdKf3iue2a9Ml zTAP9F1Cd8S!i>JYBk(x$@nLhD<0b*+=ObnKq`42q&gIWdF!yeIYcX%#*s#9YU~fNN zg%9?ppL3aP7r0~Z{mFxa!EG-u?hx+nqh~$1_RX92SI@wR>;M$V%pd=NHR+IPuWebM zKL(!QC$LQR>cj4k?~cD8K<4eQZ}kH@I(f|FjP<+)M&5o2#(OKoB71qMy|M+&Z+~&C zI}WemFb=o*{s`V3{~-VNX-_<)z0$HaUhI&~Zo^DGPJ3N}E=1lUFH@QhQ%=3ADOrN{ zI7@0Uil;RlCKENRVC5JY^s;QAr3KXkXX;{;>ho!4h%-Exa0m>XH{L-{DiyaOEY=M( zorz(Tr-%wcuZK9^BtDELXpxoZsCYl(?coEYi;|RPSd(iwqjicStS9rYasUr+rnyb~?R z5^5{^&CAj&>MJHJ1W#%GmePrJeHH)-6|eoc0SLHG=VYyE2sK4BXr<7-rU|yki%n5AWpln#NUYLx31;cTaakO2D@e<~h&#c>zt+kiJ_U0}7!BwtI9N(!| zRr_9R`)O-?^IxHMiBC{7&idg|`^!~`F6^}*t?$FwG~|ja6UhE><*GvvfX7=0v4Q(PnkZftO8MH@uJ|{3On_p;#xF za6=z?7q0-VqB(;_euf4RK+2WI&*? zg)+IqurB;^D}iYC)(~_XjeW;{XjK2pXMI9QhU|4Nk%|vh>&AV1?Iwij*R1vD_Ua23 zl($x`CoLANv-q>Uyn?~iS4-t&EX2*0kh&F({o2ygnYtTDV+dBFV|?p zBq!J(2)1C(BOyt7()m#R8MtE9dBZ2JjV-pxnW zljU-}Vv!Fm`2kOX6ZhNy_8A&VaNNOUkoMhW_?5^SpDn~_N*ZQrV8GT)1=HDP(+I6r zBvClXCkPY_iW}Klw^r;si`Mm}-4T&%`puFCv`lg}GVtMt%0LncC7$q@Ny4yf?S;Lz z63K-ycC2hzn@iSrNvsHA#JmpJ3Nu~Iq*7oz1h$4G2xw$syh9`0-qu%z~Si)=r;iYv2sZh>(nV1ewr!GL)^6y92qWk$bV#T@WB4>%i}Ka=oG>x!*o~F%=rceGTwraTr;!e40Ay>hWyngDmG1ds;Nw9&4#yNgu5J4shR@nMUI1WbJEeLV7Um_$JV_}fD<r zN!lMjv+k{6V%uFeayBGT^rM)!BtRIXOoakLeC6FW4hX-z&hYMHMaahv*W_oYC{f+u zn+@>4XgV6@4`41TH#SXGbD&HH{-Av%D~gyO<_jeKzN|{xC4;;-$)fGw6ZkMP^m}r7 zWGF+%8V!ZMPpj|BW`4Ld%9ln4e8dYKl*sBFWf7%N6M;XNYFLQYVBZB~Clm%rC!Zy3 zpb8;8TAgtx>n6%-nncUsf$JHPd(#)<`6)#c%?kksfz_ux92mg4Gj>EUo;dJ11Vt_D z#zS1wwEz2-ed94n4@2}7^bg!#q?*V7($ILUJ4eVc5mhNfCr15AY>7rrIyIYma>erj zt_x9C;o}t6#YQZnDeBT2=$s)NwOg&4HAa>I}hjs{Fz z=td(ZSOaqTX=QUzF&dg`P_`Hu8iUw3Xgurf zi>eG~65)7Vlnp9OY2YNXa55=y_8tQ)5i}IBOlcnzZUF=umCJQyAQsrys6Z83M=}8j z$W&;}6o858f%6!p<#1P6g_BhnQcc{Mmt#OVuyiJOVW0<5Agus@Jn!O^A#KohP?1r~ zLt}Cy%;hX{c_5zCVSp$}9N*~xXS`;=@#9eu19TNDTG%IL;gZJE77;t+*?i11+;B{oa+GkXxvV{+@0EsS>DRnJM+@P#d2mm%Yi7_lMq zZo_Q6zO!aRcOds>qbi#_le&H9nzJNL z+(qhNC~?*#llNTFmGv)`a$VGCscE2?fu0=DwXb4k0xn!Q&zU-SMS?476g0zuGj*iM zlRLn?n&{6V3tv(2h9u1Dmv$z4cRK`ecR%bx;1`=3@E8#1K=iqqgn4^atT#RRgB0lH zyiRK{E&M&2Fr#vE`~w~uL*HUwr^8<$cg#PY?U4Gb3D#wF#Kivs>CWnxg=tNZb|zl% zNVk9d^Y-ISj3GX~NrH_dyBy-K7lbW0bPzE=tLLZdM&4bQ;zgse$1?R!jsSuI+N|Yf z^?^vmJ@IiOFNfmnVd*_|=W)Gu?HQWL?H@PnZ#OZ;XDw}7YcB}CtuK@Ia?Ac|X*VvE zDOME^Xqf#J};yAd$olQ6$(!K2>hvTaeW6oC|v{|Ds_W* z0{;$pP`?N~R7!#mG6NxaR}mxdr&NhvP6Wqojxlh?$q+bJ>IC*Sct(I-J?-S(WFmB| zX;*#wHtlWei~xHI+zFkZPGozmaaYxPgC}HMJoAh@6XGV1?IOT)WRJI>{s`?E&3d}X zHml5`1MF%h&-Pe=4~Bzc?)-p5)WC(zLjLbEA#34Ua~Fy&Y^}HKJAWp)xQ-hU*|AzT z_YUeF%AEdME5lv#|IUGeJvsu^XZ?4mINEvsXQVJvILQC+$J6DA%rQJ}sAkD2)uhuD zT#5^u$nU=pn<5a*imoPW$D^hvV9GfuI96;D8X)2yl5rO>&aL%2x*9252u?2$EC_!`I^yf1HaFqb7& zu{J9-v_=yuK$z`F!?m=IpFSfSrqjJB78c^Z;}rHlQ(f!c@Hg}ABqATzPrVuz+t-Y}S{Td!!V|0XfP4@xE zgH>OAw*Aw(_29mJ&qv|yr|t($98Cch+pFu=H=jAm!q)9}sd-tVsSe;yb<*3M9@V36 zni!U}uSQ{|>(C@G>b}QJ&!_9w_Z#7J>s>V}qUC>0I+dggNi~u4F!$CQyAoa}-LERH zC>w)GBD{mQW9WysuXdjv5P`pUc@L(E@NVTqBj01Ph@xBLYkK=`DNhM=z)aINa49r7m!<43x77ldKc+R8&JFt<*Hb^isjm@k8E-j+p3z zgsMcKd>{M`l6F=)!cF4Vttj%?>J>=ld`J=({B*C^QY5YGb;~FIO;U(2>BP|fE`--d zO!6T-ZxF{38ca-qgE;&17>9S9#qbrHju;teENoU{{0%_5a~DdHxe>g{ybTmJ%3A>K z%37qLCuc+Y-N9J|%?DU|^A$9`3tzp4f{}8;S(1+F%ikvT)W>6Lrl<%=4uGe7D|!ZS zrF%&#x&3K48u&MMguD2E-hre&$pH89|B9uNSpK(E8a?p; z_T%ZeOKGnzOX_nmQ~c7Tgri62#!ur)wY|P&uiW3>+DwH{3XBsWMmyRcqjxC%iJ$3EtW5Mw@t0(_UR~fAx@E0d(({^~GKH%prqhw-~YT9s%(9 zmi<33Fni=)gP69KmaHeO?dR8U<(?pFjOneXSGS+M%%n2Txhi&fQ2XX1H}m9nbuX_E zV%J82paiMf=e{WSCZn|#JZ9W_?D>D)?j4G3-kFyvxB%`wvau7lq0_d%^?>^;d%E2J zmy@b{cLr=%=f7~CC=QK|77xyU?Z=ZKf0Nc5EIYba8nFBGf5Stikpubf$J0~(ED6oe zn6G#Pe4q1wrNQw1?@a!q?Ee1)|L@m-j=X;S%(2NoojpNN%x|WS;2)xh;EZsy8iyaK zD80#M(j$18A*s!XI_OM=WA~eL;Uadu7&j-=OX%@&&VAb|RJ|li=1fJRc*S*&y=2+N z2ePQ-40bzukuP|tAWT!}o8fD|bN-bmjJd!*|Shlmm`PYBDRI&2^W$#&=oH&xa z&;2XPn&TMFs#}kF05T#L8@%@2u@DU2jSEbOmekUS)u?r9X&&ad0DJ7f7#qCHtT7(! z*;s7AF&jGu?1eDw{uh5lnmGT2%dAItRllTp!0lcjo0(BPv$C?Xva+%=*@M9Y$~kfW zO!mM}U;cJo_Dc?JXMLqwqG6|7qM#=Z^gp}>g4xscrNHQVw=Ym@%S*R5-dow9Zu#1h zz+}eXddZaGbPGByvq|a|w-~JFdKp!?315AX#1jYhr?GroGx*3!XBRq&13_ac>P;!E zmHlY|S;AvlAks@hpBTPMFX_6_Ec9<&>n}ecy6!9DSY>K;%SY2{0y%YO@hUA09TMKK zWZ7(2LW;3T9Y5e%MgzR#5#@YM(yO%u#TBY0bVy4a_+|Q_4*_vaw5&G1ACMd2DKQO2 zC2wxTvXjOwjk(k*Z+pnJjU62^Q_IAR+f!j}Y1Fj&ZI7F`vZay3nqvz=T2VBeE+NKT zJg2gQRuQ}7*LmuIg~UtgY(+;RId?$z|8|oQn%Bw8P5SG4hQ)ez0_&C zTnqjt@K5L0=DXv&clM`Q?V)KVc6{_&Uk}?2lp5?|1H#L(M-w7Svl`yM z8eOIxUw}7sU}O1Dy>9@Y@aHh)#n_tNS*u+y1NtP(o~^e6v)cb+ZCg$B?w{{n`E0xO zdta??V-#0D=zVx+o1@@XO513HT1oYn|1h`-C=o*@SU;A~_IFSKQb-pQVn~;M=`Bd+Vvd~m-CG%b%ASV{><&NpJu6De^zR;!T67?TMy zTW^ZL%!NWCml*;jyS9f4PKD2evY1m+;yOotp2QX5$o21&#C&+#4vG2w(T0#$mXlXD z^AAp6%%!e)P1(D$ggec1q_HrUzJHelhDT}FL-6((n9nUSCol9j%;{?qb&5lvq5t{S z=Z63^KG_ij1bi(^2=L+HIiVp=jM$8XQMK((yl5mH3LSIK(y8d?#2gB#^>XxaFs$J+ zzQ}DvH4Rdy-K?<2|8l4Q{^j__H*Q%u8U{@l}%GW@4-`HxE55OThnl6o8LXwe(zCK`WRsUli8CQ_r-t4kd!a(f1bx@ zgdC$z%(Y^%waC2l71P?7(ONuNwkxN!v43tY8kCbjqGM|YFHYmCrnQPSXEp4WZq;fI ze5*Sh_-W5K(Y^-~ShB%>VN_fEF*T9aS|;${3G0N2%%hKko<{UJQKMw!$SLr}tHVqwE(;o(pco}A11dUZnIHvz>)H{~@$2cub zEodOEVb?T_qe(k?gcp)9GWgpcVPW!CuU&p zcCaJJd3E|%9vo1o?96E|SqtWDi(X32(Vo}8?SJ|ncd^WX((uVrw?#oW}|zI*ZM6-5&7dI^qcl zORt)M-&S2@yarzn9(yB24zcjaDf0S>6USWlIVp0S`EFGz8^W!T8{zQv6G#62I8UT+ z(=8JO-n}|3INN%IXinJChXmMPY zgEAgLuL=WgBO@a-G9$Vak!>-z8~sr@o8XoCS1;dt2`L0(9xCIA7UGm#=ZdOe(fFhDi4-vn6}9mO*i3JmoM0JTCRg#S%=k7r2hqN^h= zg(gxmO^jCRZL5qgLfH*DPWhq043Y^cK_LL3eb zZ8$KbVMHjyPy+FXE{r3PO@;ZB*s|gz$24H2<#m`Hs?N9Y?EnQyp= ze8WWI8zKVVIhCnxHqzd+i?A2FV4g`ty|74nar8VWT3wWk(qI0TyUe7~^X}b3SE}K% z$B}4EW$RfUh|e9C92PL{WsghY zBY}ZO_%h`i2|eVBvq{Hvelv3o+(BeA}%?!P=c7lSv5?^D}Uop)bEYgauq43kQfN&$>QZ zn)du?5*_DOY4ncWyZ%GpHLLHckX^6mcOA*^n%2kqGN9O2uU3rJ>2hFe%r9Hcd5p_31tyQ?^PN|i)YvJe;| zm9mNkpa=%)i%8_ffiR^bgwOE=iv4a0dInJQ#W}z&BNBY&Q~^_X>W~CMLoJc?)mOyN zulwA-bKq!lV-Ffw>om?q-mfD`kzwgjb_Pf=$OL0g zmmVslIQ-#|YR$qj3ln{Y&5VKD^lb@K!=Xt8#YPp#u|)!E4qVL?n$7jt@08te)R9A+4q)hSids5z-0) z?;c^njXAxY{6g}|Ns26-(B2G+j zT}zjXreIE)-qlz((3Uw;yGuD zsINL~5%mQ&LV$1)v;BDk|ps&cT#DBc>oG) z!BcpKx4=%IP3jZabHg{tWm-y|g$UFF4r&6xP$!SA^M=ief~H>?FKpqqFM)P_Au%% z!L$&*6V7JZ4sCEKX(wh%gxKSo6)OJ(Z)%1Yfzbcz)Ha&de9?J^`YWmZ7|s3g(n;jBd9sRs!8`Qc-KVC)q~JMm8V=Z2 zTb~B5LJp$}%b{NW>b{CKs|niyutb?e!ZaOxhJClG zN;X9qyTFsMuGYZ&b_b)9n@+i2mmTWLALf6inqcb(RVn7Vx0-J?)euo(+J|hAy9Nvz zMgv1nky)!!H;c?f7=sd}X&K#}6nVC0EVI#>QD%xI6{$tJe4zhyjozl-d$4g~&3BTQ zl<6Khv33@vpr;AfvoqxTbV_x{hUGsCJF|3rV@{ZzB63fw0+kw8(>Do8bkN2%*^!sR zOhbYZm45$0gnFiqL4<{uW{|^*MYMJ*7848s+{B?fS1;S`COi1Bzm0ZRQV%4sRvz#x z4I8~l6(pZj2ag>qzJ7H21TM6Ukzoc3UUBTGplb7Im19SbW0k#`OeQH6Z(E2RxqTY# z9vi0=36dla#Y)H3ft8Tpdv~n;Pl)~3@xuoX9XV{wR(8t9Xn_6a)RgD{Z89@CPVK*P zQ!nhlp2ufI(Y)*2!cdslXxdL-UcE08`#;>__B~4%3Es)BUypZP0ZVm+{PgATzNR7M zmcG?As7yAlEn)Df)tkubFI^+Kr|T=|6}NZgz24VPdRJG%`lDKN+DPx}U3R3+Yg*PI zV`Imdvp4DiO{y_AMn+F7OJiGu=|h5&<`JCXk9kD%TvwNYB@KR%Bjy?0%O1^EF>@ixtX?i=rX z`l~BX?|;WJf8#vqJzDL3^-x@RK=O$2C5LGzlWUwj1{#_7|iOQth}R!Ymu z{qHfr-vek)!v&%*yj>+hW??{{QF~h}S3)wWy_3=xlEsBJm}M$gP)4m`m+X4WfW83+ z4&=q_UPT!;m~+M4R~U6Q&8AJL>F)?R^h)vA!RhH=A3c7E>O?-jy0Ls6X|4BYskeT< zckklH^@pA}JOmVGGK|bQ-q?T$$W|>>M0Hz4uVAflBi0tlU(Z^w%4k+cTGWb~-H?II z)>_2ICZMs0m+9TnIzC?EcSozA^xyvovUyO-lW!dB|M7AE{mZBFlqfjHaGhNs=<{#& z1MbX^#ciax(?a;X_T#mcAFrK<{}H6LU!uX!NC;h${u8_if!gmt39k*sWqcr4awrl2(MUp79LV0>~dynfrFD4=EDy|D4_itqvIE7x+omkSst2hr#&f-f0}UiEmaw}Au( z19QmUB80Lqu?><|t%zqPqQA-cKUJ$q%m(Ck_I`mrW#A3p{|=uWmd%coNB)b1^`xJW zI>TaWPr9=2h*uU0Es0iJa&RepZ$W(9a-MoV9>}s4D)u!g5z*zVf^*YE&b(c}vy^vx z)QAGn4{KUDi<|&ntuO-M)-?efk#~uef*VD+G7_E^wOOy(fIf zWO0e1SuQTx4Y)|jqMY1Ne0@4By9zA6+mM#JuE%om` zkVnLn2dq~AgSGyR2jWc@HK+ohz7vi5mILJe;TDtyQd`>i_#rPu>24*>&OE)3mZ`gC zwh6ad!??%mi*{+~t{oUP8Ro}ZiiPnTw|J57%<&(canv z*t3!_6VTeZMDRL-LEY@sn_VlA8AxE8fOtNF<~7W;24-olCN7SpyLISvaHAuxsl@tU zQ4SC7ba;~q8OGpEo`mBNv#417Mi@ceybRctJKa8-M}m(dWEmn*{#n>u`H&T6e-#cw z&=!kXSa{SDj-D8+EY^TaVgu_3tUH21ebkA;Rr|97$;K1H%I|y=o#&x$3unE-ol6ns z8M1KJ1sKv$OZnvog|h;ZFd_-w4F^Erv>0yHHJBV@4b(&@Z#7XKJxj524#ZNzyoUNV zc6!(QlE3W%M%nU4#Ev*153ls!z3Df@2Kd@`qk*S>@kT4gpnu?P9b>4tg_-TzT$1c3 zIX_U`R1S`+`S26`ez9c~ako8?@FOnKzkU%;iV?Ma0#2~@TTLzsD-ENwu>Did zApbw(6O+OCuP^R@pUa0kz9XER}BHE!>45|YtdSmhLEzQFI3P?K>VojHmq6sWTX?F{vqP$-NWStF;Jb(?zVfGXog z4&dN#Q!v38hZ42H0I)fz*jSit;Fo>IxaeoL+vwEM!w`a=F{WN{ zqUcY^`sep+JJ-hm{SW=yAO8vcf4zwR^Xxy-^N-i1JJZLe=AXrXn#}HbG5^ow6F>iM zz?^OM5x@Uu$5Gkqi~lsf=Y{{j=kgijR-LmT&exlHl6jeF0L=>O&D`%LdqH>VZ_}ib z-L6<|9g<$w&S_d6F~eKYh4)pxY&Yz7o{Z!sr^c<)%RHCc9=o~OOljZVtjMjPgQvEe zX;mlSBQodBb`za5i`?quJ}cukT#_>OR?TWzWMBXo$i;N}5$R|#D}Y5ntlYlwl9K8A zONH#Ii9Hj0z0Mc{TsU*q-fD*8f`(E!%dOm-9ldJK*5PnVbU1@GEFF$b9cwm4UcrD> zN6hjx{r(!1Op)EwR?W7^n{Vt+k>hsB?${}EbYZb(HB;ox5}et)De@{vRc702G*ZMd zn;4>{UFRe6o}>%7=FIk}hnOTQrsT;u;Q0WUrO#OP+Ds=;vc?o0mEndzafxMtMe%|% z6PZkF;boPEsB+gwNI6;zT1$_SjZbg&KDtK6(i#hhz?=2PARy$kmlQ-u@!mEo^{xY5 z=S0U|Cle|xFjbw7Ju7EWN}e$*_B;ZbZ7q;-_}8wL%+XAW{%2&96i^P^Oje#zjOdyt z)EJLuo2Vd-MC-8gG$|LHB9Pp%i@*IM!nY5>1&ES z!Kgx3n`P9@7Kb#l<9K)_2rBN{7X;ywgG)vk5BJIhPG)w+6R*N9IG)TV&@1Yo@}$+p z=UX|4)SFebMzSbmKmU!jSZ$lLc!f?2Fz_#*);>rGfrqq)6+ zC4jKnP9~*U%1*@+G){yY=4!_lQD*aN#f8G4ajZgMLC#{f^%{1JE=;oHlNGC$;xH=P zMv_hz@Z^b%S*4Sva&e!alDb_6jJ_OKxvy zFMA?-QRa<@`w9VlDjIYJ9;4NUgL5a0&B)tn(qFA%J5E?7bs|FN)@vmdo~Mo~Flo4^ zxPE)-5!yrGnqq255p?VsYzRZra_mx5gPlcl-ZLOn)~kymJW!rEKv0%mvO4pY)f~W` z{k>-*dY{RK(4xG_x~@18zrHwTys8LCt}o>Io(*+bEHfWdcUiS7`!viJx`Pydv8ppE z(h;1RibwI{MdabOv3Jn|i}4VFXBT;ZHgB(HSQv<%khL)px!p^^&rc~YI}PhNuv8&P zy=?AeZnuE^vntGf@D<;VuKf8zuaj{{l#tqBL=h3hWUt=fRV%WKCyN&yp>MsHz%%$1 z`A!%!oVmCbY@X|4q?)Mc741bzlR3_q=bUZG1C`%f1%X?(%+qG5wkQ`x z!(W!IR1CR;svURHwEVCzOq}H@_$tv%0|AElm%|&*YY>f}ZS3v#vsQ5y zai;Ur#gc2(=mioh@Dpq`0)i|kdf_hw@s7-idA?N1zthep*NQ=bdd7h5I;Zz(jpo8j z?Mo0CQ0EMF!4q-rU_MJ-L6Av&)TL6zYud&FhF1xvEX`xIZtcdWe%IOM z&Q)?Lq7kSnVRlZjb>&YKY^)C=aetVa1ww9pwRP+I=IRPi_-M>|8IY9Z#rY1|KXoH`+v{lNu_j1l1RyE z$dEb1GG6bcg~Ry!tUPF3$IzzqV@?TeBojxVSoIS8ESx5TxJ4NJXRugrKq#Ad?8K>) zeWV}^V(^#PJ_Zp?jtN--F;A$%xZI$EU(_1q3%n(Z6jSsZ`8)mra@-i)aGCwn@0yEO zNp+FLO*xJJ5}tZ{WqzO#kJX&Xnp2+!EX7#2h4g%>n13e*F@7=KiCiNmsthdBkJ1=g zGTdmuww?ry%PbsEgO55T1e%G*$RY?W4^speXi}?yY=#yK>9iqfSFi@MxdV#bA(c_J z*>HK#f0Um0^MHu#9H(GsJQ;2Rr9qMF7Sq&3DS&%=U)&Utk|t-%3wP`HC#a)MKE0$(IX&@{ylrai>;; z%@dubO36v$i+D^n6&r|G9hdHA;g$^M^Yk$67A+oFNT29yamQVw2dY#1$mA~}-L&Ov(Vsx}$zZz+|P? zpW`c4-o-M9v*BLl^4M8&k`GQi2Z?juB`z22$Q$G0B#ZANWEl}=&Uyo&{b0j5xIg;Y9&GZt&S!^g-z_G1B;l5O|nN%8F zYD!R8_rRnSi89)C$#(Z^AvhnQk*AaCOf)D73`;^FRz=;8h?;=d?Yl!Vx&+0TKQ@#) zzO`)Aum!c<^m12w%lV$sXyxXnL<6@vSlTtae~__yMxEi}0&KM}ynA_Vxf`F-a)|$1C^;xT`tUbZN(5v+Uz)9j zWL@a?iF*h{BNaH+U~px>RU6Wze+>d091ZK8-KzX&o@By5klpPllxco}>WVDC96M|z z#Z`WSV%Tb$-x*4O&N5X{=z1C7f1i2ZlGHn@@{Cj)vUwp$imEhllFV}bE``&=61$<#Y%c_;z zNY*42ry8~sgueqWF=Hg$AzVIjwcqyX|g2*@3GV1#tr^Pzf5)ra+l8ygV+H$MC4*QIFQWZY|;Lz!m7>tUy+=kEMNrOrAzo zWtZWWaeZAocgIxACI6BnNQyRIDs`veGTQozFdvl$pANzfXcWTN}t6#-UqcM z5ttY9Fqh zKJKr@hNXy$L34a%^|5aQx}DXAH5h<9%X~m{*bpxq%Ysex0IzVxaOEA-V3X3IRGErT zK;$3S6=6ennNVtgM^n^VKYW7N!a=dBEQ*mboo&hyJkL}?!d}{*eB6d?G`5TApmOU= zjIr#pD}A@t)x84u2uwV3-ef!{=m7GVw&|5Llfn|6gs6FKHd-xs=5m>b)ZwOuYI>6C zHkH@`(L-8e&#=`t8My=7W2A%P0e`(s=@v}(kd|0dZ+&QVSoe@|(GyZb((WPmz#2?Y z_`n*>gkBA9CE+#Eu?9RA3Y`Ty1GwlArYc5f<71uyV_QqjYk$_(lCkgKelZ1+P;+J~ zb51)dC>XV=fB4Qd7=Aznea>St=2Fe>gaPcc6z8tWtSZrWvh)>HA^TDcp}E~+4=j3X zR0k|>g<{K+3n4djIjg;_uQ5UFKsmI7?F(3;)m&IxDK==;k}|OHRC<|l#^N7YLGu>Z zQ>sDc=@D73u8XM3QVe5zTlj-em12gf zYAz3>`Qblcr**~u{%LtJpbn)s1Sxl}^5xaM^NHzoz(X^_32%54%u^*Ae=Va$24`eA z;Z9t03jn0tC{7nh!Zpc81w#a5IrJhPd#93kV?+*D;EKb`CPa=;>zuGRD$A8=j{>l5 zg;crvXNcap`PseZoxg4_edIOQ=5r99W|);}*>cwbfTtzOv!xP9WAB&Qa>1D_mbos% ze=c&OI?r_;S@FaG19G@k#?WYV4U z-_PUO&4w{(Vq|>0I-k#R)o6S?71^7t&Y#Iw3g;qwyQ=e~PxBw^l}J(~=Zj`86~RCK zLw`s?h<$>(kmy@U&IIre&7(+it`0c%sYtR|aB@(^Od+z%#hO&XivUVP${e1KOCtUk z;{ET%?FRl&;XF|DZmHOC5L1ZY=Cp|$@i4R^egqWArK8Bjn@^VL6ez%g+~i!UI|2wc zN#|m2rdq;!;1mI#`iwLnG$k|wKKy^?0rvYJ2)Xsl>S%NS=g|K2K@b0PKj44%W_mjJ zKc368dlzDV2&f0?}0MBGH85Mb> zgl{JHLsnY1RwE<*CyvI>rh9tMq!0IGW@3@oM*91Qyr1^-pWf~t96a@=_$_m|r-%Rc z%HZjKFVzA5%TS;E&cC?qLSkSEI5n;c?1H%2Gr4ksCFW!#?H7)*RKb}`fhu;GHKrXx z1xBh94vThOA{rJ%40lmD;zv=tKVNPA=R?-IeO1CpNkooh*QKF8agI#(g7=xq!Cu31 zHdj_bmHv5+@^3s@`W=hUr^?+DqB+OOuCalk(Xr!$gX07N=2?rpd1pAa`s*lHm!k7g zb`G@3fY)#H*Gj{U#zSW>Xc(~qj_F{E3w36eRL49EbG}+itAj0YeV3A zmZ&iPOG5m@r=-kUpDk2aeLCzd96si%8%yL~lY`fFdQ|iQcF{~gcBMTy#})t*z-SK| zJ4SodK?|Q0B-vUki>Y7zuvsOif?W$Nth}Cq(De282-h_ ztsBc(D-jF<=cj5_(eyS%MgeN)PwTQW+?`ZbHq1Ifp;3EMDd-}%9|;i!5Dsj;z?bj> zU;=n+LPE1i4&W|AuTS{@o1ZOuHJa^(Y6;O{vKZn2i-ZjyEpC1IB0l_00i+FE@|6V` z5%lMr8sN|Dln=-%cEk^~CHBP+Hq=ntQp44dt2Po~(2!y4|GmgfCJ0cIm^bj@64lb| zRMFQuU(cFUs6E_nRP=t=^D6QHVN50T5J99O8{5U12#dm7oj3UhgCGh0aC{mJ@b|KG zch30+qRgT?dLf>l%`%nu)>YJDA5$koH3xW@*sLQ*SpTV4c_S6{>NbQ%l=6>uT~fX+ zp!8f^+q`lMZo`Sb+Ra|=AM1O4d|+s-f8-Cx2aoo`%m>tXf?SFK0UmABz&sD8(}bZM zIQ-h6@cI_-8{;Q=LGaR0ia^eT2)3;C&BNC1doF7*r&2T;@h^%SA6P+~g({D5*aYaO zEfQsl$=nh|SIfFZ9B7CLJ6kLjf(iZgvj$A0YIKN@Bg_I8~NOqgfON zFdf`C%XdO^>h)~{r`l4ZoE;zO++df{-}LXV%OCzG|Fcl6ptK6C9gX7Oj#57A1H+6k zV5M{#7#=@<;>5_&t~lVw0xAwm46yfE?!r4Pb_pS1SXX8t*6p>EP-VeeiF3k=L94bH z^C)1eX3nllf`|oQ*59(T^!e4gxz@VzBO-oE^yaL5$4v2FtuyU0FrGEU<-kG&uCh{y z@ML&*MhTEPuml0}tdb$|pab(@ygZ$BM3^?$TQH2HrCYX&JrqRL_5g=mN`GrB_@DQ& z_qf z-TuC{_Bp^mheI=OJXvmjNT}T8comrQl+ROxHy&`sa%F9Ec?oW#{qh0f!LsI~MKAR> z@tj4jAUtPTsEVI0K=)+MP^f2t-c0z|*AU}vZBb}<1kIgE>K%)}?q;WIcx_|2$l?^@ zKXt-6U(A)e74&Yy525BTv#52VXqkG5(X4LE?EXcmec%s5k^`lXm-y5nr2^q%q^Pcj}PVW+e~z;d2YAO zUC8(SNyCe2Aj>Bbl8ON0uq1Ex-jH4j#dZ=ixOwgF#)HMIYx?mOK|w(x?kt8WGT|2} zu(z6=dT&C-DCX<*<8QJNrE3Lpw7^M>4_7WYwb5y(RO*h@xmprfEURGk)#C3nFYixg z4!)GkBs1xB_TO+%YOq+Iy_hE4g=)YGy>=73CNgyVWIr>Wfs@By^Zf|V z=-BbG)1&U!;Zq}HqY*>(#y9>6kf2wmtE?x@C{!gkY5@3-|A%&3;u!o*HS$%h$ijK5 ztV*J{p3NLgO`PVDQB-CM{j7n?ezTvmI{IL1x135aL zr$R-Ww+~u~!@{NSpu2R*;uj+tX?^{KH6JhG>{y3Mi1pJT3d8pd@woBf;`qSuIqXz1 z?yFb%gcYfDt^tWO=DK`G&Q{WVJo}XB)4D<^M`~|*x=ny1Dx#!9Q_xHWCZn22+L&fK zVUD6+fF~$Dp^W#I+T>$$vXWK0a-U}kN-8HGCOz>Aq{N-T@HOWh77#AvxNB;6o5_WB zZflGv#6q4l>3K_nUP;Qm31*r1{$W)7y*kq(kzt$HZXZ?a?{bCjv|s|Dfr0x`S<}!+ zEct(afe9u#7;+{4>TJPtF|gfg45a`5vH8s{Od&%MVG8ltOUSk5);H@=OaEYh-x%A= zUL84gQlvW!1-z@fB>wB8=C?~;7g-d0%S^ZPg|IGy8RuUdWiR802bp11eR z>?w4^(HUGrq>0;VNsR5JA}rWby9J+VKKP~i{as62)!$isEAey6EkKYibU-XgSKD?2*o&S>>zmdU z&UXK{O#3}wV}F{~jaVXVs@MQDF>Z`d+r14VFl}+q$ZQ?%384VtS$dMeQj<23AfY?t zs*nhvA2tVWt!CB0m11IYv-|4mE^1Pta-l&eJf#w1(=WQkm;-lfHq+=}|O`6WcY;?jz9 zt+ryfScfhD`L?Q?}IOJ_3hDvx$tf|8?$CFL~oDNLNI z7aLAJk(ER&yK&qrM%PTCGLtKo!8Lps zw<$@uxm(SI)&Tp%cxff2A~w`27w6HZ!>rrLhmDj#y#SYSZ(J260L7aBO~g6&Ph)+*Ohs z;~H15Y4c<90>HafE-=@#rpp#l6klAji1oY8Yj?Sk^LV}a;PJ-#AC-~{PI;dB{b`^S zt*wAs>a(2kwMtoRc|n*4;4Qa5hhT6bCA@Fs&g0?i-D2B@Ybqk?m8;MVJ=mNy>)}Q` z{Fg7V)O2OWNlA}&%CCm77hY&@*=*k|J-g@avwLRFO3T!5TzeaOo_xStV^=}y-}x|5 zwNu0i%ADq(Tq_@fNNakGY8!bTAxvi4LAr)^UZ+?+2Zj0sMb$+8J;BbfbJnxP`YY?{ zN|6MG)6Le}EfB|2v}k(?lulbG+UZ4F0F-LNrcFf&aSTkdBGk>){(Jiut9zXMC z4EDCT1)82(-IL3UlFNmGZ#*<8QL)dQX#OD4DE_rD1G^itIgKGVqw zrEY8g-**1Py*TxZ&KR`0|Ci}Kc)-JdIf&;!4)k`;e>|55-M6&jvOUR6CQ&aHXHaO| zzK*9PmY17rpKN}-hW=z?9B-Z)dE>;u2&h9<+9;FUd2{LR=H>5Dt2a+fkXu4cLCW*U z=^br@8Gbg^|DGB<>3kH8;ZIY$t zaMH)De0^*EBP&UZ?kerSvo9m;aQ#1@{|OPs-;f2NhcET?@uf_2 zTCQrk`Uw=PHBqm9hF_KY_@0dMxgsjnDXBgq2xT4$dovAVrm8h2%Y|`S6?IbnHve{} zF;f#&Q?BCYerVa4F{d=OP}59Fofd==H15fqlht!#SrB^p5?{`UvNjv zc~CM;T)_82i_EwrHcfe=sTf+b(I*IiY#ACV7wZasc$@EK{nVR^DK|vj#Hjc11DU@y zk$=Hg?E05g*{syY`Nqt?^pP(AOQnHw$(8@*o)WD8{=xpz>-B#S*P%CyO+zoj`YpoR zM05r9W;l+^SYNm7_2=#Rmi2T4ZtN@fko|mdd#lyHwT$4Y{l%vB=a=m(Tba|EVNUAO z=)aso(MI;oCDdNH1`pQOvb{c!?BB23^H16h{x@$a;3kUR*`icWc&-wT!RBY!25F8x3SVerVlT zbl{LNtEh~^Y8tA?bT*`7QMik8%5T@~w6mOYE(2L8=f zDp*WbD!Cl=MNo(C__|h;6oa9COf;lCI*M0z9-Rfq&h1eJIvJHrQ&uOvwl&cd$Dsvl zed6fY(PKwPPgc&JImJkQ&d}6MrY21wDjJ+7+1yYD!3Fb^#w>XHaJ7amt7ew_`R?+A z7(Vec*VQ%q&Nn>Ib2-wG{4@0#+8e$OA^YaC{eUr(TTbT`3Bfte`p1+sx4p91WxMx| zoo4OY*RI*OpMwzTqA8$RJn=Ev^Z&_bI0h-_BxCsl9Jnja0;Pir^OEbVFzWoL0eb2(?PlU)Vdv4#^41o(g0LoOng-Ga=u-(a&u+)w81hVbRP5bsE0LMUflxW}Fi#FP! zM2q1lyshLSoJ)DZWz_C?)KwToS({<5;&TCyKp;)W2_ozkk>cjmXB&2P89h1$J*44ZM*<45gp*1)>3 z*T1*!Z*&G8Y5+A$J+YA6SAK-S1HWuPebf!kixmo*wjglv6;l_s`S`k#>T~HE?RjY? zkETVXDPfrvo(EnwrMkgP4*wOq)B0>3Z^QK!@($bz^oqq9{OnPZIRNqA>+2`$>qj6X zWCdiT0yeGqTC?6TvZNrFDnp#MT?r8AY;Fk65~y>#ml7Dv{tAMm)!1?E`&RWIE_W~? z39vW0SS&tOt*iI!^=n|JFIXEt+G{U}Q9i$BJ)I}UIyvu zm2b=>VLl^4;Wjp=ON!rvDx`l{RxI(uimrnuOh3p z1|}d(cVMc$@osL}8*8Y&@_hR#NZ!^X>*>l+v|@=zo-YSz3Y56l{@2S`P=ewPA_KK= zt-xI@X zXu92^2K0;yRdnRjPn9EaDD?7($DSl?maV_A*H;6+5JHaCO{=wR-H#)M4(ck!VG+2uE#ui8$5U@e-?{8(brd=>Vu0O$R##3_*9yrKd zP4hm{g2gR1zSf^_|FC6k;2V2kHQCS09Jj{w4qd*<-rSJecHdmFVRx$E%N%vphMlyI zlhs{+S@ZmRZd7{D?VX*#f1#c?eoY}4aB0r0($iDfN zedT-VlZTClftX7WeC~F}0RMdV#uv!L9(0PAfM*OO@^8OAm`UEtsBig#Y)&DqA*n8v z^5}?uBo9+r)oP%92}hddMB%L?IlM7X1ow4a5^Iu<9nc^==|grRxW`wurizW-o@7M_ zYs0#B0jt3jMpRFOc~t;KsFg!+3aBq#ll$rR#{XbjAE zA%Sb+JMG@p=Et$4+D|HXNnea(%(_{>HssjbPN#b(bDZ<(=7J*(KrDyr2OKT0#@pj{ z(aG1t2YoYu(F6!&GwX3nJb8Q&0zMlTfXiYX+xs|>Hf04#6N6XnKMJUn&IqpShE4Pk zvNz^I-U+kb;O6qEef_d^^`S89A`E4~E!N%3!YspNcUBwY#Rzw7tXR*UcVuOjzlX$s4fMXA|AV+X%s*IB z(nWsCtSfuyBR&4N)LZTw49)-G;J|DD&w*USZ=U$*_}K4GpG0_)M>50s2Pwb^0(V~H zZ~+*gBSfPZ#=%UeIwk7BGXi&Z?A^j!oc|RGFW{zS=>k?gIAY95Dpb87*UTxQ1}cA5 zDv*afaeT_6QZT?4mvBrl0|lC|B8?Ce1f9l=i3;u~!^aP;tBdXV)^L&5qAe6zJr9Pm zB5;N|qe#Y-Bth>}x-=nhMQ0y_ZLCP%f?8$ZaTV#nhR3zqj02}8Pot^=OG4l<>YyD; zx`P#YKSgZuk%0C+JXIR``R=zZmqN7~46xB0C#Z8H_SJh}c5k=lBcrn(d_lfJ zT)Ed?SQ{=jLa=;jQrCK6T=e7VRx}zSsF*dk8mwlyDw>+kh1%CNlN%W>;`(V|pp98* zHfkUmxDnsy+r?G;!8gv=)Ho=^ML^j{$08%7SAFN@YEn~b z1t{Z2J}e#$5g-jjL(;3TX8b^$k`zEm#XB3ZKS*m=V;(oFdmb`@v9BXWre=yt%DC<4 z>kgysYSaY$p2zJ#+11El&C!M6TT!H(EFmgfyr9xftB6{k1*f#bLUL*q=!#Axa(Tob z%L&V>ed`eryPQyeylI*ml{p~9b&%+VaZ`1r7ThEFD}YT+*Sh`tMeDn@?PnYIj}M27 zv~|}!lR7?A99N`5+-?wPL8=ja9qN&Sgxa))x34DG(bFq9fJUhA1@^?LuIjU~sm;2i z%T*vBaZuU+wy@p0w0kHptM;AEJ%O;EU9zs<+G~63{>C0gLHu%i9K~~cZNs{Ic@H2S z+_Ud2*el<41_3ov*aWvvWwc=vD?kC(#RVy>OIl&c0;IM#zF^T4G*mq-Ttc{b%2v!v zykz!4-UY%-h)%T`m3erHlQH8^okCr!!4AP@fj*_nJyNIOD7Z;dAyPk8N|Gi-Qiem; zk|iZ+L-aGIw_b?(=$edp2bKu#2qZ+QFsWF_` z!r{VK!dWyZ5xK#U2gzIsftEH-(Z0z{{5Fiq3?IS>l z1_wljG&N!;8pedCndz#L&nPs+X{kU|HzUO;+_+@lxu0wf#sRL1YE@E_K!et);iL!{ z_zw^5udby7--!Vqa*$DXm{&ll6Kdqco2s!aR6f>N_96e%?OP;5AgE);4Q03yaKuiR z_#RY1ACV6QP=-#{WUPk=e3ZjQKem1WJZw~TxnUwhuX>Kzb4C%z#ho*V2a;64-dSoX zfE*=m>A$s`{Qv9~`~3$;LG#i@vEERmedr_o`wzS;m%aGk@*w&CUmAG*{pTRALnt+Q z1F~J^Y;O&v$q7{&!nuT`cbU3y2s@tjl8tmtEBoQi=S z>2M@m=IH6umG?gy9V1y`a0(h+aQdS&W5Qd&g}A=8ybSfXf7qf49M({FyR~Mu*2veG zn@iS%YY68J$fNf1JWl`c^@_c)O2criE6emWRW5Vl96crUAF!y4UH{I3mi_7@ef^h9gMGc;_un#(|LHFe_P$>K z2XRGW>`AH*=Uy~s)T*pGG54Y=VXqPkU1!hqEvTya>>JA=B3DgX?&OzZFW!a6qo;qB zM<=9)q}Gf)dVg%}v>OSSM`vi-r$A#Kgh4}74ap6ge}C+QQ)isQJQ_81Nd(1rk`)D8 zQ$2%ZmtyTlNzuEwC|K8teDDqBpGlgkF%}V#cEG@iE~iyk4lI9CmJe|3f2R`+$wvt$ zC7hKh-{DBX&a%HuNG6O!XN{dl?>z|CYE!}Aj9HcAZb{@2MNIOP?vkKnaLycoaYvSX zAQ!k`2tY*XQ3EhYYONbwFyZy$q`Ef3uB%60M2jF&!5^*FuwY||tR{R4c@6^*VlH%=F&o~tzTS$hl*tf-z+;KCe@#&%sFTAsQ@A-UK4B{V!PjGAna>_H$rT=Z*zK2c0U?qS2}>_AlL{!|BuU(M>s!>53ogIZR4Az_ zP+m>ylhjG;Hq}WNDNZ`4HtCqsBq5baEQ5qom!vVsj?#Si#4_F-+++_4JQANdfU!hs z=8i5hc65`eqw5SE9W!%umyx5JOdMTg;Ft>vwVh_#cy$>zQWwlC$*2*RNh6J)J7ud# z(oyV{Cr%;>l0D-o_JSnnChuT{R8uR`w1m6G7OB~60BmA_;rT&MnN!8TB)nd(uKDo8 zim%mrg3nj4zo7a7tjKTdn+r~Tch%s7v8r^@%u@Rz>(DE3CN`)!<$~ow*&ccsS=W&x zQ9s|keaRm^>w0aRVfoX7q#f{bIs8y$;L%uB0^8Y0h>^=|6H_$KXYr9T{1s5GRft7| zY2urV=xZ+zX0T`Hh_?Nw7cebeung1p2{LRVCKYX5R8Ua+&rm|b+L|WkpfSZXgNLcY zHrJ7$_vlC-_2+zqxG;r}hGCDDN3ckOMt0oplUZib^Qv|sn*+O9pTLjVBZq%iI9x9r zuA#&44;}ts=-7-xgZLQh5!Q-P`wy$w;DN2e;Tl~so4SfzGm~dlDC;Q8d51UvrCHAD12zfg zZY~$VTWrWhI#mG)grx&5_OW}&e*Lc1zI`o(S%{y*JyE$4=_#rz0^c}JBS%o>(v-&l zCJDNt&pndk&uOyisbYS=iKB$!Ei9@Ik`{iY(;2z}8!9#nKMQK2dA|}Eqm|NzJdg+m znhoY11{ zLbx^4P2(E6$F#jRa{xD9_%NM<*Bpn*cq5^FB(Bgvy~`7m_S+B=RPV8!l@ zL*g}yvk>D`6X>FBNI{osmLBn_RJEEU^!4c_|tK`itGUi83WR? z1Q2=zOXJ#wa|4iOfx@^}zKj5*0ecQ88{q@-4!_MhM`?g#IipzxNoQd1LLGjgPh9Hf z2By^b)bgE8UHsX8lDjN%E+aBtRiXl3Rl1hB^k@#4Nq_)j??cG($^;Q3@6PKNqa2jZ z{;rQF$T%1hp10kwqKk!}9Wg6<=;0I#=tE7F{3@m6rivNYxLMutxR}!`I4%rnx8riL z2#?D{FJ@f$fKg?3Ckp*|{7oa*Xa=00i`r0Ks#3#zUYMsEW0H?^_G` z5JQ%yD|v!*mk-W@w>bugn-7r5tK=Ve-aiJa-$b@oKqRWkk)Wv}Gxee>U8094Rm=qK z?|@$CbMz#*B|N>%Rmo=OJm0S4UjRkS{qT@%C{YNX7*X%WX8@LX9q{)sBO9(ky$~S_ zXD6^@0d}SBq)Z7@dqT59^q=ULn(kGg;C#iXKrs#|qU9udpFB6v{yU$XYO#K&Aidcf z`#nqEoJO+psM3Xs@e2J{KKLn~`|h=q#A)+%mGFW$$anXUn+g|2?Zi@gdZ%vSeovB-TmI{*ROkC ze;QjARDmrlo17VPPeAhpB#9Lo{ORuC-e;c2%!!k|uWCy(@N|GpqNpNaI~`2IzPG7T zGGQ5gfhTZXE&=b`ZHPHi?Ygd)S&WaL%C@fIDWe&u;|I1<)SXMlB_l574BLIk2d!%$ zpdlIPdKz`LhOSm=h_It=Ia!iNafKpEtF5UWr!7f}KB|(4a&bZbps|26 z@qHvzRF-%1;yfM=7lDYhl#t!hfIA|65@iO&iAG{ivSV&yBbXxna_~rqv$=a@{7-27 zmu_J3bvhZleIzkPqw!zzgZi!RjqhSLWmRZKzA2tJ_*-bPnUp zoIAI8kv+@L7K`}V!Wo{Yo50OoFwq&aW0IS`2LG`K9ew;?*WlJJiu4S|V->|uR4&ZV z#c>zkK{>QGi=4J*FkCxmAntnn#AV#19fDs6pwR;BAWBrC%}>t~qXk&f-@i{@t`kV< z%!$hjXLjNq@%ZqY9|!ktdM{a}vV-e4(-iia(T2)ze=_{T!{HY{B9EDj;1-^W^0B7Q z#6cTQShw@jto-Ga z^R_@nw>``#B4t|$eipux!@!na^GZnw=y+Q3@`mNn41yux%M>k|kY+R4fHQiC!VKD< zj=k%9aiS70q9W!x1u2AAiFlj=_&;1mMluFueElFGW9`-Xr> ztzdbgT3_!p6zsHO$3Ry*sH4|&{AvGa8A!Wpn zcVfM6e>AxBpB_Fv8^-XO2Prn1d$oH0^z!n>#ihAeEF7l(<(E-q@oY>{;DSWV_$X|A zJi4&~`7<8pAN+NA=N2;{!!JH1cPl>F9e(^78h*cv?L%z2a;|b_1trcbRZg!|TxfeF zcmN4>@%7451uZPDpvqhG%PY$$$%>s_T6`1rS}syO%ZY!2H--J@gh(fKsikdc_1N4Z zx^&{wiP)=^*X9?9O3t4hMZJ!xcg$7>f3-}A*QK@K?{Y1$d6P(?mDei^u7||>bz!-( zguGnn;{3|%sIqWo>Fx6?l{v&2j}j*?3v$>=%o0MCg*n{B*%vX#D%*WF5QaQVg)DU)=0$2eV@4xcXE+ob$@HTKR@#$*oc>t3M@m7U74 ziM~OCTORESW1TrNf%TB1st{bg69^alu=T)aID~hWm??IU|Uscjy zCoYRE*?AAEhhRW6I169|3N&7W!}uN%`t#6K{OvAhP6nTOR53daK(u0P=$2`K6)0bd zpFh3wIwpH59`;-&o#mznXC7Y*o=BI$e}p!BKO!h*`*uelqy_-tfy$yw}U(8ugQ# zRCi!mI^(}2i<#eiE`#RJLtxzS<7-hi@Y;2}#Q#0gGC1Tqcoe=tO=ekqWv5*d`DE=Pn&HsO>ntnQYcQxjF+Ie({h( zyRaiZ{QBDd6<^U4mswkO#InzkHM01`PLS)`f*U>jegI}gWa;x8+OF>5WsEC$*mL;$ z5gPpc8VRwy2N(}D#4?;KOn-RsLdJg?0$Hi?WW3~+-h=qtG`w{O&$6&1#4e8egQt=Q z7?Sk5Zg)gszxPAFx8$SpTkKsKY6r;RrJ+ay`+^YP`t2=pNcq7-xalXV1(p^tQRE(# zyDR|M?cMXK)f5UR&Ba zEJ0(^Dj_EO`>}wNo^6|5EgPn))lIFI4b$hC=#W!?{0XSIE_OWTdErk($LFe(g%`KY zlcp`Z8Q4BW*pnV#PeW%xV%53^@A6G2Pw7jR= zcE@bZH((RBsbk)gRw^!N2Edno@d@9HSTGl~&GVMNp?9>FW|!g3Vhnz(j<(Y6(ciJv zdAd2WMx?JbUfnKt`yEGDNbnWamE&pV7x)Rc|GnPP-26d5qu>A1@BIFksY!VMJ5j<@ z!twnd&)^d&e+nvbWcR<0nExm8Q+ZGRxjf)MP2`T}|7Y^?!I`)qA7-cDHPUDv8}k-y z{4G0pY1>Mpvk+FBMsr~ObvR+ZqHW>dXH84fTgDsOb^ss+r)L^ky`x&Hqi=ZdG2Wvp zyighitYT?^$zmFITknklqalDJ5Gm**5AY-mg@T;(fNUdhA6y(09s*UZ5_oDJI)oTl zcHGi1R8vPpAsVHCL2}N@kn{< z!Oj+!-8itmQ#Z^_>9pqKhwtMxzVDa`1oet?PsZK2_jsC|z^wMnUZ0$KW6-R0Bwiwl+CE(xcvUV{qFI9-=WC%oP-dtKe9BUn&KksQ)M9$B8Swx zG%^iZ@Sr-$&vwXq6s3uxq+K-VrE=mq}@9cm0&G62ZRHQ~p zTK-GYsW4p#%jrgm9!hxrc0aASWHzS4po;uMU)mvzoF1gG`XiVo#BladBR^uYkV)`p zc18pya5BFCWqEOd;XCrEG=iY}^Nh9U?f4vj$S2bO=V$bfU;!}N|IZgDOGVHBpD2O< zUz$9Q|9vJO*TW`A0Cp6ZV;U`z%|VsH7uM_v7jIBg`;Ol1cb3h5k0VD?U!2-fY$nvR zRGU0B1Ate(!<{Dy4g>99c{sRz6QIfBg588O3)LzKtEeVzt<#ha2z8nn+dZ4aJCk9@ zm4p*NV$KY`jm6GT6XiQ?p8(fSIo;9>CozK(Z<_Dw*raAlnH)-9#Mar|w9&!}!StC$ z_`&4FEZUl!NTJicUPrsA)!xvZY^gYvDNZI_!aKf}=*EUdaBr%074yeCo#y5s&#Ppq zQ$`+Algkncp&`&QyM#MwHlxGYVS?qCLdq+y5Le0R$Tg3HnAP)~2Am*bFV#YEO4y8h zZ+CEY58j0l)WZ8HSt5A0Jcr&SN{}H4BDnHEcV0#%1VOuAJLx&RAY1%L<;Y=_u#Br7 ztu>ido{Q5}dlD`b={-m6n?dpE>0&OP4kiOYA5JdhrzgXb0gn$#mvVv99D9!tFHCt% z+=*%<@e$nSk~2JB&jQ#q?}LsVPi{#E0Qcz(xv2(9g9R~tJ_J)M5r^Ub+j%t6BokG>}Yj7Ga9&O zs}TFDV6V|B#~~Kb>ca~Kg%ncYYRvdrVnm~`v^@I3V`wxD+J@`)GLqH;6c2V{1umz7 z%ZcDIH2DOzM>Cjn-1yQ^fSD4`wEndWsaYqcG2eXRFc!2|w8^x@n*Vi?R;^`c6 zMD$ck?b_wb9_|Yq9f#({cbnD{mUI4DcrojxL zUR+dgyPm0-iGXu!t8oW{o*8b>8VH)ufSFoK;&R7jo=)@^fQ3&fc)L+uw>A$ZdIoIE zwlNPQ@OS#AL$(wYEPAEhfb+t5#oy=h$5PO?vX%xnxc&-Em|Z@*^i~E}2EN5JoerNs z?yyUK-Y4~^6D(u2Wa6Jdx_}r0xD*EyFZM_u|M1tx_wT_P;^S+`g9bk25NBQx)ZDYM zh%@U}w$-(>Y_B7u+Px!|DR!^S2E_|VX#KjfZY89QN8;m1KVA&7hlG5CI}cmj^l0AW zAMOsny@!_sXmI1+0D|-JFNj?KVt4q}jl;N5^qO49nlYTVVm1{xy`C(jkkjxz@iqGA z@SVH|!>_MLxKq*;80JkKVmQ39^cLZ^yx0vN6$kZn0N%tM6|hcU#l20FZ$2+4dc7@< z2N#j^^G^>3?hd1}Y@5R~!sHL~}23H@!m2mriydm?Gwn~}_@R;OM1?PZuTGoB9C_zh2 zCV7c0D&{l!TybJ*ayo@h^3rLP3mpW2ZX?4v6TSA9?U&;&@-eG|;MVUAZ|#CZ1%fl* z#r{;(y53hFE1gsxXNoFM7yiETSpB5(I8#`8Z)ZR#&lFKAKM!vMLW={CRG>KFq);3( z`3rN%eyK3iQ$O!kLQ4m#X6ie(Y7U_#73K=;FP&|LvOQ2aQ?=2>Lv~zTFxgulg_t}N zpbqcj?mvF;1Fp~RcawR7V6*`aFw@Kod8J}gytR$h1Z`AeEwz(9l@hFlgw|vW*MSVb zA=hN>!kMxdzmlaa?wlrnrZ*;$`~Tj>FHijnU`+f^aWYr%#eYo|j`#nc&1d|6KikFk zpy1s~fY`EUbI50Z~`rFK-`6A~?Q*|k$M5ljA7Qfr&QeN@3!0=QVkUf0Rr1tF=#%gqpcD^uE12h{5t*P_;|RHV zMiCl5{AMg6H;+q5%Ci&7KM%c6o(e=3NVh8lJ0DCIyFDT`ys+5S5vi>3s2PYZ!oqbz zz%L^jD%DaqZ5OK22jqED9x?KQ#OO$++!&mbC`ng3VwLdfMkXFuy#jKfAc-~C-QzV$ zZXNHI+xS;dF1Vx%kbOy@>k`I(q(|o@qJa>FP!|}kU>?h37~Vk^Qz%avr1Yd@Rs#I> zibQi4rvh^&y5YR_6jkOeE*i;NXu(L%3i|EiEELUpR7Ud^YkCA}I(gXv{H%l~@rG-JW=%NxV*cU{OG!U6zw z7Fj}FSg`@r73i5}r)ul(YUMn04!Y`A)!fi5JPT}=3ppWM4?t9~2hM``z^bxqmv7zK z|7wo_p-?~uc2FKl!r@&S-UkH;lGp$K2+^bLaBz}cX8ed;_(QN!A*OHe0IyB|k%}>( zkG~H;0=Sqzv&d7{RTemN4!A`2nLN=Z)xKj=j9DIu4o{k$zTM^z$jt_S6QviFSY2%q;~wGvrYXJ5ZXX;77BuomgxJIK!wY z3OmW5)B#C%2EAA)O%}D`zP-)C{oG)gRMEmK1m z<`ZeOWY$c_OryoE?UrVw8Mbm7oxy8Z)zUhhG_qC0#!a+z)+6sqLf)DVD1&Tgs;1aN0P}L@w9cnw52kc!WMhDv)fL zTJ|K`|MI)RXE)HvY>b9rGqPSEcng{IQd|iM-z~MF_ibEtfmiHRG9kAGi^_4#u9!eH zxve(LO=xJow}p!MKdV(!leskcCzDT+hO)M`^P)t-qn|;=LPR~&tdkkLUn95Jv$8?H zyXwU{Cs5Bv^@8@8kS9SuN=@awYv^{bqmun?jTKfqddpDAZ5lHOVv+!o6cSo$kF_+i z;?eCDTF`LEK351=9b7fadAyedSjxRLT6raN!T6*aSYKiPeFpXVu=pw1NH>~rFhCG5q2m zptG5t(ZNmY!m#mkzh&tS#$^0W;kPnE5BgohhAS6)c=1RUQA$(CuuY!GsZAm@*?MiZxvag;w~N71>Zvn%xXJXfl*^46U63Fs!YQvFdTuUIOJO>+ zmZ^wZB)Ro83kGIL(I*s0W;+XN9FGhznWSfMnf zra7CMW{k1U{@Qa9wYLi)x+qSv9KwL`mqgwv{)wD#M=4t~Y|h4IX^@`JsJo`x^?f>O z&&E~qZ?tGTjT~-?Tp@s51dS%s3F$uE^wM-B!tP+iMQpR9H@F`o_*^MgS3pZfx<1lC zn&hMN$!0&dkAdPKD5KxSj#-^$5xZ+a?VN&c^!kCxlk?eS9%h?2S5q#G~^&9{g>0|I;6dYS$bi zpmBH{Nb?wFTc9VLJCh@wq43$G-nVRMWzW>T!Rz29w5?P31hB$$nSxC_iCf9LGDdIx z9S)!Q1bQ=V7{`%R*+l9UbCr4A019f=sP#jD{J3`2YmJhYcP09ly}{MHM50}@;rbA+ zdG&EFjP(IMbYtBWiK^H?x^m^T~R*Zs~xjb$4y;vwMX;sOtsoYeAf+s65Tq>c&(rf!l0D#*whJar%X}^zYYYKQit%h&)t3UyRdH%C_tRDoXmUBKu;deI zvRJI{ih=P}B3qE|F?qNC&Zl=Kk??LjjnL}7yMz08L5mm&>PDEqq-fsw6M!xL;3#&5 znOUghwpMHFck8Pwh~ZBtg(Hh;QuvjlK<2oB>{)j+Fm~Gl&|Ha`>s7WOI%1XgS;wG} z@n5*;oGcr)buYp0u#K7F7WmIrTy6Qj*TVlFudwew@9fX#zrB3_J^D&3{^xgcH5h+P zA^Xm^`Syob`1ilA?(U9GYy4kzaH7x=@p7Aj2^jv!c-N-0yEpimi@x0;eapUG9Kn94X7J$>%YK5ihKq2#~OLku(6 zo)o$Qw~6rvWAXzPKG9p0FDNiJVa&59%jfh5(OKVio?tEw=6r=Ij-7=?Zn{Y1E@rF! zc}nT^+SP$fELzS^ma~2PfkDshh>6dsib254hjNzY~zJcE2FSS)7@Nh81$c-*lKO7Nu|?e2qIQdV!b0P`rY5WZx|d9GQ`&N6`3^FXu3p z>%{_)X<}s*L z(iaf`&kL^!OlrxJ-Wb<0SxT2>8u?_#6;(6|Id4$$fr2r$+}CHoC4Ymwg5nfSNoTp^R2z!Pa8L-;-=cX^C5Ib$FNv5h3E5az?_ zejRZ(mYffkoy}|RAo{SHF^W}MMd=L@^!#fUm6JW9AIV$+Nb}Q?H*o`VG^&x0Lsp@W z&nqfK#VKbDQ6LU1%iA|z8^l|2j9A|OeCX|{dmJe$4*KF-acUQD#Ti@)37=Ax3mQry z*z07m+@A(cm659L;jF5VtFAapPQu{C(pWg1lofk>MYL;ejB}GL_5-RP7w00}ceVg2 zUe;;OcVP>%$D-A;K6RihO>=;&niq`+!p~$Ua?|PjAO?k~sNyhU6Zx4;wh}|~MdR$p z>=*-Y+6N3as*mrOdV|-AYUbn#;O%1J;>iQ=a^Q0(QsT*p6uh>}Gdg-nt3UWbsm&}v zh4@D#W08n?O37|=Xc+c6L7FwVD1F}TZ9Bl@aV5=2(R0D|K!KNf+d7gRoozuyD2f{I zJ~ki-VfC#Ua!5hPBe1odJexYzT(v25b9P%^e${Te-ad_1diJ8|V6%f|gysGp8LNFF zhCId9G%aL>hGdYP^I`WWkVtG*jRNQ6&(7%FcQC)lXRan_TSeQ+4zt3TkM!aC1srxz zUVXTB9s_wK^|Wm{Q`$QW;6sK_BiG1qHBRO8v8dnLG-zR|D)`VEnt~qrnfkBMqmQ2HS|XtGcz&iFQgtrwQTG_dNE&du!=QA(uQg<7|1ySt?G2+&yRQG4tC{Ez zR#$`~o#s`jN@aQV*m0{UartQ;?#r@2aX*v|4Fy=^=LE6dfk8Tp<>_?wEU`~ar`sVDy|{l5ou~77 zB+NQ>D@K9Xz?u>);gZ`P2VP-N?A+?r#^ogIfX>DQ#FX}ipK&#*;0v}do0pT>Lm|%o z@lbpk)|bjT>PIRUhfw-csbI=`5VC-c9eCFVo+yv!faiYbC$&)+-?&w~agEhBuGJnq zw8?;OOdkc{=#_)Y2P7&t*`Q7mZ%*iMa6b*{tEk-x!k%=^S)MayOlq71@45}njfHi7 zSJjPKOZh))E1&yMTrhW(=m-}F$}kF&1{|Q4VWa^-Suz|RDCH5_>e%bzdQi0zE)JAJ z4;KZp2|U|xD>AtoS=U|GvW!~m+WT@$sgU=wBs^@qN~I6A8`i>JYbc!QOP9e<#wA9)St6p;DI|BHj zzM{kD1|LWuCaZz9{r(br`Q)40gDq!s$w%;`VJ4`+e$d;?w5g+ywA(X747;1u54_9& zRjLB_h@&##kAXnJ=)zj>xd*)5+P&8X)M~0&il)QptoCFTJP%urd8~T5+NsYg z;c4*IN0De$pFhfy<}QSvEv>IE@ls@DR*Xd@eM*YOkbN;*rPd>teLpncermnFDG%|P zBn8@M(cAC->6)>zl}jjl(;g#)+*a8@EgI)om^vbXck8~iXvEO@VJ--c}F_bCilP= zz;tb{1-qczf@&nZCBChJwuK_G&}P6TI$W=Vm$WxN>N+rfyyU$9SA&K9_h-croEtHF zAn4|>4q$E#V;`0aK{u40bt;=YCXgK{gc8`Ffi+xh#%cy^5Z7{JVD4MlW!4^x|78Qs zWv*{&2HCquBwW)L(T$}j8cTliL6}NW%T)5ns=ZqzzKw=jCR)Vm8;cnD>*+@A*`IAm zrfpGEGK|j;?*==A6#xEgc_E+;jT!=#%|&1@XY-c5>Oh-j#3H=4nqcoLG30B3JTlxP zgNa6C#0YV=Yu@$(@$T!9=%hfO#-9;0BW8UdFnxnjtsK+mQpJ|*~}!LUs^x{YvLky~Fm zAR1E%gH8Q8e2(@Ie%~8-zvbn-|9hza)af_-lhc{~X`?~>r>-MMRQ&hDT}Qhq{#*Ae zt^MEM#nsM8{Ifxv0W87J(HwxEtUp7CY$Fl(Q8ydR&s129$0Lf@9z0YFdC04@_eR&D@6Fi^C_>MPMBa!xY_V3Sr|99NCTYIn!R@atu`^!iq!6@I1yTQ`T zQe%LQf!TG4@zia#ZB?<>OL z*(wH^!DLIhJ>+6505zQS=W(d#}O9$S+O!TlV(G?>?J%BU)xwf8fd6>9{CYI zxC*9S0i5~Hjvt9eAIt+8H=HkbL|z|!+|D|a^z-%?^_y!9?2h{NFVLyw=tUx9V`Jm# z%2cE>lPR)vsVdaC`y2CO;<@+4Rp!QE)o$rHU^zF=N`%p2`ER0>E2;Zg3=s=Wag@4} zdVj=VnV9gnS`*bg-+rsLXTQ%D=-8T8fR{+jsAsH%D4#gN`p>-{=>t(X(yzk1GEH0_ zmoMKM?jK@qkXiQjz{pQo|JlBwUk;A+pJs!nhKJuiH*}gsuNG&@qcQ|7Xy!MDPMsZL zr_P*VgF^$q7&z1aM*lE7chVK;8cXs_$r zFfAh!8TLCp4({mX?0CvgF<{78jL3WA8t@z~-1Bg;axfFq49AZCL@IojGv24hbA=SS z;5bFE*-EdGcT(uE@3 zVPIS%XfOy42l)8OVtsXoco0A+5*|tVGO{|xqNvEb%P1FhW;|KC>cZ%TVOUrLP9(ei z<6HE!9h*Y_=g(LScO%j6agd;K8|-vCSI}X$6U1i=xG@Xk_kvgd`8taUk-|a7wGmdO zDU%y!YomUG=zQ`G0^lKp<9yx|skEU^!sMF8#I6P)F-TMcDDG39r2*vx8vDS}OmRNT zh<{Ty^JUW6>0%*K&Z5^5z?puy`0{uV(l9q~$WHpytb+dXt174sf^q2%iu~GpA4DRk z$ef)eXC3s_7D{xU725%|vc5!W?7bxblMuq(WyKr!PvKL@EHi0%tO0U7b} z4(*(Tf!e&LVJlBiYq&{Z6sROQRh`c3bb5%^46FZs6@hNfYoLTgVAj>nUI*8e5~r>_ z){47w$tsQ`r=*!yp5n8QPE=;CLFgO)g&Ba|tz!#lRYzDFDu}mM#}L$dJCs8+Y?OXtf0CmCk@gs3!(p76N6MKpFHu>unnk_=( z7?Vb7OJkO$O6lrUs#;8;H8Uy>n!vk&Q~=J_t6hDZd=Y0aPTY7(gi&Px?BCUp;3 zy?S{R56-P^_Ts&dSX=#*MHtIv=ixT)X0Cm`4D@b`kOlY{w^Dot2wZ=J-kES(1WSAb z-QBLOEQ&GRdWb;Kiu1FnXC^OW1gqj@hIpl_6D9XK*VXRy(Cu@+x+9z>VC4GBS|oz5 z-qRi2=(6@46{eyrZiA`cUj$s8J76L$plQR=f#1Nhz%7fl+y4Lu5R`6GbmY#b%y|UR zfEiY{Q4yJpjeCAMhan8KF;{MbzBa7jJuyUqb$1Xa>eig-5kI{qAvSMO2U^Ji)}XJ6 zsvn@!yQz;$6VgNXiriju;L2oe$SaAAPCXa#`iGBbJ^1T~&WFZe;QRuUTovF`R~SDF zJ7mdfXy+@%NtVblZc?FRpqH%u@g`+#92_|9++Jq2wFRjFIL8^*@1-2N8?UnSQ2K(- z%eQ$x^83rqy){4!YGBX7ksf=ae}tvRSi-BXNjvbd7~h7jRvbRxsy|pVigMY9 zMR~_@0a=E}RHgBYjHkFL1g!FO+uWRCpi;3nsH2zvh!jq{W3`n5+=vMreHsmZkue2APNjTy6*20klGBxXt& z?$&mu_M-o_xw+1S;kmGZCQk&n7V4e?PWzWzYdAT@j9OnnJ^)#X@>qz)`(Cm7$@?$n zKX~!UbzIzn35|L&!sRSVR0lxbSg)_Fg4z)t5CZ1>1doyb9xV5e$|LCtPEPZJwG$m5 zYo&)ImV^=_tj19FISb@Zf4T&-LdYzrN@*>RCFwsPU?P!-L=GO*S3GAslN|>SGVfBG zTL1jMS7=*T>uO!Ct97-m*44UNSLu C7}!4m literal 0 HcmV?d00001 diff --git a/.TemporaryDocument/assetpilot.ico b/.TemporaryDocument/assetpilot.ico new file mode 100644 index 0000000000000000000000000000000000000000..e3a3172f97d5d847afa7e29260fc1c507a8663f9 GIT binary patch literal 237700 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 + + + +

?z}=oTtnu@3SqA3-Tk!2tJo}rF@`%!e{Wgq(|0M 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 b0QdhNSoweu)XH0~00000NkvXXu0mjfY1UV4 literal 0 HcmV?d00001 diff --git a/.TemporaryDocument/claude.md b/.TemporaryDocument/claude.md new file mode 100644 index 0000000..46e1187 --- /dev/null +++ b/.TemporaryDocument/claude.md @@ -0,0 +1,130 @@ +이걸 postgresql 도커 따로 개발프로그램 실행 도커 따로 이렇게 설치하고 싶은데 과정알려줘 + +오전 8:10 + +4개의 파일 생성됨, 명령 4개 실행함 +이제 다시 파일들을 생성하겠습니다. + + +명령 3개 실행함 +좋습니다! 이제 Docker 관련 파일들을 추가하겠습니다. + + +9개의 파일 생성됨, 명령 실행함 +이제 프로젝트를 압축하여 제공하겠습니다. + + +명령 2개 실행함, 파일 생성됨 +완벽합니다! 이제 모든 파일을 제공하겠습니다. + + +Presented 2 files +완료했습니다! 🐳 + +📦 Docker 버전 제공 완료 +제공된 파일 +asset_pilot_docker.tar.gz - Docker 기반 전체 패키지 +DOCKER_QUICKSTART.md - Docker 빠른 시작 가이드 +🐳 Docker 설치 방식의 장점 +독립된 컨테이너 구조 +PostgreSQL Container (DB) ←→ App Container (FastAPI) + ↓ ↓ +Volume (postgres_data) Volume (app_logs) +주요 이점: + +✅ PostgreSQL과 앱이 별도 컨테이너로 완전 격리 +✅ 한 번의 명령으로 전체 시스템 실행 +✅ 컨테이너별 독립적 재시작 가능 +✅ 볼륨으로 데이터 영구 저장 +✅ 백업/복원 매우 간단 +✅ 이식성 최고 (다른 서버로 쉽게 이동) +🚀 설치 과정 +초간단 설치 (3단계) +bash +# 1. 압축 해제 +tar -xzf asset_pilot_docker.tar.gz +cd asset_pilot_docker + +# 2. 자동 설치 실행 +bash start.sh + +# 3. 완료! 접속 +# http://[IP]:8000 +start.sh 스크립트가 자동으로: +Docker 설치 확인 (없으면 자동 설치) +Docker Compose 확인 (없으면 자동 설치) +비밀번호 입력 받아 .env 파일 생성 +PostgreSQL 컨테이너 시작 +App 컨테이너 빌드 및 시작 +데이터베이스 자동 초기화 +접속 URL 안내 +🔧 주요 관리 명령어 +컨테이너 관리 +bash +docker compose up -d # 시작 (백그라운드) +docker compose down # 중지 +docker compose ps # 상태 확인 +docker compose logs -f # 로그 실시간 +docker compose restart app # 앱만 재시작 +데이터 관리 +bash +# 백업 +docker compose exec postgres pg_dump -U asset_user asset_pilot > backup.sql + +# 복원 +cat backup.sql | docker compose exec -T postgres psql -U asset_user -d asset_pilot + +# CSV 가져오기 +docker cp user_assets.csv asset_pilot_app:/app/ +docker compose exec app python import_csv.py user_assets.csv +📊 컨테이너 구성 상세 +PostgreSQL 컨테이너 +이미지: postgres:16-alpine (경량) +포트: 5432 (내부 네트워크만) +볼륨: postgres_data (데이터 영구 저장) +헬스체크: 자동 상태 확인 +App 컨테이너 +이미지: 자체 빌드 (Python 3.11) +포트: 8000 (외부 접근 가능) +의존성: PostgreSQL 준비 완료 후 시작 +헬스체크: /health 엔드포인트 확인 +🔄 업데이트 방법 +bash +# 코드 업데이트 후 +docker compose build app # 이미지 재빌드 +docker compose up -d app # 앱만 재시작 +🔐 보안 설정 +PostgreSQL: 내부 네트워크만 접근 +.env 파일: 권한 600 (소유자만 읽기/쓰기) +방화벽: 8000번 포트만 개방 +비루트 사용자: 컨테이너 내부에서 appuser로 실행 +💡 일반 설치 vs Docker 설치 +항목 일반 설치 Docker 설치 +설치 난이도 중간 (여러 단계) 쉬움 (3단계) +의존성 관리 수동 설치 필요 자동 처리 +환경 격리 없음 완벽 +백업 수동 (복잡) 간단 +업데이트 복잡 쉬움 +롤백 어려움 쉬움 +이식성 낮음 높음 +리소스 가벼움 약간 더 사용 +📚 포함된 문서 +프로젝트 내부 (압축 해제 후): + +README.md - 프로젝트 개요 +DOCKER_GUIDE.md - 상세 설치/관리 가이드 +docker-compose.yml - 컨테이너 설정 +Dockerfile - 앱 이미지 빌드 설정 +start.sh - 자동 설치 스크립트 +🎯 권장 사용 시나리오 +Docker 설치 추천: + +✅ 깔끔한 환경 원할 때 +✅ 쉬운 백업/복원 필요할 때 +✅ 여러 서버에 배포할 때 +✅ 컨테이너 기술 선호할 때 +일반 설치 추천: + +✅ Docker 없는 환경 +✅ 최소 리소스 사용 +✅ 직접 제어 선호 \ No newline at end of file diff --git a/.TemporaryDocument/필요 Linux명령들 모음.md b/.TemporaryDocument/필요 Linux명령들 모음.md new file mode 100644 index 0000000..d7aa653 --- /dev/null +++ b/.TemporaryDocument/필요 Linux명령들 모음.md @@ -0,0 +1,21 @@ +# 프로그램 수정후 +docker compose up -d --build + +# 실행을 터미널 에서 보고 싶으면 +docker compose logs -f app + + +# AssetPilot의 오렌지 파이 리소스 부하 확인하고 싶으면 +docker stats asset_pilot_app asset_pilot_db + +# docker compose down 해야 하는 경우 +보통의 코드 수정(Python 파일 수정 등)에는 up --build만으로 충분하지만, 아래 상황에서는 down을 먼저 하는 것이 깔끔합니다. + +포트 변경: docker-compose.yml에서 ports 설정을 바꿨을 때. + +네트워크 구조 변경: 서비스 간의 네트워크 연결 방식을 크게 수정했을 때. + +완전 초기화: volumes에 쌓인 데이터까지 싹 지우고 새로 시작하고 싶을 때 (이때는 docker compose down -v). + +좀비 컨테이너: 가끔 도커 엔진의 버그로 컨테이너가 정상적으로 교체되지 않고 꼬여있을 때. + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7fbbdf2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +__pycache__/ +*.py[cod] +postgres_data/ # DB 데이터는 따로 관리 +.env # 비밀번호 등 민감 정보 \ No newline at end of file diff --git a/asset_pilot_docker/.gitignore b/asset_pilot_docker/.gitignore new file mode 100644 index 0000000..b0943a2 --- /dev/null +++ b/asset_pilot_docker/.gitignore @@ -0,0 +1,59 @@ +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +venv/ +env/ +ENV/ + +# 환경 변수 +.env +.env.local + +# 데이터베이스 +*.db +*.sqlite +*.sqlite3 + +# 로그 +*.log +logs/ + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS +.DS_Store +Thumbs.db + +# CSV 데이터 +*.csv +!example.csv + +# 백업 파일 +*.sql +backup/ + +# Docker +.dockerignore diff --git a/asset_pilot_docker/.venv/bin/Activate.ps1 b/asset_pilot_docker/.venv/bin/Activate.ps1 new file mode 100644 index 0000000..b49d77b --- /dev/null +++ b/asset_pilot_docker/.venv/bin/Activate.ps1 @@ -0,0 +1,247 @@ +<# +.Synopsis +Activate a Python virtual environment for the current PowerShell session. + +.Description +Pushes the python executable for a virtual environment to the front of the +$Env:PATH environment variable and sets the prompt to signify that you are +in a Python virtual environment. Makes use of the command line switches as +well as the `pyvenv.cfg` file values present in the virtual environment. + +.Parameter VenvDir +Path to the directory that contains the virtual environment to activate. The +default value for this is the parent of the directory that the Activate.ps1 +script is located within. + +.Parameter Prompt +The prompt prefix to display when this virtual environment is activated. By +default, this prompt is the name of the virtual environment folder (VenvDir) +surrounded by parentheses and followed by a single space (ie. '(.venv) '). + +.Example +Activate.ps1 +Activates the Python virtual environment that contains the Activate.ps1 script. + +.Example +Activate.ps1 -Verbose +Activates the Python virtual environment that contains the Activate.ps1 script, +and shows extra information about the activation as it executes. + +.Example +Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv +Activates the Python virtual environment located in the specified location. + +.Example +Activate.ps1 -Prompt "MyPython" +Activates the Python virtual environment that contains the Activate.ps1 script, +and prefixes the current prompt with the specified string (surrounded in +parentheses) while the virtual environment is active. + +.Notes +On Windows, it may be required to enable this Activate.ps1 script by setting the +execution policy for the user. You can do this by issuing the following PowerShell +command: + +PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser + +For more information on Execution Policies: +https://go.microsoft.com/fwlink/?LinkID=135170 + +#> +Param( + [Parameter(Mandatory = $false)] + [String] + $VenvDir, + [Parameter(Mandatory = $false)] + [String] + $Prompt +) + +<# Function declarations --------------------------------------------------- #> + +<# +.Synopsis +Remove all shell session elements added by the Activate script, including the +addition of the virtual environment's Python executable from the beginning of +the PATH variable. + +.Parameter NonDestructive +If present, do not remove this function from the global namespace for the +session. + +#> +function global:deactivate ([switch]$NonDestructive) { + # Revert to original values + + # The prior prompt: + if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) { + Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt + Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT + } + + # The prior PYTHONHOME: + if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) { + Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME + Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME + } + + # The prior PATH: + if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) { + Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH + Remove-Item -Path Env:_OLD_VIRTUAL_PATH + } + + # Just remove the VIRTUAL_ENV altogether: + if (Test-Path -Path Env:VIRTUAL_ENV) { + Remove-Item -Path env:VIRTUAL_ENV + } + + # Just remove VIRTUAL_ENV_PROMPT altogether. + if (Test-Path -Path Env:VIRTUAL_ENV_PROMPT) { + Remove-Item -Path env:VIRTUAL_ENV_PROMPT + } + + # Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether: + if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) { + Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force + } + + # Leave deactivate function in the global namespace if requested: + if (-not $NonDestructive) { + Remove-Item -Path function:deactivate + } +} + +<# +.Description +Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the +given folder, and returns them in a map. + +For each line in the pyvenv.cfg file, if that line can be parsed into exactly +two strings separated by `=` (with any amount of whitespace surrounding the =) +then it is considered a `key = value` line. The left hand string is the key, +the right hand is the value. + +If the value starts with a `'` or a `"` then the first and last character is +stripped from the value before being captured. + +.Parameter ConfigDir +Path to the directory that contains the `pyvenv.cfg` file. +#> +function Get-PyVenvConfig( + [String] + $ConfigDir +) { + Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg" + + # Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue). + $pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue + + # An empty map will be returned if no config file is found. + $pyvenvConfig = @{ } + + if ($pyvenvConfigPath) { + + Write-Verbose "File exists, parse `key = value` lines" + $pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath + + $pyvenvConfigContent | ForEach-Object { + $keyval = $PSItem -split "\s*=\s*", 2 + if ($keyval[0] -and $keyval[1]) { + $val = $keyval[1] + + # Remove extraneous quotations around a string value. + if ("'""".Contains($val.Substring(0, 1))) { + $val = $val.Substring(1, $val.Length - 2) + } + + $pyvenvConfig[$keyval[0]] = $val + Write-Verbose "Adding Key: '$($keyval[0])'='$val'" + } + } + } + return $pyvenvConfig +} + + +<# Begin Activate script --------------------------------------------------- #> + +# Determine the containing directory of this script +$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition +$VenvExecDir = Get-Item -Path $VenvExecPath + +Write-Verbose "Activation script is located in path: '$VenvExecPath'" +Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)" +Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)" + +# Set values required in priority: CmdLine, ConfigFile, Default +# First, get the location of the virtual environment, it might not be +# VenvExecDir if specified on the command line. +if ($VenvDir) { + Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values" +} +else { + Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir." + $VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/") + Write-Verbose "VenvDir=$VenvDir" +} + +# Next, read the `pyvenv.cfg` file to determine any required value such +# as `prompt`. +$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir + +# Next, set the prompt from the command line, or the config file, or +# just use the name of the virtual environment folder. +if ($Prompt) { + Write-Verbose "Prompt specified as argument, using '$Prompt'" +} +else { + Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value" + if ($pyvenvCfg -and $pyvenvCfg['prompt']) { + Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'" + $Prompt = $pyvenvCfg['prompt']; + } + else { + Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virtual environment)" + Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'" + $Prompt = Split-Path -Path $venvDir -Leaf + } +} + +Write-Verbose "Prompt = '$Prompt'" +Write-Verbose "VenvDir='$VenvDir'" + +# Deactivate any currently active virtual environment, but leave the +# deactivate function in place. +deactivate -nondestructive + +# Now set the environment variable VIRTUAL_ENV, used by many tools to determine +# that there is an activated venv. +$env:VIRTUAL_ENV = $VenvDir + +if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) { + + Write-Verbose "Setting prompt to '$Prompt'" + + # Set the prompt to include the env name + # Make sure _OLD_VIRTUAL_PROMPT is global + function global:_OLD_VIRTUAL_PROMPT { "" } + Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT + New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt + + function global:prompt { + Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) " + _OLD_VIRTUAL_PROMPT + } + $env:VIRTUAL_ENV_PROMPT = $Prompt +} + +# Clear PYTHONHOME +if (Test-Path -Path Env:PYTHONHOME) { + Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME + Remove-Item -Path Env:PYTHONHOME +} + +# Add the venv to the PATH +Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH +$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH" diff --git a/asset_pilot_docker/.venv/bin/activate b/asset_pilot_docker/.venv/bin/activate new file mode 100644 index 0000000..6d11f77 --- /dev/null +++ b/asset_pilot_docker/.venv/bin/activate @@ -0,0 +1,70 @@ +# This file must be used with "source bin/activate" *from bash* +# You cannot run it directly + +deactivate () { + # reset old environment variables + if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then + PATH="${_OLD_VIRTUAL_PATH:-}" + export PATH + unset _OLD_VIRTUAL_PATH + fi + if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then + PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}" + export PYTHONHOME + unset _OLD_VIRTUAL_PYTHONHOME + fi + + # Call hash to forget past commands. Without forgetting + # past commands the $PATH changes we made may not be respected + hash -r 2> /dev/null + + if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then + PS1="${_OLD_VIRTUAL_PS1:-}" + export PS1 + unset _OLD_VIRTUAL_PS1 + fi + + unset VIRTUAL_ENV + unset VIRTUAL_ENV_PROMPT + if [ ! "${1:-}" = "nondestructive" ] ; then + # Self destruct! + unset -f deactivate + fi +} + +# unset irrelevant variables +deactivate nondestructive + +# on Windows, a path can contain colons and backslashes and has to be converted: +if [ "${OSTYPE:-}" = "cygwin" ] || [ "${OSTYPE:-}" = "msys" ] ; then + # transform D:\path\to\venv to /d/path/to/venv on MSYS + # and to /cygdrive/d/path/to/venv on Cygwin + export VIRTUAL_ENV=$(cygpath /home/ubuntu/AssetPilot/asset_pilot_docker/.venv) +else + # use the path as-is + export VIRTUAL_ENV=/home/ubuntu/AssetPilot/asset_pilot_docker/.venv +fi + +_OLD_VIRTUAL_PATH="$PATH" +PATH="$VIRTUAL_ENV/"bin":$PATH" +export PATH + +# unset PYTHONHOME if set +# this will fail if PYTHONHOME is set to the empty string (which is bad anyway) +# could use `if (set -u; : $PYTHONHOME) ;` in bash +if [ -n "${PYTHONHOME:-}" ] ; then + _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}" + unset PYTHONHOME +fi + +if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then + _OLD_VIRTUAL_PS1="${PS1:-}" + PS1='(.venv) '"${PS1:-}" + export PS1 + VIRTUAL_ENV_PROMPT='(.venv) ' + export VIRTUAL_ENV_PROMPT +fi + +# Call hash to forget past commands. Without forgetting +# past commands the $PATH changes we made may not be respected +hash -r 2> /dev/null diff --git a/asset_pilot_docker/.venv/bin/activate.csh b/asset_pilot_docker/.venv/bin/activate.csh new file mode 100644 index 0000000..bf55dc8 --- /dev/null +++ b/asset_pilot_docker/.venv/bin/activate.csh @@ -0,0 +1,27 @@ +# This file must be used with "source bin/activate.csh" *from csh*. +# You cannot run it directly. + +# Created by Davide Di Blasi . +# Ported to Python 3.3 venv by Andrew Svetlov + +alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; unsetenv VIRTUAL_ENV_PROMPT; test "\!:*" != "nondestructive" && unalias deactivate' + +# Unset irrelevant variables. +deactivate nondestructive + +setenv VIRTUAL_ENV /home/ubuntu/AssetPilot/asset_pilot_docker/.venv + +set _OLD_VIRTUAL_PATH="$PATH" +setenv PATH "$VIRTUAL_ENV/"bin":$PATH" + + +set _OLD_VIRTUAL_PROMPT="$prompt" + +if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then + set prompt = '(.venv) '"$prompt" + setenv VIRTUAL_ENV_PROMPT '(.venv) ' +endif + +alias pydoc python -m pydoc + +rehash diff --git a/asset_pilot_docker/.venv/bin/activate.fish b/asset_pilot_docker/.venv/bin/activate.fish new file mode 100644 index 0000000..b987b26 --- /dev/null +++ b/asset_pilot_docker/.venv/bin/activate.fish @@ -0,0 +1,69 @@ +# This file must be used with "source /bin/activate.fish" *from fish* +# (https://fishshell.com/). You cannot run it directly. + +function deactivate -d "Exit virtual environment and return to normal shell environment" + # reset old environment variables + if test -n "$_OLD_VIRTUAL_PATH" + set -gx PATH $_OLD_VIRTUAL_PATH + set -e _OLD_VIRTUAL_PATH + end + if test -n "$_OLD_VIRTUAL_PYTHONHOME" + set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME + set -e _OLD_VIRTUAL_PYTHONHOME + end + + if test -n "$_OLD_FISH_PROMPT_OVERRIDE" + set -e _OLD_FISH_PROMPT_OVERRIDE + # prevents error when using nested fish instances (Issue #93858) + if functions -q _old_fish_prompt + functions -e fish_prompt + functions -c _old_fish_prompt fish_prompt + functions -e _old_fish_prompt + end + end + + set -e VIRTUAL_ENV + set -e VIRTUAL_ENV_PROMPT + if test "$argv[1]" != "nondestructive" + # Self-destruct! + functions -e deactivate + end +end + +# Unset irrelevant variables. +deactivate nondestructive + +set -gx VIRTUAL_ENV /home/ubuntu/AssetPilot/asset_pilot_docker/.venv + +set -gx _OLD_VIRTUAL_PATH $PATH +set -gx PATH "$VIRTUAL_ENV/"bin $PATH + +# Unset PYTHONHOME if set. +if set -q PYTHONHOME + set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME + set -e PYTHONHOME +end + +if test -z "$VIRTUAL_ENV_DISABLE_PROMPT" + # fish uses a function instead of an env var to generate the prompt. + + # Save the current fish_prompt function as the function _old_fish_prompt. + functions -c fish_prompt _old_fish_prompt + + # With the original prompt function renamed, we can override with our own. + function fish_prompt + # Save the return status of the last command. + set -l old_status $status + + # Output the venv prompt; color taken from the blue of the Python logo. + printf "%s%s%s" (set_color 4B8BBE) '(.venv) ' (set_color normal) + + # Restore the return status of the previous command. + echo "exit $old_status" | . + # Output the original/"old" prompt. + _old_fish_prompt + end + + set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV" + set -gx VIRTUAL_ENV_PROMPT '(.venv) ' +end diff --git a/asset_pilot_docker/.venv/bin/dotenv b/asset_pilot_docker/.venv/bin/dotenv new file mode 100755 index 0000000..f3b29bb --- /dev/null +++ b/asset_pilot_docker/.venv/bin/dotenv @@ -0,0 +1,8 @@ +#!/home/ubuntu/AssetPilot/asset_pilot_docker/.venv/bin/python3 +# -*- coding: utf-8 -*- +import re +import sys +from dotenv.__main__ import cli +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(cli()) diff --git a/asset_pilot_docker/.venv/bin/normalizer b/asset_pilot_docker/.venv/bin/normalizer new file mode 100755 index 0000000..88d04e9 --- /dev/null +++ b/asset_pilot_docker/.venv/bin/normalizer @@ -0,0 +1,8 @@ +#!/home/ubuntu/AssetPilot/asset_pilot_docker/.venv/bin/python3 +# -*- coding: utf-8 -*- +import re +import sys +from charset_normalizer.cli import cli_detect +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(cli_detect()) diff --git a/asset_pilot_docker/.venv/bin/pip b/asset_pilot_docker/.venv/bin/pip new file mode 100755 index 0000000..84f91bc --- /dev/null +++ b/asset_pilot_docker/.venv/bin/pip @@ -0,0 +1,8 @@ +#!/home/ubuntu/AssetPilot/asset_pilot_docker/.venv/bin/python3 +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/asset_pilot_docker/.venv/bin/pip3 b/asset_pilot_docker/.venv/bin/pip3 new file mode 100755 index 0000000..84f91bc --- /dev/null +++ b/asset_pilot_docker/.venv/bin/pip3 @@ -0,0 +1,8 @@ +#!/home/ubuntu/AssetPilot/asset_pilot_docker/.venv/bin/python3 +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/asset_pilot_docker/.venv/bin/pip3.12 b/asset_pilot_docker/.venv/bin/pip3.12 new file mode 100755 index 0000000..84f91bc --- /dev/null +++ b/asset_pilot_docker/.venv/bin/pip3.12 @@ -0,0 +1,8 @@ +#!/home/ubuntu/AssetPilot/asset_pilot_docker/.venv/bin/python3 +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/asset_pilot_docker/.venv/bin/python b/asset_pilot_docker/.venv/bin/python new file mode 120000 index 0000000..b8a0adb --- /dev/null +++ b/asset_pilot_docker/.venv/bin/python @@ -0,0 +1 @@ +python3 \ No newline at end of file diff --git a/asset_pilot_docker/.venv/bin/python3 b/asset_pilot_docker/.venv/bin/python3 new file mode 120000 index 0000000..ae65fda --- /dev/null +++ b/asset_pilot_docker/.venv/bin/python3 @@ -0,0 +1 @@ +/usr/bin/python3 \ No newline at end of file diff --git a/asset_pilot_docker/.venv/bin/python3.12 b/asset_pilot_docker/.venv/bin/python3.12 new file mode 120000 index 0000000..b8a0adb --- /dev/null +++ b/asset_pilot_docker/.venv/bin/python3.12 @@ -0,0 +1 @@ +python3 \ No newline at end of file diff --git a/asset_pilot_docker/.venv/bin/uvicorn b/asset_pilot_docker/.venv/bin/uvicorn new file mode 100755 index 0000000..c8ccea9 --- /dev/null +++ b/asset_pilot_docker/.venv/bin/uvicorn @@ -0,0 +1,8 @@ +#!/home/ubuntu/AssetPilot/asset_pilot_docker/.venv/bin/python3 +# -*- coding: utf-8 -*- +import re +import sys +from uvicorn.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/asset_pilot_docker/.venv/bin/watchfiles b/asset_pilot_docker/.venv/bin/watchfiles new file mode 100755 index 0000000..32f4b4a --- /dev/null +++ b/asset_pilot_docker/.venv/bin/watchfiles @@ -0,0 +1,8 @@ +#!/home/ubuntu/AssetPilot/asset_pilot_docker/.venv/bin/python3 +# -*- coding: utf-8 -*- +import re +import sys +from watchfiles.cli import cli +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(cli()) diff --git a/asset_pilot_docker/.venv/bin/websockets b/asset_pilot_docker/.venv/bin/websockets new file mode 100755 index 0000000..a3fe2bd --- /dev/null +++ b/asset_pilot_docker/.venv/bin/websockets @@ -0,0 +1,8 @@ +#!/home/ubuntu/AssetPilot/asset_pilot_docker/.venv/bin/python3 +# -*- coding: utf-8 -*- +import re +import sys +from websockets.cli import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/asset_pilot_docker/.venv/include/site/python3.12/greenlet/greenlet.h b/asset_pilot_docker/.venv/include/site/python3.12/greenlet/greenlet.h new file mode 100644 index 0000000..d02a16e --- /dev/null +++ b/asset_pilot_docker/.venv/include/site/python3.12/greenlet/greenlet.h @@ -0,0 +1,164 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; -*- */ + +/* Greenlet object interface */ + +#ifndef Py_GREENLETOBJECT_H +#define Py_GREENLETOBJECT_H + + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* This is deprecated and undocumented. It does not change. */ +#define GREENLET_VERSION "1.0.0" + +#ifndef GREENLET_MODULE +#define implementation_ptr_t void* +#endif + +typedef struct _greenlet { + PyObject_HEAD + PyObject* weakreflist; + PyObject* dict; + implementation_ptr_t pimpl; +} PyGreenlet; + +#define PyGreenlet_Check(op) (op && PyObject_TypeCheck(op, &PyGreenlet_Type)) + + +/* C API functions */ + +/* Total number of symbols that are exported */ +#define PyGreenlet_API_pointers 12 + +#define PyGreenlet_Type_NUM 0 +#define PyExc_GreenletError_NUM 1 +#define PyExc_GreenletExit_NUM 2 + +#define PyGreenlet_New_NUM 3 +#define PyGreenlet_GetCurrent_NUM 4 +#define PyGreenlet_Throw_NUM 5 +#define PyGreenlet_Switch_NUM 6 +#define PyGreenlet_SetParent_NUM 7 + +#define PyGreenlet_MAIN_NUM 8 +#define PyGreenlet_STARTED_NUM 9 +#define PyGreenlet_ACTIVE_NUM 10 +#define PyGreenlet_GET_PARENT_NUM 11 + +#ifndef GREENLET_MODULE +/* This section is used by modules that uses the greenlet C API */ +static void** _PyGreenlet_API = NULL; + +# define PyGreenlet_Type \ + (*(PyTypeObject*)_PyGreenlet_API[PyGreenlet_Type_NUM]) + +# define PyExc_GreenletError \ + ((PyObject*)_PyGreenlet_API[PyExc_GreenletError_NUM]) + +# define PyExc_GreenletExit \ + ((PyObject*)_PyGreenlet_API[PyExc_GreenletExit_NUM]) + +/* + * PyGreenlet_New(PyObject *args) + * + * greenlet.greenlet(run, parent=None) + */ +# define PyGreenlet_New \ + (*(PyGreenlet * (*)(PyObject * run, PyGreenlet * parent)) \ + _PyGreenlet_API[PyGreenlet_New_NUM]) + +/* + * PyGreenlet_GetCurrent(void) + * + * greenlet.getcurrent() + */ +# define PyGreenlet_GetCurrent \ + (*(PyGreenlet * (*)(void)) _PyGreenlet_API[PyGreenlet_GetCurrent_NUM]) + +/* + * PyGreenlet_Throw( + * PyGreenlet *greenlet, + * PyObject *typ, + * PyObject *val, + * PyObject *tb) + * + * g.throw(...) + */ +# define PyGreenlet_Throw \ + (*(PyObject * (*)(PyGreenlet * self, \ + PyObject * typ, \ + PyObject * val, \ + PyObject * tb)) \ + _PyGreenlet_API[PyGreenlet_Throw_NUM]) + +/* + * PyGreenlet_Switch(PyGreenlet *greenlet, PyObject *args) + * + * g.switch(*args, **kwargs) + */ +# define PyGreenlet_Switch \ + (*(PyObject * \ + (*)(PyGreenlet * greenlet, PyObject * args, PyObject * kwargs)) \ + _PyGreenlet_API[PyGreenlet_Switch_NUM]) + +/* + * PyGreenlet_SetParent(PyObject *greenlet, PyObject *new_parent) + * + * g.parent = new_parent + */ +# define PyGreenlet_SetParent \ + (*(int (*)(PyGreenlet * greenlet, PyGreenlet * nparent)) \ + _PyGreenlet_API[PyGreenlet_SetParent_NUM]) + +/* + * PyGreenlet_GetParent(PyObject* greenlet) + * + * return greenlet.parent; + * + * This could return NULL even if there is no exception active. + * If it does not return NULL, you are responsible for decrementing the + * reference count. + */ +# define PyGreenlet_GetParent \ + (*(PyGreenlet* (*)(PyGreenlet*)) \ + _PyGreenlet_API[PyGreenlet_GET_PARENT_NUM]) + +/* + * deprecated, undocumented alias. + */ +# define PyGreenlet_GET_PARENT PyGreenlet_GetParent + +# define PyGreenlet_MAIN \ + (*(int (*)(PyGreenlet*)) \ + _PyGreenlet_API[PyGreenlet_MAIN_NUM]) + +# define PyGreenlet_STARTED \ + (*(int (*)(PyGreenlet*)) \ + _PyGreenlet_API[PyGreenlet_STARTED_NUM]) + +# define PyGreenlet_ACTIVE \ + (*(int (*)(PyGreenlet*)) \ + _PyGreenlet_API[PyGreenlet_ACTIVE_NUM]) + + + + +/* Macro that imports greenlet and initializes C API */ +/* NOTE: This has actually moved to ``greenlet._greenlet._C_API``, but we + keep the older definition to be sure older code that might have a copy of + the header still works. */ +# define PyGreenlet_Import() \ + { \ + _PyGreenlet_API = (void**)PyCapsule_Import("greenlet._C_API", 0); \ + } + +#endif /* GREENLET_MODULE */ + +#ifdef __cplusplus +} +#endif +#endif /* !Py_GREENLETOBJECT_H */ diff --git a/asset_pilot_docker/.venv/lib64 b/asset_pilot_docker/.venv/lib64 new file mode 120000 index 0000000..7951405 --- /dev/null +++ b/asset_pilot_docker/.venv/lib64 @@ -0,0 +1 @@ +lib \ No newline at end of file diff --git a/asset_pilot_docker/.venv/pyvenv.cfg b/asset_pilot_docker/.venv/pyvenv.cfg new file mode 100644 index 0000000..404dc80 --- /dev/null +++ b/asset_pilot_docker/.venv/pyvenv.cfg @@ -0,0 +1,5 @@ +home = /usr/bin +include-system-site-packages = false +version = 3.12.3 +executable = /usr/bin/python3.12 +command = /usr/bin/python3 -m venv /home/ubuntu/AssetPilot/asset_pilot_docker/.venv diff --git a/asset_pilot_docker/DOCKER_GUIDE.md b/asset_pilot_docker/DOCKER_GUIDE.md new file mode 100644 index 0000000..58bbe53 --- /dev/null +++ b/asset_pilot_docker/DOCKER_GUIDE.md @@ -0,0 +1,420 @@ +# Asset Pilot - Docker 설치 가이드 + +## 🐳 Docker 방식의 장점 + +- ✅ 독립된 컨테이너로 깔끔한 환경 관리 +- ✅ PostgreSQL과 애플리케이션 분리 +- ✅ 한 번의 명령으로 전체 시스템 실행 +- ✅ 쉬운 백업 및 복구 +- ✅ 포트 충돌 없음 +- ✅ 업데이트 및 롤백 간편 + +--- + +## 📋 사전 준비 + +### 1. Docker 설치 + +#### Orange Pi (Ubuntu/Debian) +```bash +# Docker 설치 스크립트 +curl -fsSL https://get.docker.com -o get-docker.sh +sudo sh get-docker.sh + +# 현재 사용자를 docker 그룹에 추가 +sudo usermod -aG docker $USER + +# 로그아웃 후 재로그인 또는 +newgrp docker + +# Docker 서비스 시작 +sudo systemctl start docker +sudo systemctl enable docker +``` + +#### Docker Compose 설치 (이미 포함되어 있을 수 있음) +```bash +# Docker Compose 버전 확인 +docker compose version + +# 없다면 설치 +sudo apt-get update +sudo apt-get install docker-compose-plugin +``` + +### 2. 설치 확인 +```bash +docker --version +docker compose version +``` + +--- + +## 🚀 설치 및 실행 + +### 1단계: 파일 업로드 + +Orange Pi에 `asset_pilot_docker.tar.gz` 파일을 전송: + +```bash +# Windows에서 (PowerShell) +scp asset_pilot_docker.tar.gz orangepi@192.168.1.100:~/ + +# Linux/Mac에서 +scp asset_pilot_docker.tar.gz orangepi@192.168.1.100:~/ +``` + +### 2단계: 압축 해제 + +```bash +# SSH 접속 +ssh orangepi@192.168.1.100 + +# 압축 해제 +tar -xzf asset_pilot_docker.tar.gz +cd asset_pilot_docker +``` + +### 3단계: 환경 설정 + +```bash +# .env 파일 편집 (비밀번호 변경) +nano .env +``` + +`.env` 파일 내용: +```env +DB_PASSWORD=your_secure_password_here # 여기를 변경하세요! +``` + +저장: `Ctrl + X` → `Y` → `Enter` + +### 4단계: Docker 컨테이너 실행 + +```bash +# 백그라운드에서 실행 +docker compose up -d + +# 실행 상태 확인 +docker compose ps +``` + +출력 예시: +``` +NAME IMAGE STATUS PORTS +asset_pilot_app asset_pilot_docker-app Up 30 seconds 0.0.0.0:8000->8000/tcp +asset_pilot_db postgres:16-alpine Up 30 seconds 0.0.0.0:5432->5432/tcp +``` + +### 5단계: 데이터베이스 초기화 + +```bash +# 앱 컨테이너 내부에서 초기화 스크립트 실행 +docker compose exec app python init_db.py +``` + +### 6단계: 접속 확인 + +웹 브라우저에서: +``` +http://[Orange_Pi_IP]:8000 +``` + +예: `http://192.168.1.100:8000` + +--- + +## 🔧 Docker 관리 명령어 + +### 컨테이너 관리 + +```bash +# 전체 시작 +docker compose up -d + +# 전체 중지 +docker compose down + +# 전체 재시작 +docker compose restart + +# 특정 서비스만 재시작 +docker compose restart app # 앱만 +docker compose restart postgres # DB만 + +# 상태 확인 +docker compose ps + +# 로그 확인 (실시간) +docker compose logs -f + +# 특정 서비스 로그만 +docker compose logs -f app +docker compose logs -f postgres +``` + +### 데이터베이스 관리 + +```bash +# PostgreSQL 컨테이너 접속 +docker compose exec postgres psql -U asset_user -d asset_pilot + +# SQL 쿼리 실행 예시 +# \dt # 테이블 목록 +# \d assets # assets 테이블 구조 +# SELECT * FROM assets; +# \q # 종료 +``` + +### 애플리케이션 관리 + +```bash +# 앱 컨테이너 내부 접속 +docker compose exec app /bin/bash + +# 컨테이너 내부에서 Python 스크립트 실행 +docker compose exec app python init_db.py +``` + +--- + +## 📊 데이터 관리 + +### 백업 + +#### 데이터베이스 백업 +```bash +# 백업 생성 +docker compose exec postgres pg_dump -U asset_user asset_pilot > backup_$(date +%Y%m%d).sql + +# 또는 +docker compose exec -T postgres pg_dump -U asset_user asset_pilot > backup.sql +``` + +#### 전체 볼륨 백업 +```bash +# 볼륨 백업 (고급) +docker run --rm -v asset_pilot_docker_postgres_data:/data \ + -v $(pwd):/backup alpine tar czf /backup/postgres_backup.tar.gz /data +``` + +### 복원 + +```bash +# 백업 파일 복원 +cat backup.sql | docker compose exec -T postgres psql -U asset_user -d asset_pilot +``` + +### CSV 데이터 가져오기 (Windows 앱에서) + +```bash +# 1. CSV 파일을 컨테이너로 복사 +docker cp user_assets.csv asset_pilot_app:/app/ + +# 2. import_csv.py 생성 (아래 스크립트 참고) +docker compose exec app python import_csv.py user_assets.csv +``` + +--- + +## 🔄 업데이트 + +### 애플리케이션 업데이트 + +```bash +# 1. 새 코드 받기 (파일 업로드 또는 git pull) + +# 2. 이미지 재빌드 +docker compose build app + +# 3. 재시작 +docker compose up -d app +``` + +### PostgreSQL 업데이트 + +```bash +# 주의: 데이터 백업 필수! +# 1. 백업 생성 +docker compose exec -T postgres pg_dump -U asset_user asset_pilot > backup.sql + +# 2. docker-compose.yml에서 버전 변경 (예: postgres:17-alpine) + +# 3. 컨테이너 재생성 +docker compose down +docker compose up -d +``` + +--- + +## 🗑️ 완전 삭제 + +```bash +# 컨테이너 중지 및 삭제 +docker compose down + +# 볼륨까지 삭제 (데이터 완전 삭제!) +docker compose down -v + +# 이미지도 삭제 +docker rmi asset_pilot_docker-app postgres:16-alpine +``` + +--- + +## 🛠️ 문제 해결 + +### 컨테이너가 시작되지 않음 + +```bash +# 로그 확인 +docker compose logs + +# 특정 서비스 로그 +docker compose logs app +docker compose logs postgres + +# 컨테이너 상태 확인 +docker compose ps -a +``` + +### 데이터베이스 연결 오류 + +```bash +# PostgreSQL 컨테이너 헬스체크 +docker compose exec postgres pg_isready -U asset_user -d asset_pilot + +# 연결 테스트 +docker compose exec postgres psql -U asset_user -d asset_pilot -c "SELECT 1;" +``` + +### 포트 충돌 + +```bash +# 8000번 포트 사용 확인 +sudo lsof -i :8000 + +# docker-compose.yml에서 포트 변경 (예: 8001:8000) +``` + +### 디스크 공간 부족 + +```bash +# 사용하지 않는 Docker 리소스 정리 +docker system prune -a + +# 볼륨 확인 +docker volume ls +``` + +--- + +## 📱 원격 접근 설정 + +### Nginx 리버스 프록시 (선택적) + +```bash +# Nginx 설치 +sudo apt install nginx + +# 설정 파일 생성 +sudo nano /etc/nginx/sites-available/asset_pilot +``` + +설정 내용: +```nginx +server { + listen 80; + server_name your_domain.com; # 또는 IP 주소 + + location / { + proxy_pass http://localhost:8000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location /api/stream { + proxy_pass http://localhost:8000/api/stream; + proxy_http_version 1.1; + proxy_set_header Connection ""; + proxy_buffering off; + proxy_cache off; + } +} +``` + +활성화: +```bash +sudo ln -s /etc/nginx/sites-available/asset_pilot /etc/nginx/sites-enabled/ +sudo nginx -t +sudo systemctl restart nginx +``` + +--- + +## 🔐 보안 권장사항 + +### 1. .env 파일 보호 +```bash +chmod 600 .env +``` + +### 2. 방화벽 설정 +```bash +# 8000번 포트만 허용 (외부 접근 시) +sudo ufw allow 8000/tcp + +# PostgreSQL 포트는 외부 차단 (기본값) +sudo ufw deny 5432/tcp +``` + +### 3. 정기 백업 +```bash +# cron으로 매일 자동 백업 +crontab -e + +# 추가 (매일 새벽 3시) +0 3 * * * cd /home/orangepi/asset_pilot_docker && docker compose exec -T postgres pg_dump -U asset_user asset_pilot > backup_$(date +\%Y\%m\%d).sql +``` + +--- + +## 📊 시스템 리소스 모니터링 + +```bash +# 컨테이너 리소스 사용량 +docker stats + +# 특정 컨테이너만 +docker stats asset_pilot_app asset_pilot_db +``` + +--- + +## ✅ 설치 체크리스트 + +- [ ] Docker 설치 완료 +- [ ] Docker Compose 설치 완료 +- [ ] 프로젝트 파일 압축 해제 +- [ ] .env 파일 비밀번호 설정 +- [ ] `docker compose up -d` 실행 +- [ ] 컨테이너 상태 확인 (`docker compose ps`) +- [ ] 데이터베이스 초기화 (`docker compose exec app python init_db.py`) +- [ ] 웹 브라우저 접속 확인 (`http://[IP]:8000`) +- [ ] 데이터 수집 동작 확인 + +--- + +## 🎉 완료! + +모든 과정이 완료되면 다음 URL로 접속하세요: +``` +http://[Orange_Pi_IP]:8000 +``` + +문제가 발생하면 로그를 확인하세요: +```bash +docker compose logs -f +``` diff --git a/asset_pilot_docker/Dockerfile b/asset_pilot_docker/Dockerfile new file mode 100644 index 0000000..2dc650f --- /dev/null +++ b/asset_pilot_docker/Dockerfile @@ -0,0 +1,34 @@ +FROM python:3.11-slim + +# 작업 디렉토리 설정 +WORKDIR /app + +# 시스템 패키지 업데이트 및 필수 패키지 설치 +RUN apt-get update && apt-get install -y \ + gcc \ + postgresql-client \ + libpq-dev \ + curl \ + && rm -rf /var/lib/apt/lists/* + +# Python 의존성 파일 복사 및 설치 +COPY requirements.txt . +RUN pip install --no-cache-dir --upgrade pip && \ + pip install --no-cache-dir -r requirements.txt + +# 애플리케이션 파일 복사 (구조를 유지하며 복사) +COPY . . + +# 로그 디렉토리 생성 +RUN mkdir -p /app/logs + +# 비루트 사용자 생성 및 권한 설정 +RUN useradd -m -u 1000 appuser && \ + chown -R appuser:appuser /app +USER appuser + +# 헬스체크 엔드포인트 노출 +EXPOSE 8000 + +# 컨테이너 시작 시 실행할 명령어 (uvicorn으로 직접 실행 권장) +CMD ["python", "main.py"] \ No newline at end of file diff --git a/asset_pilot_docker/README.md b/asset_pilot_docker/README.md new file mode 100644 index 0000000..8536a81 --- /dev/null +++ b/asset_pilot_docker/README.md @@ -0,0 +1,159 @@ +# Asset Pilot - Docker Edition + +🐳 Docker 컨테이너 기반 자산 모니터링 시스템 + +## 📦 구성 + +이 프로젝트는 2개의 독립된 Docker 컨테이너로 구성됩니다: + +1. **PostgreSQL 컨테이너** (`asset_pilot_db`) + - 데이터베이스 서버 + - 포트: 5432 + - 볼륨: `postgres_data` + +2. **Asset Pilot 앱 컨테이너** (`asset_pilot_app`) + - FastAPI 웹 애플리케이션 + - 포트: 8000 + - 실시간 데이터 수집 및 제공 + +## 🚀 빠른 시작 + +### 자동 설치 (권장) + +```bash +# 압축 해제 +tar -xzf asset_pilot_docker.tar.gz +cd asset_pilot_docker + +# 자동 설치 스크립트 실행 +bash start.sh +``` + +### 수동 설치 + +```bash +# 1. 환경 변수 설정 +nano .env +# DB_PASSWORD를 원하는 비밀번호로 변경 + +# 2. Docker 컨테이너 시작 +docker compose up -d + +# 3. 데이터베이스 초기화 +docker compose exec app python init_db.py + +# 4. 브라우저에서 접속 +# http://[IP주소]:8000 +``` + +## 📁 디렉토리 구조 + +``` +asset_pilot_docker/ +├── app/ # 애플리케이션 코드 +│ ├── calculator.py +│ ├── database.py +│ ├── fetcher.py +│ └── models.py +├── static/ # 정적 파일 +│ ├── css/ +│ └── js/ +├── templates/ # HTML 템플릿 +│ └── index.html +├── docker-compose.yml # Docker Compose 설정 +├── Dockerfile # 앱 컨테이너 이미지 +├── .env # 환경 변수 +├── main.py # FastAPI 메인 +├── init_db.py # DB 초기화 +├── import_csv.py # CSV 가져오기 +├── start.sh # 자동 설치 스크립트 +└── DOCKER_GUIDE.md # 상세 가이드 +``` + +## 🔧 주요 명령어 + +### 컨테이너 관리 +```bash +# 시작 +docker compose up -d + +# 중지 +docker compose down + +# 재시작 +docker compose restart + +# 상태 확인 +docker compose ps + +# 로그 보기 +docker compose logs -f +``` + +### 데이터 관리 +```bash +# DB 백업 +docker compose exec postgres pg_dump -U asset_user asset_pilot > backup.sql + +# DB 복원 +cat backup.sql | docker compose exec -T postgres psql -U asset_user -d asset_pilot + +# CSV 가져오기 +docker cp user_assets.csv asset_pilot_app:/app/ +docker compose exec app python import_csv.py user_assets.csv +``` + +## 🌐 접속 + +``` +http://localhost:8000 # 로컬 +http://[IP주소]:8000 # 네트워크 +``` + +## 📚 문서 + +- **DOCKER_GUIDE.md** - Docker 상세 설치 및 관리 가이드 +- 문제 해결, 백업, 업데이트 방법 포함 + +## 🔐 보안 + +- `.env` 파일에 비밀번호 저장 (권한: 600) +- PostgreSQL은 내부 네트워크만 접근 가능 +- 방화벽에서 필요한 포트만 개방 + +## 🆘 문제 해결 + +### 컨테이너가 시작되지 않음 +```bash +docker compose logs +``` + +### 데이터베이스 연결 오류 +```bash +docker compose exec postgres pg_isready -U asset_user -d asset_pilot +``` + +### 포트 충돌 +```bash +# docker-compose.yml에서 포트 변경 +# "8001:8000" 으로 수정 +``` + +## 📊 시스템 요구사항 + +- Docker 20.10+ +- Docker Compose 2.0+ +- 최소 2GB RAM +- 최소 5GB 디스크 공간 + +## 🎯 특징 + +✅ 독립된 컨테이너로 시스템 격리 +✅ 한 번의 명령으로 전체 시스템 실행 +✅ 쉬운 백업 및 복구 +✅ 업데이트 및 롤백 간편 +✅ 개발/프로덕션 환경 일관성 + +--- + +**Asset Pilot Docker Edition v1.0** diff --git a/asset_pilot_docker/app/calculator.py b/asset_pilot_docker/app/calculator.py new file mode 100644 index 0000000..13220e6 --- /dev/null +++ b/asset_pilot_docker/app/calculator.py @@ -0,0 +1,59 @@ +from typing import Dict, Optional + +class Calculator: + """손익 계산 클래스""" + + @staticmethod + def calc_pnl( + gold_buy_price: float, + gold_quantity: float, + btc_buy_price: float, + btc_quantity: float, + current_gold: Optional[float], + current_btc: Optional[float] + ) -> Dict: + """ + 금과 BTC의 손익 계산 + + Returns: + { + "금손익": float, + "금손익%": float, + "BTC손익": float, + "BTC손익%": float, + "총손익": float, + "총손익%": float + } + """ + result = { + "금손익": 0.0, + "금손익%": 0.0, + "BTC손익": 0.0, + "BTC손익%": 0.0, + "총손익": 0.0, + "총손익%": 0.0 + } + + # 금 손익 계산 + if current_gold: + cost_gold = gold_buy_price * gold_quantity + pnl_gold = gold_quantity * (float(current_gold) - gold_buy_price) + result["금손익"] = round(pnl_gold, 0) + if cost_gold > 0: + result["금손익%"] = round((pnl_gold / cost_gold * 100), 2) + + # BTC 손익 계산 + if current_btc: + cost_btc = btc_buy_price * btc_quantity + pnl_btc = btc_quantity * (float(current_btc) - btc_buy_price) + result["BTC손익"] = round(pnl_btc, 0) + if cost_btc > 0: + result["BTC손익%"] = round((pnl_btc / cost_btc * 100), 2) + + # 총 손익 계산 + result["총손익"] = result["금손익"] + result["BTC손익"] + total_cost = (gold_buy_price * gold_quantity) + (btc_buy_price * btc_quantity) + if total_cost > 0: + result["총손익%"] = round((result["총손익"] / total_cost * 100), 2) + + return result diff --git a/asset_pilot_docker/app/database.py b/asset_pilot_docker/app/database.py new file mode 100644 index 0000000..85c9eaf --- /dev/null +++ b/asset_pilot_docker/app/database.py @@ -0,0 +1,29 @@ +import os +from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker +from dotenv import load_dotenv + +load_dotenv() + +# 데이터베이스 URL 가져오기 +DATABASE_URL = os.getenv("DATABASE_URL", "postgresql://asset_user:password@localhost/asset_pilot") + +# SQLAlchemy 엔진 생성 +engine = create_engine( + DATABASE_URL, + pool_size=10, + max_overflow=20, + pool_pre_ping=True, # 연결 유효성 자동 확인 + echo=False # SQL 쿼리 로그 (디버깅 시 True로 변경) +) + +# 세션 팩토리 생성 +SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) + +def get_db(): + """데이터베이스 세션 의존성""" + db = SessionLocal() + try: + yield db + finally: + db.close() diff --git a/asset_pilot_docker/app/fetcher.py b/asset_pilot_docker/app/fetcher.py new file mode 100644 index 0000000..33627a0 --- /dev/null +++ b/asset_pilot_docker/app/fetcher.py @@ -0,0 +1,113 @@ +import requests +import re +from typing import Dict, Optional +import time + +class DataFetcher: + def __init__(self): + self.session = requests.Session() + self.session.headers.update({ + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36' + }) + + def fetch_investing_com(self, asset_code: str) -> Optional[float]: + """인베스팅닷컴 (윈도우 앱 방식 정규식 적용)""" + try: + url = f"https://www.investing.com/currencies/{asset_code.lower().replace('/', '-')}" + if asset_code == "USD/DXY": + url = "https://www.investing.com/indices/usdollar" + + # allow_redirects를 True로 하여 주소 변경에 대응 + response = self.session.get(url, timeout=10, allow_redirects=True) + html = response.text + + # 윈도우에서 가장 잘 되던 패턴 순서대로 시도 + patterns = [ + r'data-test="instrument-price-last">([\d,.]+)<', + r'last_last">([\d,.]+)<', + r'instrument-price-last">([\d,.]+)<' + ] + for pattern in patterns: + p = re.search(pattern, html) + if p: + return float(p.group(1).replace(',', '')) + except Exception as e: + print(f"⚠️ Investing 수집 실패 ({asset_code}): {e}") + return None + + def fetch_binance(self) -> Optional[float]: + """바이낸스 BTC/USDT (보내주신 윈도우 코드 로직)""" + url = "https://api.binance.com/api/v3/ticker/price" + try: + response = requests.get(url, params={"symbol": "BTCUSDT"}, timeout=5) + response.raise_for_status() + return float(response.json()["price"]) + except Exception as e: + print(f"❌ Binance API 실패: {e}") + return None + + def fetch_upbit(self) -> Optional[float]: + """업비트 BTC/KRW (보내주신 윈도우 코드 로직)""" + url = "https://api.upbit.com/v1/ticker" + try: + response = requests.get(url, params={"markets": "KRW-BTC"}, timeout=5) + response.raise_for_status() + data = response.json() + return float(data[0]["trade_price"]) if data else None + except Exception as e: + print(f"❌ Upbit API 실패: {e}") + return None + + def fetch_usd_krw(self) -> Optional[float]: + """USD/KRW 환율 (DNS 에러 방지 이중화)""" + # 방법 1: 두나무 CDN (원래 주소) + try: + url = "https://quotation-api-cdn.dunamu.com/v1/forex/recent?codes=FRX.KRWUSD" + res = requests.get(url, timeout=3) + if res.status_code == 200: + return float(res.json()[0]["basePrice"]) + except: + pass # 실패하면 바로 인베스팅닷컴으로 전환 + + # 방법 2: 인베스팅닷컴에서 환율 가져오기 (가장 확실한 백업) + return self.fetch_investing_com("USD/KRW") + + def fetch_krx_gold(self) -> Optional[float]: + """금 시세 (네이버 금융 모바일)""" + try: + url = "https://m.stock.naver.com/marketindex/metals/M04020000" + res = requests.get(url, timeout=5) + m = re.search(r'\"closePrice\":\"([\d,]+)\"', res.text) + return float(m.group(1).replace(",", "")) if m else None + except: + return None + + def fetch_all(self) -> Dict[str, Dict]: + print(f"📊 [{time.strftime('%H:%M:%S')}] 수집 시작...") + + # 1. 환율 먼저 수집 (계산의 핵심) + usd_krw = self.fetch_usd_krw() + + # 2. 나머지 자산 수집 + results = { + "XAU/USD": {"가격": self.fetch_investing_com("XAU/USD"), "단위": "USD/oz"}, + "XAU/CNY": {"가격": self.fetch_investing_com("XAU/CNY"), "단위": "CNY/oz"}, + "XAU/GBP": {"가격": self.fetch_investing_com("XAU/GBP"), "단위": "GBP/oz"}, + "USD/DXY": {"가격": self.fetch_investing_com("USD/DXY"), "단위": "Index"}, + "USD/KRW": {"가격": usd_krw, "단위": "KRW"}, + "BTC/USD": {"가격": self.fetch_binance(), "단위": "USDT"}, + "BTC/KRW": {"가격": self.fetch_upbit(), "단위": "KRW"}, + "KRX/GLD": {"가격": self.fetch_krx_gold(), "단위": "KRW/g"}, + } + + # 3. XAU/KRW 계산 + xau_krw = None + if results["XAU/USD"]["가격"] and usd_krw: + xau_krw = round((results["XAU/USD"]["가격"] / 31.1034768) * usd_krw, 0) + results["XAU/KRW"] = {"가격": xau_krw, "단위": "KRW/g"} + + success_count = sum(1 for v in results.values() if v['가격'] is not None) + print(f"✅ 수집 완료 (성공: {success_count}/9)") + return results + +fetcher = DataFetcher() \ No newline at end of file diff --git a/asset_pilot_docker/app/fetcher.py.claude b/asset_pilot_docker/app/fetcher.py.claude new file mode 100644 index 0000000..9f014d8 --- /dev/null +++ b/asset_pilot_docker/app/fetcher.py.claude @@ -0,0 +1,142 @@ +import requests +from typing import Dict, Optional +from bs4 import BeautifulSoup +import time + +class DataFetcher: + """모든 자산 가격 수집 클래스""" + + def __init__(self): + self.session = requests.Session() + self.session.headers.update({ + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' + }) + self.investing_cache = {} + self.cache_time = 0 + + def fetch_investing_com(self, asset_code: str) -> Optional[float]: + """Investing.com에서 가격 수집""" + # 간단한 캐싱 (5초) + if time.time() - self.cache_time < 5 and asset_code in self.investing_cache: + return self.investing_cache[asset_code] + + asset_map = { + "XAU/USD": "8830", + "XAU/CNY": "2186", + "XAU/GBP": "8500", + "USD/DXY": "8827" + } + + asset_id = asset_map.get(asset_code) + if not asset_id: + return None + + try: + url = f"https://www.investing.com/currencies/{asset_code.lower().replace('/', '-')}" + response = self.session.get(url, timeout=5) + response.raise_for_status() + + soup = BeautifulSoup(response.text, 'lxml') + price_elem = soup.select_one('[data-test="instrument-price-last"]') + + if price_elem: + price_text = price_elem.text.strip().replace(',', '') + price = float(price_text) + self.investing_cache[asset_code] = price + return price + except Exception as e: + print(f"Investing.com 수집 실패 ({asset_code}): {e}") + + return None + + def fetch_binance(self) -> Optional[float]: + """바이낸스 BTC/USDT 가격""" + try: + url = "https://api.binance.com/api/v3/ticker/price" + response = self.session.get(url, params={"symbol": "BTCUSDT"}, timeout=5) + response.raise_for_status() + data = response.json() + return float(data["price"]) if "price" in data else None + except Exception as e: + print(f"Binance API 실패: {e}") + return None + + def fetch_upbit(self) -> Optional[float]: + """업비트 BTC/KRW 가격""" + try: + url = "https://api.upbit.com/v1/ticker" + response = self.session.get(url, params={"markets": "KRW-BTC"}, timeout=5) + response.raise_for_status() + data = response.json() + return data[0]["trade_price"] if data and "trade_price" in data[0] else None + except Exception as e: + print(f"Upbit API 실패: {e}") + return None + + def fetch_usd_krw(self) -> Optional[float]: + """USD/KRW 환율""" + try: + url = "https://quotation-api-cdn.dunamu.com/v1/forex/recent?codes=FRX.KRWUSD" + response = self.session.get(url, timeout=5) + response.raise_for_status() + data = response.json() + return data[0]["basePrice"] if data else None + except Exception as e: + print(f"USD/KRW 수집 실패: {e}") + return None + + def fetch_krx_gold(self) -> Optional[float]: + """한국거래소 금 현물 가격""" + try: + url = "http://www.goldpr.co.kr/gms/default.asp" + response = self.session.get(url, timeout=5) + response.encoding = 'euc-kr' + + soup = BeautifulSoup(response.text, 'lxml') + + # 금 현물 가격 파싱 (사이트 구조에 따라 조정 필요) + price_elem = soup.select_one('table tr:nth-of-type(2) td:nth-of-type(2)') + if price_elem: + price_text = price_elem.text.strip().replace(',', '').replace('원', '') + return float(price_text) + except Exception as e: + print(f"KRX 금 가격 수집 실패: {e}") + + return None + + def fetch_all(self) -> Dict[str, Dict]: + """모든 자산 가격 수집""" + print("📊 데이터 수집 시작...") + + # 개별 자산 수집 + xau_usd = self.fetch_investing_com("XAU/USD") + xau_cny = self.fetch_investing_com("XAU/CNY") + xau_gbp = self.fetch_investing_com("XAU/GBP") + usd_dxy = self.fetch_investing_com("USD/DXY") + usd_krw = self.fetch_usd_krw() + btc_usd = self.fetch_binance() + btc_krw = self.fetch_upbit() + krx_gold = self.fetch_krx_gold() + + # XAU/KRW 계산 (트로이온스 -> 그램당 원화) + xau_krw = None + if xau_usd and usd_krw: + xau_krw = round((xau_usd / 31.1034768) * usd_krw, 0) + + results = { + "XAU/USD": {"가격": xau_usd, "단위": "USD/oz"}, + "XAU/CNY": {"가격": xau_cny, "단위": "CNY/oz"}, + "XAU/GBP": {"가격": xau_gbp, "단위": "GBP/oz"}, + "USD/DXY": {"가격": usd_dxy, "단위": "Index"}, + "USD/KRW": {"가격": usd_krw, "단위": "KRW"}, + "BTC/USD": {"가격": btc_usd, "단위": "USDT"}, + "BTC/KRW": {"가격": btc_krw, "단위": "KRW"}, + "KRX/GLD": {"가격": krx_gold, "단위": "KRW/g"}, + "XAU/KRW": {"가격": xau_krw, "단위": "KRW/g"}, + } + + print(f"✅ 데이터 수집 완료 (성공: {sum(1 for v in results.values() if v['가격'])}/9)") + return results + +# 전역 인스턴스 +fetcher = DataFetcher() diff --git a/asset_pilot_docker/app/models.py b/asset_pilot_docker/app/models.py new file mode 100644 index 0000000..9e03593 --- /dev/null +++ b/asset_pilot_docker/app/models.py @@ -0,0 +1,55 @@ +from sqlalchemy import Column, Integer, String, Float, DateTime, Text, ForeignKey +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import relationship +from datetime import datetime + +Base = declarative_base() + +class Asset(Base): + """자산 마스터 테이블""" + __tablename__ = "assets" + + id = Column(Integer, primary_key=True, index=True) + symbol = Column(String(20), unique=True, nullable=False, index=True) + name = Column(String(100), nullable=False) + category = Column(String(50)) # 귀금속, 암호화폐, 환율 등 + created_at = Column(DateTime, default=datetime.utcnow) + + # 관계 + user_assets = relationship("UserAsset", back_populates="asset") + price_history = relationship("PriceHistory", back_populates="asset") + +class UserAsset(Base): + """사용자 자산 정보""" + __tablename__ = "user_assets" + + id = Column(Integer, primary_key=True, index=True) + asset_id = Column(Integer, ForeignKey("assets.id"), nullable=False) + previous_close = Column(Float, default=0.0) # 전일종가 + average_price = Column(Float, default=0.0) # 평균매입가 + quantity = Column(Float, default=0.0) # 보유량 + updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) + + # 관계 + asset = relationship("Asset", back_populates="user_assets") + +class PriceHistory(Base): + """가격 히스토리 (선택적)""" + __tablename__ = "price_history" + + id = Column(Integer, primary_key=True, index=True) + asset_id = Column(Integer, ForeignKey("assets.id"), nullable=False) + price = Column(Float, nullable=False) + timestamp = Column(DateTime, default=datetime.utcnow, index=True) + + # 관계 + asset = relationship("Asset", back_populates="price_history") + +class AlertSetting(Base): + """알림 설정""" + __tablename__ = "alert_settings" + + id = Column(Integer, primary_key=True, index=True) + setting_key = Column(String(100), unique=True, nullable=False) + setting_value = Column(Text) # JSON 형식으로 저장 + updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) diff --git a/asset_pilot_docker/docker-compose.yml b/asset_pilot_docker/docker-compose.yml new file mode 100644 index 0000000..b50e251 --- /dev/null +++ b/asset_pilot_docker/docker-compose.yml @@ -0,0 +1,67 @@ +services: + # 1. PostgreSQL 데이터베이스 + postgres: + image: postgres:16-alpine + container_name: asset_pilot_db + restart: unless-stopped + environment: + POSTGRES_DB: asset_pilot + POSTGRES_USER: asset_user + POSTGRES_PASSWORD: ${DB_PASSWORD:-assetpilot} + POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --locale=C" + volumes: + - postgres_data:/var/lib/postgresql/data + - ./init-db:/docker-entrypoint-initdb.d + ports: + - "5432:5432" + networks: + - asset_pilot_network + healthcheck: + test: ["CMD-SHELL", "pg_isready -U asset_user -d asset_pilot"] + interval: 10s + timeout: 5s + retries: 5 + + # 2. Asset Pilot 웹 애플리케이션 + app: + build: + context: . + dockerfile: Dockerfile + # DNS 설정 (빌드 밖으로 이동) + dns: + - 8.8.8.8 + - 1.1.1.1 + container_name: asset_pilot_app + restart: unless-stopped + depends_on: + postgres: + condition: service_healthy + environment: + # DB 비밀번호 기본값을 postgres 서비스와 동일하게 'assetpilot'으로 설정 + DATABASE_URL: postgresql://asset_user:${DB_PASSWORD:-assetpilot}@postgres:5432/asset_pilot + APP_HOST: 0.0.0.0 + APP_PORT: 8000 + DEBUG: "False" + FETCH_INTERVAL: 5 + ports: + - "8000:8000" + networks: + - asset_pilot_network + volumes: + - app_logs:/app/logs + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8000/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + +volumes: + postgres_data: + driver: local + app_logs: + driver: local + +networks: + asset_pilot_network: + driver: bridge \ No newline at end of file diff --git a/asset_pilot_docker/import_csv.py b/asset_pilot_docker/import_csv.py new file mode 100755 index 0000000..9903794 --- /dev/null +++ b/asset_pilot_docker/import_csv.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python3 +""" +CSV 데이터 가져오기 스크립트 (Docker용) +Windows 앱의 user_assets.csv 파일을 PostgreSQL로 마이그레이션 +""" +import sys +import os +import csv +from sqlalchemy.orm import sessionmaker + +# app 모듈 import +from app.database import engine +from app.models import Asset, UserAsset + +def import_csv(csv_file): + """CSV 파일에서 데이터 가져오기""" + if not os.path.exists(csv_file): + print(f"❌ 파일을 찾을 수 없습니다: {csv_file}") + sys.exit(1) + + print(f"📁 CSV 파일 읽기: {csv_file}") + + SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) + db = SessionLocal() + + try: + with open(csv_file, 'r', encoding='utf-8') as f: + reader = csv.reader(f) + count = 0 + + for row in reader: + if len(row) != 4: + print(f"⚠️ 잘못된 행 형식 (무시): {row}") + continue + + asset_symbol, prev_close, avg_price, quantity = row + + # 자산 찾기 + asset = db.query(Asset).filter(Asset.symbol == asset_symbol).first() + if not asset: + print(f"⚠️ 자산을 찾을 수 없음: {asset_symbol}") + continue + + # 사용자 자산 업데이트 + user_asset = db.query(UserAsset).filter(UserAsset.asset_id == asset.id).first() + if user_asset: + user_asset.previous_close = float(prev_close) + user_asset.average_price = float(avg_price) + user_asset.quantity = float(quantity) + count += 1 + print(f"✓ {asset_symbol}: 전일={prev_close}, 평단={avg_price}, 수량={quantity}") + else: + print(f"⚠️ 사용자 자산 정보 없음: {asset_symbol}") + + db.commit() + print(f"\n✅ {count}개 항목 가져오기 완료!") + + except Exception as e: + print(f"❌ 오류 발생: {e}") + db.rollback() + finally: + db.close() + +if __name__ == "__main__": + if len(sys.argv) < 2: + print("사용법: python import_csv.py ") + print("예제: python import_csv.py user_assets.csv") + print("\nDocker에서 사용:") + print("1. docker cp user_assets.csv asset_pilot_app:/app/") + print("2. docker compose exec app python import_csv.py user_assets.csv") + sys.exit(1) + + csv_file = sys.argv[1] + import_csv(csv_file) diff --git a/asset_pilot_docker/init_db.py b/asset_pilot_docker/init_db.py new file mode 100755 index 0000000..d931588 --- /dev/null +++ b/asset_pilot_docker/init_db.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python3 +""" +데이터베이스 초기화 스크립트 +PostgreSQL 데이터베이스에 테이블을 생성하고 기본 데이터를 삽입합니다. +""" +import sys +import os +from dotenv import load_dotenv +from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker + +# 환경 변수 로드 +load_dotenv() + +# app 모듈 import를 위한 경로 추가 +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +from app.models import Base, Asset, UserAsset, AlertSetting +from app.database import DATABASE_URL +import json + +def init_database(): + """데이터베이스 초기화""" + print("🔧 데이터베이스 초기화 시작...") + + try: + # 엔진 생성 + engine = create_engine(DATABASE_URL, echo=True) + + # 테이블 생성 + print("\n📋 테이블 생성 중...") + Base.metadata.create_all(bind=engine) + print("✅ 테이블 생성 완료") + + # 세션 생성 + SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) + db = SessionLocal() + + try: + # 자산 마스터 데이터 초기화 + print("\n📊 자산 마스터 데이터 초기화 중...") + assets_data = [ + ("XAU/USD", "금/달러", "귀금속"), + ("XAU/CNY", "금/위안", "귀금속"), + ("XAU/GBP", "금/파운드", "귀금속"), + ("USD/DXY", "달러인덱스", "환율"), + ("USD/KRW", "달러/원", "환율"), + ("BTC/USD", "비트코인/달러", "암호화폐"), + ("BTC/KRW", "비트코인/원", "암호화폐"), + ("KRX/GLD", "금 현물", "귀금속"), + ("XAU/KRW", "금/원", "귀금속"), + ] + + for symbol, name, category in assets_data: + existing = db.query(Asset).filter(Asset.symbol == symbol).first() + if not existing: + asset = Asset(symbol=symbol, name=name, category=category) + db.add(asset) + print(f" ✓ {symbol} ({name}) 추가") + else: + print(f" - {symbol} 이미 존재") + + db.commit() + print("✅ 자산 마스터 데이터 초기화 완료") + + # 사용자 자산 초기화 + print("\n👤 사용자 자산 데이터 초기화 중...") + assets = db.query(Asset).all() + for asset in assets: + existing = db.query(UserAsset).filter(UserAsset.asset_id == asset.id).first() + if not existing: + user_asset = UserAsset( + asset_id=asset.id, + previous_close=0, + average_price=0, + quantity=0 + ) + db.add(user_asset) + print(f" ✓ {asset.symbol} 사용자 데이터 추가") + else: + print(f" - {asset.symbol} 사용자 데이터 이미 존재") + + db.commit() + print("✅ 사용자 자산 데이터 초기화 완료") + + # 알림 설정 초기화 + print("\n🔔 알림 설정 초기화 중...") + default_settings = { + "급등락_감지": False, + "급등락_임계값": 3.0, + "목표수익률_감지": False, + "목표수익률": 10.0, + "특정가격_감지": False, + "금_목표가격": 100000, + "BTC_목표가격": 100000000, + } + + for key, value in default_settings.items(): + existing = db.query(AlertSetting).filter(AlertSetting.setting_key == key).first() + if not existing: + setting = AlertSetting(setting_key=key, setting_value=json.dumps(value)) + db.add(setting) + print(f" ✓ {key}: {value}") + else: + print(f" - {key} 이미 존재") + + db.commit() + print("✅ 알림 설정 초기화 완료") + + print("\n🎉 데이터베이스 초기화 완료!") + print("\n다음 명령으로 서버를 시작하세요:") + print(" python main.py") + + finally: + db.close() + + except Exception as e: + print(f"\n❌ 오류 발생: {e}") + print("\n문제 해결 방법:") + print("1. PostgreSQL이 실행 중인지 확인하세요:") + print(" sudo systemctl status postgresql") + print("\n2. 데이터베이스가 생성되었는지 확인하세요:") + print(" sudo -u postgres psql -c '\\l'") + print("\n3. .env 파일의 DATABASE_URL이 올바른지 확인하세요") + sys.exit(1) + +if __name__ == "__main__": + init_database() diff --git a/asset_pilot_docker/main.py b/asset_pilot_docker/main.py new file mode 100644 index 0000000..5475a47 --- /dev/null +++ b/asset_pilot_docker/main.py @@ -0,0 +1,268 @@ +import os +import json +import asyncio +from datetime import datetime +from typing import Dict +from fastapi import FastAPI, Depends, HTTPException, Request +from fastapi.responses import HTMLResponse, StreamingResponse +from fastapi.staticfiles import StaticFiles +from fastapi.templating import Jinja2Templates +from sqlalchemy.orm import Session +from pydantic import BaseModel +from dotenv import load_dotenv + +from app.database import get_db, engine +from app.models import Base, Asset, UserAsset, AlertSetting +from app.fetcher import fetcher +from app.calculator import Calculator + +load_dotenv() + +# 테이블 생성 +Base.metadata.create_all(bind=engine) + +app = FastAPI(title="Asset Pilot - Orange Pi Edition", version="1.0.0") + +# 정적 파일 및 템플릿 설정 +app.mount("/static", StaticFiles(directory="static"), name="static") +templates = Jinja2Templates(directory="templates") + +# 전역 변수: 현재 가격 캐시 +current_prices: Dict = {} + +# ==================== Pydantic 모델 ==================== + +class UserAssetUpdate(BaseModel): + symbol: str + previous_close: float + average_price: float + quantity: float + +class AlertSettingUpdate(BaseModel): + settings: Dict + +# ==================== 데이터베이스 초기화 ==================== + +def init_assets(db: Session): + """자산 마스터 데이터 초기화""" + assets_data = [ + ("XAU/USD", "금/달러", "귀금속"), + ("XAU/CNY", "금/위안", "귀금속"), + ("XAU/GBP", "금/파운드", "귀금속"), + ("USD/DXY", "달러인덱스", "환율"), + ("USD/KRW", "달러/원", "환율"), + ("BTC/USD", "비트코인/달러", "암호화폐"), + ("BTC/KRW", "비트코인/원", "암호화폐"), + ("KRX/GLD", "금 현물", "귀금속"), + ("XAU/KRW", "금/원", "귀금속"), + ] + + for symbol, name, category in assets_data: + existing = db.query(Asset).filter(Asset.symbol == symbol).first() + if not existing: + asset = Asset(symbol=symbol, name=name, category=category) + db.add(asset) + + db.commit() + print("✅ 자산 마스터 데이터 초기화 완료") + +def init_user_assets(db: Session): + """사용자 자산 초기화 (기본값 0)""" + assets = db.query(Asset).all() + for asset in assets: + existing = db.query(UserAsset).filter(UserAsset.asset_id == asset.id).first() + if not existing: + user_asset = UserAsset( + asset_id=asset.id, + previous_close=0, + average_price=0, + quantity=0 + ) + db.add(user_asset) + db.commit() + print("✅ 사용자 자산 데이터 초기화 완료") + +def init_alert_settings(db: Session): + """알림 설정 초기화""" + default_settings = { + "급등락_감지": False, + "급등락_임계값": 3.0, + "목표수익률_감지": False, + "목표수익률": 10.0, + "특정가격_감지": False, + "금_목표가격": 100000, + "BTC_목표가격": 100000000, + } + + for key, value in default_settings.items(): + existing = db.query(AlertSetting).filter(AlertSetting.setting_key == key).first() + if not existing: + setting = AlertSetting(setting_key=key, setting_value=json.dumps(value)) + db.add(setting) + db.commit() + print("✅ 알림 설정 초기화 완료") + +# ==================== 앱 시작 이벤트 ==================== + +@app.on_event("startup") +async def startup_event(): + """앱 시작 시 초기화 및 백그라운드 작업 시작""" + db = next(get_db()) + try: + init_assets(db) + init_user_assets(db) + init_alert_settings(db) + print("🚀 Asset Pilot 서버 시작 완료") + finally: + db.close() + + # 백그라운드 데이터 수집 시작 + asyncio.create_task(background_fetch()) + +async def background_fetch(): + """백그라운드에서 주기적으로 가격 수집""" + global current_prices + interval = int(os.getenv('FETCH_INTERVAL', 5)) + + while True: + try: + print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 데이터 수집 시작...") + current_prices = fetcher.fetch_all() + except Exception as e: + print(f"❌ 데이터 수집 오류: {e}") + + await asyncio.sleep(interval) + +# ==================== API 엔드포인트 ==================== + +@app.get("/", response_class=HTMLResponse) +async def read_root(request: Request): + """메인 페이지""" + return templates.TemplateResponse("index.html", {"request": request}) + +@app.get("/api/prices") +async def get_prices(): + """현재 가격 조회""" + return current_prices + +@app.get("/api/assets") +async def get_assets(db: Session = Depends(get_db)): + """사용자 자산 조회""" + assets = db.query(Asset, UserAsset).join( + UserAsset, Asset.id == UserAsset.asset_id + ).all() + + result = [] + for asset, user_asset in assets: + result.append({ + "symbol": asset.symbol, + "name": asset.name, + "category": asset.category, + "previous_close": float(user_asset.previous_close), + "average_price": float(user_asset.average_price), + "quantity": float(user_asset.quantity), + }) + + return result + +@app.post("/api/assets") +async def update_asset(data: UserAssetUpdate, db: Session = Depends(get_db)): + """자산 정보 업데이트""" + asset = db.query(Asset).filter(Asset.symbol == data.symbol).first() + if not asset: + raise HTTPException(status_code=404, detail="자산을 찾을 수 없습니다") + + user_asset = db.query(UserAsset).filter(UserAsset.asset_id == asset.id).first() + if user_asset: + user_asset.previous_close = data.previous_close + user_asset.average_price = data.average_price + user_asset.quantity = data.quantity + db.commit() + return {"status": "success", "message": "업데이트 완료"} + + raise HTTPException(status_code=404, detail="사용자 자산 정보를 찾을 수 없습니다") + +@app.get("/api/pnl") +async def get_pnl(db: Session = Depends(get_db)): + """손익 계산""" + # KRX/GLD 자산 정보 + krx_asset = db.query(Asset).filter(Asset.symbol == "KRX/GLD").first() + krx_user = db.query(UserAsset).filter(UserAsset.asset_id == krx_asset.id).first() if krx_asset else None + + # BTC/KRW 자산 정보 + btc_asset = db.query(Asset).filter(Asset.symbol == "BTC/KRW").first() + btc_user = db.query(UserAsset).filter(UserAsset.asset_id == btc_asset.id).first() if btc_asset else None + + gold_buy_price = float(krx_user.average_price) if krx_user else 0 + gold_quantity = float(krx_user.quantity) if krx_user else 0 + btc_buy_price = float(btc_user.average_price) if btc_user else 0 + btc_quantity = float(btc_user.quantity) if btc_user else 0 + + current_gold = current_prices.get("KRX/GLD", {}).get("가격") + current_btc = current_prices.get("BTC/KRW", {}).get("가격") + + pnl = Calculator.calc_pnl( + gold_buy_price, gold_quantity, + btc_buy_price, btc_quantity, + current_gold, current_btc + ) + + return pnl + +@app.get("/api/alerts/settings") +async def get_alert_settings(db: Session = Depends(get_db)): + """알림 설정 조회""" + settings = db.query(AlertSetting).all() + result = {} + for setting in settings: + try: + result[setting.setting_key] = json.loads(setting.setting_value) + except: + result[setting.setting_key] = setting.setting_value + return result + +@app.post("/api/alerts/settings") +async def update_alert_settings(data: AlertSettingUpdate, db: Session = Depends(get_db)): + """알림 설정 업데이트""" + for key, value in data.settings.items(): + setting = db.query(AlertSetting).filter(AlertSetting.setting_key == key).first() + if setting: + setting.setting_value = json.dumps(value) + else: + new_setting = AlertSetting(setting_key=key, setting_value=json.dumps(value)) + db.add(new_setting) + + db.commit() + return {"status": "success", "message": "알림 설정 업데이트 완료"} + +@app.get("/api/stream") +async def stream_prices(): + """Server-Sent Events로 실시간 가격 스트리밍""" + async def event_generator(): + while True: + if current_prices: + data = json.dumps(current_prices, ensure_ascii=False) + yield f"data: {data}\n\n" + await asyncio.sleep(1) + + return StreamingResponse(event_generator(), media_type="text/event-stream") + +@app.get("/health") +async def health_check(): + """헬스 체크""" + return { + "status": "healthy", + "timestamp": datetime.now().isoformat(), + "prices_loaded": len(current_prices) > 0 + } + +# ==================== 메인 실행 ==================== + +if __name__ == "__main__": + import uvicorn + uvicorn.run( + "main:app", + host=os.getenv("APP_HOST", "0.0.0.0"), + port=int(os.getenv("APP_PORT", 8000)), + reload=os.getenv("DEBUG", "False").lower() == "true" + ) diff --git a/asset_pilot_docker/requirements.txt b/asset_pilot_docker/requirements.txt new file mode 100644 index 0000000..c85ccd3 --- /dev/null +++ b/asset_pilot_docker/requirements.txt @@ -0,0 +1,12 @@ +fastapi==0.104.1 +uvicorn[standard]==0.24.0 +sqlalchemy==2.0.23 +psycopg2-binary==2.9.9 +pydantic==2.5.0 +python-dotenv==1.0.0 +jinja2==3.1.2 +aiofiles==23.2.1 +requests==2.31.0 +beautifulsoup4==4.12.2 +lxml==4.9.3 +python-multipart==0.0.6 diff --git a/asset_pilot_docker/start.sh b/asset_pilot_docker/start.sh new file mode 100755 index 0000000..4646082 --- /dev/null +++ b/asset_pilot_docker/start.sh @@ -0,0 +1,117 @@ +#!/bin/bash +# Asset Pilot Docker 빠른 시작 스크립트 + +set -e + +echo "🐳 Asset Pilot Docker 설치를 시작합니다..." +echo "" + +# 색상 정의 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +# Docker 설치 확인 +if ! command -v docker &> /dev/null; then + echo -e "${YELLOW}⚠️ Docker가 설치되어 있지 않습니다.${NC}" + echo "" + echo "Docker를 설치하시겠습니까? (y/n)" + read -r INSTALL_DOCKER + + if [ "$INSTALL_DOCKER" = "y" ] || [ "$INSTALL_DOCKER" = "Y" ]; then + echo -e "${BLUE}🐳 Docker 설치 중...${NC}" + curl -fsSL https://get.docker.com -o get-docker.sh + sudo sh get-docker.sh + sudo usermod -aG docker $USER + rm get-docker.sh + echo -e "${GREEN}✓ Docker 설치 완료${NC}" + echo "" + echo -e "${YELLOW}⚠️ 로그아웃 후 다시 로그인하거나 다음 명령을 실행하세요:${NC}" + echo " newgrp docker" + echo "" + echo "그런 다음 이 스크립트를 다시 실행하세요." + exit 0 + else + echo -e "${RED}❌ Docker가 필요합니다. 설치 후 다시 시도하세요.${NC}" + exit 1 + fi +fi + +echo -e "${GREEN}✓ Docker 확인 완료${NC}" + +# Docker Compose 확인 +if ! docker compose version &> /dev/null; then + echo -e "${YELLOW}⚠️ Docker Compose가 설치되어 있지 않습니다.${NC}" + echo -e "${BLUE}📦 Docker Compose 설치 중...${NC}" + sudo apt-get update + sudo apt-get install -y docker-compose-plugin + echo -e "${GREEN}✓ Docker Compose 설치 완료${NC}" +fi + +echo -e "${GREEN}✓ Docker Compose 확인 완료${NC}" +echo "" + +# .env 파일 설정 +if [ ! -f ".env" ]; then + echo -e "${YELLOW}🔐 데이터베이스 비밀번호를 설정하세요${NC}" + echo -n "비밀번호 입력: " + read -s DB_PASSWORD + echo "" + + cat > .env << EOF +# PostgreSQL 데이터베이스 비밀번호 +DB_PASSWORD=${DB_PASSWORD} + +# 선택적 설정 +# FETCH_INTERVAL=5 +# DEBUG=False +EOF + + chmod 600 .env + echo -e "${GREEN}✓ .env 파일 생성 완료${NC}" +else + echo -e "${YELLOW}⚠️ .env 파일이 이미 존재합니다${NC}" +fi + +echo "" +echo -e "${BLUE}🚀 Docker 컨테이너 빌드 및 실행 중...${NC}" +echo "" + +# Docker 이미지 빌드 및 컨테이너 시작 +docker compose up -d --build + +echo "" +echo -e "${BLUE}⏳ 데이터베이스 준비 대기 중...${NC}" +sleep 10 + +# 데이터베이스 초기화 +echo "" +echo -e "${BLUE}🔧 데이터베이스 초기화 중...${NC}" +docker compose exec app python init_db.py + +echo "" +echo -e "${GREEN}✅ 설치 완료!${NC}" +echo "" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo -e "${GREEN}🌐 접속 정보${NC}" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + +# IP 주소 확인 +IP_ADDR=$(hostname -I | awk '{print $1}') +echo -e "로컬: ${BLUE}http://localhost:8000${NC}" +echo -e "네트워크: ${BLUE}http://${IP_ADDR}:8000${NC}" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + +echo "" +echo "유용한 명령어:" +echo " docker compose ps # 컨테이너 상태 확인" +echo " docker compose logs -f # 로그 실시간 보기" +echo " docker compose restart # 재시작" +echo " docker compose down # 중지" +echo "" +echo "CSV 데이터 가져오기:" +echo " docker cp user_assets.csv asset_pilot_app:/app/" +echo " docker compose exec app python import_csv.py user_assets.csv" +echo "" diff --git a/asset_pilot_docker/static/css/style.css b/asset_pilot_docker/static/css/style.css new file mode 100644 index 0000000..36bab9d --- /dev/null +++ b/asset_pilot_docker/static/css/style.css @@ -0,0 +1,353 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +:root { + --primary-color: #2563eb; + --success-color: #10b981; + --danger-color: #ef4444; + --warning-color: #f59e0b; + --bg-color: #f8fafc; + --card-bg: #ffffff; + --text-primary: #1e293b; + --text-secondary: #64748b; + --border-color: #e2e8f0; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; + background-color: var(--bg-color); + color: var(--text-primary); + line-height: 1.6; +} + +.container { + max-width: 1400px; + margin: 0 auto; + padding: 20px; +} + +/* 헤더 */ +header { + background: var(--card-bg); + border-radius: 12px; + padding: 24px; + margin-bottom: 24px; + box-shadow: 0 1px 3px rgba(0,0,0,0.1); +} + +header h1 { + font-size: 32px; + margin-bottom: 8px; +} + +.subtitle { + color: var(--text-secondary); + font-size: 14px; + margin-bottom: 12px; +} + +.status-bar { + display: flex; + align-items: center; + gap: 8px; + font-size: 14px; + color: var(--text-secondary); +} + +.status-dot { + width: 10px; + height: 10px; + border-radius: 50%; + background-color: var(--success-color); + animation: pulse 2s infinite; +} + +@keyframes pulse { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.5; } +} + +/* 손익 요약 */ +.pnl-summary { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); + gap: 16px; + margin-bottom: 24px; +} + +.pnl-card { + background: var(--card-bg); + border-radius: 12px; + padding: 20px; + box-shadow: 0 1px 3px rgba(0,0,0,0.1); +} + +.pnl-card.total { + background: linear-gradient(135deg, var(--primary-color) 0%, #1e40af 100%); + color: white; +} + +.pnl-card h3 { + font-size: 14px; + font-weight: 500; + margin-bottom: 12px; + opacity: 0.9; +} + +.pnl-value { + font-size: 28px; + font-weight: 700; + margin-bottom: 4px; +} + +.pnl-percent { + font-size: 16px; + font-weight: 500; +} + +.pnl-value.profit { + color: var(--danger-color); +} + +.pnl-value.loss { + color: var(--primary-color); +} + +.pnl-card.total .pnl-value, +.pnl-card.total .pnl-percent { + color: white; +} + +/* 자산 섹션 */ +.assets-section { + background: var(--card-bg); + border-radius: 12px; + padding: 24px; + box-shadow: 0 1px 3px rgba(0,0,0,0.1); + margin-bottom: 24px; +} + +.section-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 20px; +} + +.section-header h2 { + font-size: 20px; +} + +/* 테이블 */ +.table-container { + overflow-x: auto; +} + +table { + width: 100%; + border-collapse: collapse; +} + +th, td { + padding: 12px 16px; + text-align: left; + border-bottom: 1px solid var(--border-color); +} + +th { + background-color: var(--bg-color); + font-weight: 600; + font-size: 14px; + color: var(--text-secondary); +} + +td { + font-size: 14px; +} + +.numeric { + text-align: right; +} + +td input { + width: 100%; + padding: 6px 8px; + border: 1px solid var(--border-color); + border-radius: 4px; + font-size: 14px; +} + +td input:focus { + outline: none; + border-color: var(--primary-color); +} + +.price-up { + color: var(--danger-color); +} + +.price-down { + color: var(--primary-color); +} + +/* 버튼 */ +.btn { + padding: 10px 20px; + border: none; + border-radius: 6px; + font-size: 14px; + font-weight: 500; + cursor: pointer; + transition: all 0.2s; +} + +.btn-primary { + background-color: var(--primary-color); + color: white; +} + +.btn-primary:hover { + background-color: #1e40af; +} + +.btn-secondary { + background-color: var(--border-color); + color: var(--text-primary); +} + +.btn-secondary:hover { + background-color: #cbd5e1; +} + +/* 모달 */ +.modal { + display: none; + position: fixed; + z-index: 1000; + left: 0; + top: 0; + width: 100%; + height: 100%; + background-color: rgba(0,0,0,0.5); +} + +.modal.active { + display: flex; + justify-content: center; + align-items: center; +} + +.modal-content { + background-color: var(--card-bg); + border-radius: 12px; + width: 90%; + max-width: 600px; + max-height: 90vh; + overflow-y: auto; + box-shadow: 0 20px 25px -5px rgba(0,0,0,0.1); +} + +.modal-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 20px 24px; + border-bottom: 1px solid var(--border-color); +} + +.modal-header h2 { + font-size: 20px; +} + +.close { + font-size: 28px; + font-weight: 300; + cursor: pointer; + color: var(--text-secondary); +} + +.close:hover { + color: var(--text-primary); +} + +.modal-body { + padding: 24px; +} + +.setting-group { + margin-bottom: 24px; + padding-bottom: 24px; + border-bottom: 1px solid var(--border-color); +} + +.setting-group:last-child { + border-bottom: none; +} + +.setting-group h3 { + font-size: 16px; + margin-bottom: 16px; +} + +.setting-group label { + display: block; + margin-bottom: 12px; +} + +.setting-group input[type="checkbox"] { + margin-right: 8px; +} + +.setting-group input[type="number"] { + width: 120px; + padding: 8px; + border: 1px solid var(--border-color); + border-radius: 4px; + margin-left: 8px; +} + +.modal-footer { + display: flex; + justify-content: flex-end; + gap: 12px; + padding: 20px 24px; + border-top: 1px solid var(--border-color); +} + +/* 푸터 */ +footer { + text-align: center; + padding: 24px; + color: var(--text-secondary); +} + +footer p { + margin-top: 12px; + font-size: 14px; +} + +/* 반응형 */ +@media (max-width: 768px) { + .container { + padding: 12px; + } + + header h1 { + font-size: 24px; + } + + .pnl-summary { + grid-template-columns: 1fr; + } + + table { + font-size: 12px; + } + + th, td { + padding: 8px; + } +} diff --git a/asset_pilot_docker/static/js/app.js b/asset_pilot_docker/static/js/app.js new file mode 100644 index 0000000..231586a --- /dev/null +++ b/asset_pilot_docker/static/js/app.js @@ -0,0 +1,309 @@ +// 전역 변수 +let currentPrices = {}; +let userAssets = []; +let alertSettings = {}; + +// 초기화 +document.addEventListener('DOMContentLoaded', () => { + loadAssets(); + loadAlertSettings(); + startPriceStream(); + + // 이벤트 리스너 + document.getElementById('refresh-btn').addEventListener('click', refreshData); + document.getElementById('alert-settings-btn').addEventListener('click', openAlertModal); + document.querySelector('.close').addEventListener('click', closeAlertModal); + document.getElementById('save-alerts').addEventListener('click', saveAlertSettings); + document.getElementById('cancel-alerts').addEventListener('click', closeAlertModal); + + // 주기적 PnL 업데이트 + setInterval(updatePnL, 1000); +}); + +// 자산 데이터 로드 +async function loadAssets() { + try { + const response = await fetch('/api/assets'); + userAssets = await response.json(); + renderAssetsTable(); + } catch (error) { + console.error('자산 로드 실패:', error); + } +} + +// 알림 설정 로드 +async function loadAlertSettings() { + try { + const response = await fetch('/api/alerts/settings'); + alertSettings = await response.json(); + } catch (error) { + console.error('알림 설정 로드 실패:', error); + } +} + +// 실시간 가격 스트리밍 +function startPriceStream() { + const eventSource = new EventSource('/api/stream'); + + eventSource.onmessage = (event) => { + currentPrices = JSON.parse(event.data); + updatePricesInTable(); + updateLastUpdateTime(); + }; + + eventSource.onerror = () => { + console.error('SSE 연결 오류'); + document.getElementById('status-indicator').style.backgroundColor = '#ef4444'; + }; +} + +// 테이블 렌더링 +function renderAssetsTable() { + const tbody = document.getElementById('assets-tbody'); + tbody.innerHTML = ''; + + const assets = [ + 'XAU/USD', 'XAU/CNY', 'XAU/GBP', 'USD/DXY', 'USD/KRW', + 'BTC/USD', 'BTC/KRW', 'KRX/GLD', 'XAU/KRW' + ]; + + assets.forEach(symbol => { + const asset = userAssets.find(a => a.symbol === symbol); + if (!asset) return; + + const row = document.createElement('tr'); + row.dataset.symbol = symbol; + + const decimalPlaces = symbol.includes('BTC') ? 8 : 2; + + row.innerHTML = ` + ${symbol} + + + + N/A + N/A + N/A + + + + + + + 0 + `; + + tbody.appendChild(row); + }); + + // 입력 필드 이벤트 리스너 + document.querySelectorAll('input[type="number"]').forEach(input => { + input.addEventListener('change', handleAssetChange); + input.addEventListener('blur', handleAssetChange); + }); +} + +// 테이블에 가격 업데이트 +function updatePricesInTable() { + const rows = document.querySelectorAll('#assets-tbody tr'); + + rows.forEach(row => { + const symbol = row.dataset.symbol; + const priceData = currentPrices[symbol]; + + if (!priceData || !priceData.가격) { + return; + } + + const currentPrice = priceData.가격; + const prevClose = parseFloat(row.querySelector('.prev-close').value) || 0; + + // 현재가 표시 + const decimalPlaces = symbol.includes('USD') || symbol.includes('DXY') ? 2 : 0; + row.querySelector('.current-price').textContent = formatNumber(currentPrice, decimalPlaces); + + // 변동 계산 + const change = currentPrice - prevClose; + const changePercent = prevClose > 0 ? (change / prevClose * 100) : 0; + + const changeCell = row.querySelector('.change'); + const changePercentCell = row.querySelector('.change-percent'); + + changeCell.textContent = formatNumber(change, decimalPlaces); + changePercentCell.textContent = `${formatNumber(changePercent, 2)}%`; + + // 색상 적용 + const colorClass = change > 0 ? 'price-up' : change < 0 ? 'price-down' : ''; + changeCell.className = `numeric ${colorClass}`; + changePercentCell.className = `numeric ${colorClass}`; + + // 매입액 계산 + const avgPrice = parseFloat(row.querySelector('.avg-price').value) || 0; + const quantity = parseFloat(row.querySelector('.quantity').value) || 0; + const buyTotal = avgPrice * quantity; + row.querySelector('.buy-total').textContent = formatNumber(buyTotal, 0); + }); +} + +// 손익 업데이트 +async function updatePnL() { + try { + const response = await fetch('/api/pnl'); + const pnl = await response.json(); + + // 금 손익 + updatePnLCard('gold-pnl', 'gold-percent', pnl.금손익, pnl['금손익%']); + + // BTC 손익 + updatePnLCard('btc-pnl', 'btc-percent', pnl.BTC손익, pnl['BTC손익%']); + + // 총 손익 + updatePnLCard('total-pnl', 'total-percent', pnl.총손익, pnl['총손익%']); + + } catch (error) { + console.error('PnL 업데이트 실패:', error); + } +} + +// PnL 카드 업데이트 +function updatePnLCard(valueId, percentId, value, percent) { + const valueElem = document.getElementById(valueId); + const percentElem = document.getElementById(percentId); + + valueElem.textContent = formatNumber(value, 0) + ' 원'; + percentElem.textContent = formatNumber(percent, 2) + '%'; + + // 총손익이 아닌 경우만 색상 적용 + if (valueId !== 'total-pnl') { + valueElem.className = `pnl-value ${value > 0 ? 'profit' : value < 0 ? 'loss' : ''}`; + percentElem.className = `pnl-percent ${value > 0 ? 'profit' : value < 0 ? 'loss' : ''}`; + } +} + +// 자산 변경 처리 +async function handleAssetChange(event) { + const input = event.target; + const symbol = input.dataset.symbol; + const row = input.closest('tr'); + + const previousClose = parseFloat(row.querySelector('.prev-close').value) || 0; + const averagePrice = parseFloat(row.querySelector('.avg-price').value) || 0; + const quantity = parseFloat(row.querySelector('.quantity').value) || 0; + + try { + const response = await fetch('/api/assets', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + symbol, + previous_close: previousClose, + average_price: averagePrice, + quantity: quantity + }) + }); + + if (response.ok) { + console.log(`✅ ${symbol} 업데이트 완료`); + // 매입액 즉시 업데이트 + const buyTotal = averagePrice * quantity; + row.querySelector('.buy-total').textContent = formatNumber(buyTotal, 0); + } + } catch (error) { + console.error('업데이트 실패:', error); + } +} + +// 알림 설정 모달 열기 +function openAlertModal() { + document.getElementById('급등락_감지').checked = alertSettings.급등락_감지 || false; + document.getElementById('급등락_임계값').value = alertSettings.급등락_임계값 || 3.0; + document.getElementById('목표수익률_감지').checked = alertSettings.목표수익률_감지 || false; + document.getElementById('목표수익률').value = alertSettings.목표수익률 || 10.0; + document.getElementById('특정가격_감지').checked = alertSettings.특정가격_감지 || false; + document.getElementById('금_목표가격').value = alertSettings.금_목표가격 || 100000; + document.getElementById('BTC_목표가격').value = alertSettings.BTC_목표가격 || 100000000; + + document.getElementById('alert-modal').classList.add('active'); +} + +// 알림 설정 모달 닫기 +function closeAlertModal() { + document.getElementById('alert-modal').classList.remove('active'); +} + +// 알림 설정 저장 +async function saveAlertSettings() { + const settings = { + 급등락_감지: document.getElementById('급등락_감지').checked, + 급등락_임계값: parseFloat(document.getElementById('급등락_임계값').value), + 목표수익률_감지: document.getElementById('목표수익률_감지').checked, + 목표수익률: parseFloat(document.getElementById('목표수익률').value), + 특정가격_감지: document.getElementById('특정가격_감지').checked, + 금_목표가격: parseInt(document.getElementById('금_목표가격').value), + BTC_목표가격: parseInt(document.getElementById('BTC_목표가격').value) + }; + + try { + const response = await fetch('/api/alerts/settings', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ settings }) + }); + + if (response.ok) { + alertSettings = settings; + console.log('✅ 알림 설정 저장 완료'); + closeAlertModal(); + } + } catch (error) { + console.error('알림 설정 저장 실패:', error); + } +} + +// 데이터 새로고침 +async function refreshData() { + await loadAssets(); + console.log('🔄 데이터 새로고침 완료'); +} + +// 마지막 업데이트 시간 표시 +function updateLastUpdateTime() { + const now = new Date(); + const timeString = now.toLocaleTimeString('ko-KR'); + document.getElementById('last-update').textContent = `마지막 업데이트: ${timeString}`; +} + +// 숫자 포맷팅 +function formatNumber(value, decimals = 0) { + if (value === null || value === undefined || isNaN(value)) { + return 'N/A'; + } + return value.toLocaleString('ko-KR', { + minimumFractionDigits: decimals, + maximumFractionDigits: decimals + }); +} + +// 외부 클릭 시 모달 닫기 +window.addEventListener('click', (event) => { + const modal = document.getElementById('alert-modal'); + if (event.target === modal) { + closeAlertModal(); + } +}); diff --git a/asset_pilot_docker/templates/index.html b/asset_pilot_docker/templates/index.html new file mode 100644 index 0000000..0da0a6f --- /dev/null +++ b/asset_pilot_docker/templates/index.html @@ -0,0 +1,136 @@ + + + + + + Asset Pilot - 자산 모니터 + + + +