- Flask Blueprint 아키텍처로 전환 (dashboard, upload, backup, status) - app.py 681줄 95줄로 축소 (86% 감소) - HTML 템플릿 모듈화 (base.html + 기능별 templates) - CSS/JS 파일 분리 (common + 기능별 파일) - 대시보드 기능 추가 (통계, 주간 예보, 방문객 추이) - 파일 업로드 웹 인터페이스 구현 - 백업/복구 관리 UI 구현 - Docker 배포 환경 개선 - .gitignore 업데이트 (uploads, backups, cache 등)
114 lines
3.2 KiB
Python
114 lines
3.2 KiB
Python
# daily_run.py
|
|
"""
|
|
daily_run.py
|
|
|
|
매일 정기적으로 실행되는 데이터 수집 스크립트
|
|
- weather_asos.py: 기상청 ASOS 데이터 수집
|
|
- ga4.py: Google Analytics 4 데이터 수집
|
|
- air_quality.py: 대기환경 API 데이터 수집
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import logging
|
|
import traceback
|
|
from datetime import datetime
|
|
|
|
# lib 디렉토리를 path에 추가
|
|
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), 'lib')))
|
|
|
|
from conf import db, db_schema
|
|
from lib.common import setup_logging
|
|
|
|
# 로거 설정
|
|
logger = setup_logging('daily_run', 'INFO')
|
|
|
|
def run_weather():
|
|
"""기상청 ASOS 데이터 수집"""
|
|
try:
|
|
logger.info("=" * 60)
|
|
logger.info("[RUNNING] weather_asos.py")
|
|
logger.info("=" * 60)
|
|
|
|
from weather_asos import main as weather_main
|
|
result = weather_main()
|
|
logger.info("[SUCCESS] weather_asos 완료")
|
|
return True
|
|
|
|
except Exception as e:
|
|
logger.error(f"[ERROR] weather_asos 실행 실패: {e}")
|
|
logger.error(traceback.format_exc())
|
|
return False
|
|
|
|
def run_ga4():
|
|
"""Google Analytics 4 데이터 수집"""
|
|
try:
|
|
logger.info("=" * 60)
|
|
logger.info("[RUNNING] ga4.py")
|
|
logger.info("=" * 60)
|
|
|
|
from ga4 import main as ga4_main
|
|
result = ga4_main()
|
|
logger.info("[SUCCESS] ga4 완료")
|
|
return True
|
|
|
|
except Exception as e:
|
|
logger.error(f"[ERROR] ga4 실행 실패: {e}")
|
|
logger.error(traceback.format_exc())
|
|
return False
|
|
|
|
def run_air_quality():
|
|
"""대기환경 API 데이터 수집"""
|
|
try:
|
|
logger.info("=" * 60)
|
|
logger.info("[RUNNING] air_quality.py")
|
|
logger.info("=" * 60)
|
|
|
|
from air_quality import AirQualityCollector
|
|
config = db.load_config()
|
|
collector = AirQualityCollector(config, db.engine, db_schema.air)
|
|
collector.run()
|
|
logger.info("[SUCCESS] air_quality 완료")
|
|
return True
|
|
|
|
except Exception as e:
|
|
logger.error(f"[ERROR] air_quality 실행 실패: {e}")
|
|
logger.error(traceback.format_exc())
|
|
return False
|
|
|
|
def main():
|
|
"""메인 실행 함수"""
|
|
logger.info(f"\n{'='*60}")
|
|
logger.info(f"[START] daily_run.py 시작: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
|
logger.info(f"{'='*60}\n")
|
|
|
|
results = {}
|
|
|
|
# 각 작업 실행
|
|
results['weather'] = run_weather()
|
|
results['ga4'] = run_ga4()
|
|
results['air_quality'] = run_air_quality()
|
|
|
|
# 결과 정리
|
|
logger.info(f"\n{'='*60}")
|
|
logger.info("[SUMMARY] 작업 완료 결과:")
|
|
logger.info(f"{'='*60}")
|
|
for task, success in results.items():
|
|
status = "✓ SUCCESS" if success else "✗ FAILED"
|
|
logger.info(f" {task}: {status}")
|
|
|
|
logger.info(f"[END] daily_run.py 종료: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
|
logger.info(f"{'='*60}\n")
|
|
|
|
# 모든 작업 성공 여부 반환
|
|
return all(results.values())
|
|
|
|
if __name__ == "__main__":
|
|
try:
|
|
success = main()
|
|
sys.exit(0 if success else 1)
|
|
except Exception as e:
|
|
logger.critical(f"[CRITICAL] 예상치 못한 에러: {e}")
|
|
logger.critical(traceback.format_exc())
|
|
sys.exit(1)
|