Go to file
2026-06-16 09:55:17 +09:00
api_server Add 'api_server/' from commit 'cd684eae2200b96f62db0f0244ce54a13485ec6e' 2026-06-15 12:53:33 +09:00
app chore: setup supabase cli and pull baseline migration 2026-06-15 13:49:24 +09:00
crawler fix: ensure backfill_state table is created inside backward_backfill.py initialization 2026-06-16 09:52:44 +09:00
docs docs: add historical backfill operation and verification guide 2026-06-16 09:55:17 +09:00
sql chore: merge subprojects into monorepo layout 2026-06-15 12:54:11 +09:00
supabase chore: setup supabase cli and pull baseline migration 2026-06-15 13:49:24 +09:00
tools chore: merge subprojects into monorepo layout 2026-06-15 12:54:11 +09:00
.gitignore chore: setup supabase cli and pull baseline migration 2026-06-15 13:49:24 +09:00
AGENTS.md chore: merge subprojects into monorepo layout 2026-06-15 12:54:11 +09:00
README.md chore: merge subprojects into monorepo layout 2026-06-15 12:54:11 +09:00

☀️ SolarPower 태양광 발전 통합 관제 시스템

태양광 발전소의 실시간 발전 데이터를 수집하고 모니터링하는 통합 관제 시스템입니다.


📋 목차

  1. 시스템 개요
  2. 전체 아키텍처
  3. 인프라 구성
  4. 크롤러 (Synology NAS / PC)
  5. API 서버 (Oracle Cloud)
  6. 모바일 앱 (React Native/Expo)
  7. 데이터베이스 (Supabase)
  8. 문제 해결 가이드

시스템 개요

지원 발전소

호기 크롤러 타입 모니터링 시스템 비고
1호기 NREMS nrems.co.kr 1,2호기 통합 계정
2호기 NREMS nrems.co.kr 인버터별 분리 처리
3호기 NREMS nrems.co.kr
4호기 NREMS nrems.co.kr
5호기 KREMC kremc.kr JWT 인증, 월 단위 수집
6호기 Sun-WMS sun-wms.com 암호화된 페이로드, 월 단위 수집
8호기 Hyundai hyundai-es.co.kr 월별 통계 API 사용 (초고속)
9호기 NREMS nrems.co.kr
10호기 CMSolar cmsolar2.kr

전체 아키텍처

flowchart TD
    subgraph 외부시스템["외부 모니터링 시스템"]
        NREMS["NREMS<br/>(1,2,3,4,9호기)"]
        KREMC["KREMC<br/>(5호기)"]
        SUNWMS["Sun-WMS<br/>(6호기)"]
        HYUNDAI["Hyundai<br/>(8호기)"]
        CMSOLAR["CMSolar<br/>(10호기)"]
    end

    subgraph CLOUD["Oracle Cloud (CRAWLER & API)"]
        FASTAPI["FastAPI Server<br/>(Port 8000)"]
        NGINX["Nginx Reverse Proxy<br/>(Port 443)"]
        CRAWLER["Python Crawler<br/>(Tailscale Routing)"]
    end

    subgraph NAS["Synology NAS (Exit Node)"]
        TAILSCALE["Tailscale Node<br/>(Home IP Mapping)"]
    end

    subgraph SUPABASE["Supabase (PostgreSQL)"]
        DB_PLANTS["plants 테이블"]
        DB_LOGS["solar_logs 테이블"]
        DB_DAILY["daily_stats 테이블"]
    end

    subgraph CLIENT["클라이언트"]
        APP["React Native App"]
        WEB["Web Browser"]
    end

    NREMS --> CRAWLER
    KREMC --> CRAWLER
    SUNWMS --> CRAWLER
    HYUNDAI --> CRAWLER
    CMSOLAR --> CRAWLER
    
    CRAWLER -.->|Tailscale Tunnel| TAILSCALE
    TAILSCALE -.->|Proxy Request| 외부시스템

    CRAWLER -->|INSERT| DB_LOGS
    CRAWLER -->|UPSERT| DB_DAILY
    
    FASTAPI -->|SELECT| DB_PLANTS
    FASTAPI -->|SELECT| DB_LOGS
    FASTAPI -->|SELECT| DB_DAILY
    
    NGINX --> FASTAPI
    
    APP -->|HTTPS| NGINX
    WEB -->|HTTPS| NGINX

인프라 구성

서버 접속 정보

