#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 밍글 스튜디오 웹사이트 로컬 개발 서버 Python 기반 HTTP 서버로 개발 및 테스트 지원 """ import http.server import socketserver import webbrowser import os import sys import socket from pathlib import Path # 한글 출력을 위한 인코딩 설정 if os.name == 'nt': # Windows import locale import codecs # UTF-8 강제 설정 try: sys.stdout.reconfigure(encoding='utf-8') sys.stderr.reconfigure(encoding='utf-8') except: # Python 3.6 이하 버전 호환 sys.stdout = codecs.getwriter('utf-8')(sys.stdout.detach()) sys.stderr = codecs.getwriter('utf-8')(sys.stderr.detach()) # 서버 설정 PORT = 3000 HOST = '0.0.0.0' # 모든 인터페이스에서 접근 가능 class CustomHTTPRequestHandler(http.server.SimpleHTTPRequestHandler): """커스텀 HTTP 요청 핸들러""" def end_headers(self): # CORS 헤더 추가 (개발용) self.send_header('Access-Control-Allow-Origin', '*') self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS') self.send_header('Access-Control-Allow-Headers', 'Content-Type') # 캐시 비활성화 (개발용) self.send_header('Cache-Control', 'no-cache, no-store, must-revalidate') self.send_header('Pragma', 'no-cache') self.send_header('Expires', '0') super().end_headers() def do_GET(self): """GET 요청 처리""" original_path = self.path # .html로 직접 접근하는 경우 리다이렉트 if self.path.endswith('.html') and self.path != '/index.html': clean_path = self.path[:-5] # .html 제거 self.send_response(301) self.send_header('Location', clean_path) self.end_headers() return # .html 확장자 없이 접근 시 자동으로 .html 추가 if not self.path.endswith('/') and '.' not in os.path.basename(self.path): html_path = self.path + '.html' if os.path.exists(html_path.lstrip('/')): self.path = html_path # 기본 파일 처리 if self.path == '/': self.path = '/index.html' super().do_GET() def log_message(self, format, *args): """로그 메시지 포맷팅""" print(f"[{self.log_date_time_string()}] {format % args}") def find_available_port(start_port=8001): """사용 가능한 포트 찾기""" for port in range(start_port, start_port + 20): # 더 많은 포트 시도 try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 주소 재사용 sock.bind(('localhost', port)) # 실제로 바인드 테스트 sock.close() print(f"Available port found: {port}") return port # 성공하면 해당 포트 반환 except OSError: continue # 포트가 사용 중이면 다음 포트 시도 print(f"No available port found in range {start_port}-{start_port+19}") return start_port # 찾지 못하면 기본값 반환 def main(): """메인 서버 실행 함수""" # 현재 디렉토리가 프로젝트 루트인지 확인 if not os.path.exists('index.html'): print("Error: index.html file not found.") print("Please run from project root directory.") sys.exit(1) # 사용 가능한 포트 찾기 available_port = find_available_port(PORT) try: # 서버 시작 httpd = socketserver.TCPServer((HOST, available_port), CustomHTTPRequestHandler) httpd.allow_reuse_address = True # 주소 재사용 허용 with httpd: # 로컬 및 외부 접근 주소 표시 import socket local_ip = socket.gethostbyname(socket.gethostname()) print("Mingle Studio Development Server Started!") print("="*60) print(f"Local Access: http://localhost:{available_port}") print(f"Network Access: http://{local_ip}:{available_port}") print(f"Root Directory: {os.getcwd()}") print("="*60) print("Main Pages:") print(f" Home: http://localhost:{available_port}/") print(f" About: http://localhost:{available_port}/about") print(f" Services: http://localhost:{available_port}/services") print(f" Portfolio: http://localhost:{available_port}/portfolio") print(f" Gallery: http://localhost:{available_port}/gallery") print(f" Contact: http://localhost:{available_port}/contact") print(f" Q&A: http://localhost:{available_port}/qna") print("="*60) print("External Access Setup:") print(f" 1. Setup port forwarding for port {available_port} on router") print(f" 2. Access via public IP: http://[PUBLIC_IP]:{available_port}") print(f" 3. Same network: http://{local_ip}:{available_port}") print("="*60) print("Tip: Press Ctrl+C to stop the server.") print("Opening browser automatically...") # 기본 브라우저에서 자동으로 열기 (로컬호스트로) webbrowser.open(f"http://localhost:{available_port}") # 서버 실행 httpd.serve_forever() except KeyboardInterrupt: print("\n\nServer stopped.") print("Goodbye!") except OSError as e: if e.errno == 10048: # WinError 10048 print(f"\nError: Port {available_port} is already in use.") print("Try different port or check the following:") print("1. Check if another server is running") print("2. Kill Python process in Task Manager") print(f"3. Run in command prompt: netstat -ano | findstr :{available_port}") else: print(f"Server error: {e}") sys.exit(1) if __name__ == "__main__": main()