# =================================================================== # apps/dashboard/app.py # 정적 데이터 대시보드 웹 애플리케이션 # =================================================================== # 방문객, 날씨, 대기질, 예측 데이터를 시각화하는 대시보드입니다. # Flask Blueprint 기반으로 구현되어 통합 앱에 포함할 수 있습니다. # =================================================================== """ 정적 데이터 대시보드 웹 애플리케이션 방문객 통계, 날씨 정보, 대기질 데이터 등을 조회하고 시각화하는 대시보드를 제공합니다. 사용 예시: from apps.dashboard.app import create_app app = create_app() app.run() """ import os from flask import Flask, Blueprint, jsonify, request, render_template from werkzeug.exceptions import HTTPException from core.config import get_config from core.logging_utils import get_logger, setup_logging from core.database import get_engine, DBSession logger = get_logger(__name__) # Blueprint 생성 dashboard_bp = Blueprint('dashboard', __name__, url_prefix='/api/dashboard') @dashboard_bp.route('/health', methods=['GET']) def health_check(): """ 헬스 체크 엔드포인트 Returns: 상태 정보 JSON """ return jsonify({ 'status': 'healthy', 'service': 'dashboard' }) @dashboard_bp.route('/stats', methods=['GET']) def get_stats(): """ 기본 통계 조회 Query Parameters: start_date: 시작 날짜 (YYYY-MM-DD) end_date: 종료 날짜 (YYYY-MM-DD) Returns: 통계 데이터 JSON """ start_date = request.args.get('start_date') end_date = request.args.get('end_date') # TODO: 실제 통계 조회 구현 return jsonify({ 'start_date': start_date, 'end_date': end_date, 'total_visitors': 0, 'average_visitors': 0, 'data': [] }) @dashboard_bp.route('/weather/forecast', methods=['GET']) def get_weather_forecast(): """ 날씨 예보 조회 Returns: 날씨 예보 데이터 JSON """ from services.weather import get_daily_vilage_forecast config = get_config() service_key = config.data_api.get('service_key', '') if not service_key: return jsonify({'error': 'API 키가 설정되지 않았습니다.'}), 500 try: forecast = get_daily_vilage_forecast(service_key) return jsonify({ 'status': 'success', 'data': forecast }) except Exception as e: logger.error(f"날씨 예보 조회 실패: {e}") return jsonify({'error': str(e)}), 500 @dashboard_bp.route('/weather/precipitation', methods=['GET']) def get_precipitation(): """ 강수량 예보 조회 Query Parameters: format: 출력 형식 (json, html, text) Returns: 강수량 데이터 """ from services.weather import PrecipitationService output_format = request.args.get('format', 'json') try: service = PrecipitationService() data = service.get_precipitation_info(output_format=output_format) if output_format == 'html': return data, 200, {'Content-Type': 'text/html; charset=utf-8'} elif output_format == 'text': return data, 200, {'Content-Type': 'text/plain; charset=utf-8'} else: return jsonify(data) except Exception as e: logger.error(f"강수량 조회 실패: {e}") return jsonify({'error': str(e)}), 500 @dashboard_bp.errorhandler(HTTPException) def handle_exception(e): """HTTP 예외 핸들러""" return jsonify({ 'error': e.description, 'status_code': e.code }), e.code def create_app(config_override: dict = None) -> Flask: """ Flask 애플리케이션 팩토리 Args: config_override: 설정 덮어쓰기 딕셔너리 Returns: Flask 앱 인스턴스 """ app = Flask(__name__) # 설정 로드 config = get_config() app.config['SECRET_KEY'] = config.flask.get('secret_key', 'dev-secret') app.config['JSON_AS_ASCII'] = False if config_override: app.config.update(config_override) # 로깅 설정 setup_logging('apps.dashboard', level=config.log_level) # Blueprint 등록 app.register_blueprint(dashboard_bp) # 루트 엔드포인트 @app.route('/') def index(): return jsonify({ 'name': 'FGTools Dashboard API', 'version': '1.0.0', 'endpoints': [ '/api/dashboard/health', '/api/dashboard/stats', '/api/dashboard/weather/forecast', '/api/dashboard/weather/precipitation', ] }) logger.info("Dashboard 앱 초기화 완료") return app def run_server(host: str = '0.0.0.0', port: int = 5000, debug: bool = False): """ 개발 서버 실행 Args: host: 바인딩 호스트 port: 포트 번호 debug: 디버그 모드 """ app = create_app() app.run(host=host, port=port, debug=debug) if __name__ == '__main__': config = get_config() run_server( host=config.flask.get('host', '0.0.0.0'), port=config.flask.get('port', 5000), debug=config.debug )