서버 용도 접속 명령어
Oracle Cloud API 서버 & 크롤러 ssh -i "~/.ssh/holdem_server.key" ubuntu@140.245.73.212
Synology NAS 데이터 백업 & Tailscale Exit Node ssh -p2022 haneulai@192.168.45.151

도메인

도메인 용도
https://solorpower.dadot.net API 서버 (Nginx 리버스 프록시)

크롤러 (Oracle Cloud / PC)

위치

d:\dev\etc\SolorPower\crawler\ (Local PC)
/home/ubuntu/SolorPower/crawler/ (Oracle Cloud)

네트워크 구성 (Tailscale)

일부 모니터링 사이트에서 Oracle Cloud IP가 차단되는 문제를 해결하기 위해 Tailscale을 사용하여 네트워크를 구성하였습니다.

  • 주 호스트: Oracle Cloud (크롤러 실행)
  • Exit Node: Synology NAS (가정용 IP 제공)
  • 동작: 크롤링 요청 시 Tailscale 터널을 통해 NAS의 IP를 사용하여 외부 시스템에 접근합니다.

디렉토리 구조

crawler/
├── main.py              # 메인 실행 파일 (실시간 수집용)
├── crawler_gui.py       # GUI 관리 도구 (과거 데이터 수집용) ← NEW!
├── config.py            # 발전소/인증 설정
├── database.py          # Supabase 연동
├── fetch_history.py     # 과거 데이터 수집 로직
├── .env                 # 환경 변수 (SUPABASE_URL, SUPABASE_KEY)
└── crawlers/
    ├── __init__.py      # 크롤러 라우팅
    ├── base.py          # 공통 유틸리티
    ├── nrems.py         # NREMS 크롤러
    ├── kremc.py         # KREMC 크롤러
    ├── sun_wms.py       # Sun-WMS 크롤러
    ├── hyundai.py       # Hyundai 크롤러
    └── cmsolar.py       # CMSolar 크롤러

GUI 관리 도구 (NEW)

과거 데이터를 편리하게 수집하고 복구하기 위한 GUI 도구가 추가되었습니다.

  1. 실행:
    python crawler_gui.py
    
  2. 기능:
    • 발전소별 실시간 상태 확인
    • 과거 데이터 수집: 날짜 범위를 지정하여 일별/월별 데이터 일괄 수집
    • 로그 정리: 미래 날짜로 잘못 들어간 오염 데이터 삭제 기능

자동 수집 (Cron)

# 30분마다 실행 (Oracle Cloud 환경)
*/30 * * * * cd /home/ubuntu/SolorPower/crawler && /home/ubuntu/SolorPower/crawler/venv/bin/python main.py >> cron.log 2>&1

크롤러별 개선 사항 (2026.01)

  • 공통: 미래 날짜 데이터(UTC/KST 혼동)가 저장되는 버그 수정 및 자동 청소 로직 추가.
  • NREMS: 일별 데이터 수집 시 월 단위로 분할 요청하여 끊김 방지.
  • KREMC: 5호기 인증 토큰 파싱 개선 및 월 단위 배치 수집 적용.
  • Sun-WMS: 6호기 세션 유지 및 월 단위 수집 안정화.
  • Hyundai: 8호기 getSolraMonthWork API를 활용하여 1년치 데이터를 수십 초 내에 수집하도록 최적화.

API 서버 (Oracle Cloud)

위치

/home/ubuntu/SolorPower/api_server/

환경 설정 (.env)

SUPABASE_URL=https://xxxx.supabase.co
SUPABASE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6...
DEBUG=false

서비스 관리

sudo systemctl restart solar-api

API 엔드포인트

Method Endpoint 설명
GET /plants/{plant_id}/stats 발전소 통계 조회 (일/월/년)
GET /plants/{plant_id}/stats/today 오늘(또는 특정일) 시간별 상세 조회
POST /plants/{plant_id}/upload 엑셀 데이터 업로드 (일간)
POST /plants/{plant_id}/upload/monthly 엑셀 데이터 업로드 (월간)

파라미터 설명:

  • period: day (일별), month (월별), year (연도별)
  • year: (옵션) 조회 기준 연도
  • month: (옵션) period=day시 조회할 월
  • date: (옵션) stats/today시 조회할 날짜 (YYYY-MM-DD)

모바일 앱 & 웹 (React Native/Expo)

위치

d:\dev\etc\SolorPower\app\

주요 기능

  • 실시간/통계 통합: 대시보드 및 상세 차트(일/월/년).
  • 날짜 네비게이션: ◀ 2026년 1월 ▶ 등의 컨트롤로 자유로운 과거 데이터 탐색.
  • 엑셀 업로드:
    • 일간: date, generation 또는 year, month, day, kwh 포맷 지원.
    • 월간: year, month, kwh 포맷 지원.
    • 별칭(발전량, kwh 등) 및 셀 병합 처리 지원.
  • 반응형 웹 지원: PC/모바일 브라우저 최적화.

웹 앱 배포 가이드 (Web Deployment)

React Native(Expo) 앱을 웹으로 빌드하고 Nginx 서버에 배포하는 과정입니다.

1. 웹 빌드 (Local PC)

cd d:\dev\etc\SolorPower\app
npm run export:web
  • dist 폴더에 정적 웹 파일들이 생성됩니다.

2. 서버 업로드 (SCP)

빌드된 dist 폴더를 Oracle Cloud 서버의 웹 루트로 전송합니다. (참고: /var/www/html/ 권한 문제로 인해 임시 폴더로 전송 후 sudo로 이동해야 할 수 있습니다)

# 1. 홈 디렉토리로 전송
scp -i "~/.ssh/holdem_server.key" -r dist ubuntu@140.245.73.212:~/dist_temp

# 2. 서버 접속 후 이동
ssh -i "~/.ssh/holdem_server.key" ubuntu@140.245.73.212
sudo rm -rf /var/www/html/dist
sudo mv ~/dist_temp /var/www/html/dist

3. Nginx 설정 (서버 분석 결과)

실제 운영 중인 Nginx 설정 (/etc/nginx/sites-enabled/solorpower)의 핵심 구조입니다.

라우팅 규칙:

  • Frontend: /var/www/html/dist (React Static Files)
  • Backend: http://127.0.0.1:8000 (FastAPI)
    • /plants (데이터/통계 API)
    • /docs, /openapi.json (API 문서)
server {
    listen 80;
    server_name solorpower.dadot.net;
    # HTTPS 리다이렉트 생략...

    listen 443 ssl;
    # SSL 인증서 설정 생략...
    
    # 1. React Frontend (정적 파일)
    location / {
        root /var/www/html/dist;
        index index.html;
        try_files $uri $uri/ /index.html;
    }

    # 2. FastAPI Backend (API 프록시)
    # plants(데이터), docs(문서) 경로만 백엔드로 토스
    location ~ ^/(plants|docs|openapi.json) {
        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;
    }
}

4. 적용

sudo systemctl reload nginx

이제 https://solorpower.dadot.net 에서 배포된 웹 앱을 확인할 수 있습니다.


데이터베이스 (Supabase)

주요 테이블

  1. plants: 발전소 기본 정보.
  2. solar_logs: 실시간 발전 로그 (10분/30분 단위). created_at 기준.
  3. daily_stats: 일별 발전량 통계. date 기준. (과거 데이터는 여기에 저장됨)
  4. monthly_stats: 월별 발전량 통계. month 기준.

개발 히스토리

2026-04-22

  • 크롤러 인프라 이전: 크롤러 실행 환경을 Synology NAS에서 Oracle Cloud로 이전.
  • 네트워크 우회 설정: Oracle Cloud IP 차단 이슈 대응을 위해 Tailscale을 도입, Synology NAS를 Exit Node로 설정하여 가정용 IP로 크롤링 수행.
  • 안정성 강화: 클라우드 환경 이전을 통해 NAS 리소스 부하 감소 및 수집 안전성 확보.

2026-01-30

2026-01-28

  • Stats API 고도화: 날짜/월 탐색을 위한 파라미터(month, date) 추가.
  • 연간 통계 개선: 단일 연도 조회에서 '해당 연도 포함 최근 5년' 조회로 변경.
  • 엑셀 업로드 유연성: year, month, day 컬럼이 분리된 파일도 자동 인식 및 처리.
  • Frontend 개선: 차트 상단 날짜 네비게이션(◀ ▶) 추가, 조회 기간 범위 표시 강화.

2026-01-27

  • Crawler 구조화: crawler_manager.py 도입 (스마트 스케줄링, 학습/최적화 모드).
  • GUI & Documentation: 관리자 GUI 기능 확장 및 crawler_structure.md 문서화.
  • 과거 데이터 수집 최적화: 모든 크롤러 월 단위 분할 수집 지원.

2026-01-23

  • 통계 조회 API 추가 및 엑셀 업로드 API 구현.

2026-01-22

  • 대시보드 필드명 매핑 수정.