# 전동차 업무 인수인계 및 고장관리 프로그램 아키텍처 ## 1. 프로젝트 개요 ### 1.1 목적 - 전동차 운용실의 24시간 교대 근무 환경에서 업무 인수인계 및 고장관리를 위한 윈도우 데스크톱 애플리케이션 - 기존 엑셀 매크로 기반 시스템을 현대적인 GUI 애플리케이션으로 대체 ### 1.2 기술 스택 - **Frontend**: PySide6 (Qt for Python) - **Database**: SQLite (로컬) → Supabase (원격, 추후 연동) - **Font**: GmarketSans - **Platform**: Windows Native ### 1.3 설계 원칙 - 모듈화된 구조로 유지보수성 확보 - 상속 기반 확장성 설계 - 상세한 로깅 및 주석 - 현대적이고 미려한 커스텀 UI --- ## 2. 프로젝트 구조 ``` handover/ ├── main.py # 진입점 ├── requirements.txt # 의존성 패키지 ├── ARCHITECTURE.md # 아키텍처 문서 ├── config.ini # 설정 파일 ├── assets/ # 리소스 │ ├── fonts/ # 폰트 파일 │ │ └── GmarketSans/ │ ├── icons/ # 아이콘 │ ├── images/ # 이미지 │ └── styles/ # QSS 스타일시트 │ ├── dark_theme.qss │ └── light_theme.qss │ ├── core/ # 핵심 모듈 │ ├── __init__.py │ ├── constants.py # 상수 정의 │ ├── config.py # 설정 관리 │ ├── logger.py # 로깅 시스템 │ ├── signals.py # 전역 시그널 │ └── exceptions.py # 커스텀 예외 │ ├── database/ # 데이터베이스 모듈 │ ├── __init__.py │ ├── db_manager.py # DB 연결 관리 │ ├── models.py # 데이터 모델 정의 │ ├── crud.py # CRUD 연산 │ ├── migrations.py # DB 마이그레이션 │ └── sync_manager.py # 원격 DB 동기화 (추후) │ ├── services/ # 비즈니스 로직 │ ├── __init__.py │ ├── auth_service.py # 인증/권한 서비스 │ ├── weather_service.py # 날씨 정보 서비스 │ ├── update_service.py # 업데이트 서비스 │ ├── backup_service.py # 백업 서비스 │ └── notification_service.py # 알림 서비스 │ ├── ui/ # UI 모듈 │ ├── __init__.py │ ├── main_window.py # 메인 윈도우 │ │ │ ├── base/ # 기본 UI 컴포넌트 │ │ ├── __init__.py │ │ ├── base_widget.py # 기본 위젯 클래스 │ │ ├── base_dialog.py # 기본 다이얼로그 클래스 │ │ ├── base_section.py # 기본 섹션 클래스 │ │ └── base_table.py # 기본 테이블 클래스 │ │ │ ├── components/ # 재사용 가능 컴포넌트 │ │ ├── __init__.py │ │ ├── custom_button.py # 커스텀 버튼 │ │ ├── custom_input.py # 커스텀 입력 필드 │ │ ├── custom_table.py # 커스텀 테이블 │ │ ├── custom_calendar.py # 커스텀 캘린더 │ │ ├── toggle_switch.py # 토글 스위치 │ │ ├── dropdown.py # 드롭다운 │ │ ├── splitter.py # 분리바 │ │ ├── popup_widget.py # 팝업 위젯 │ │ └── train_info_popup.py # 편성 정보 팝업 │ │ │ ├── panels/ # 패널 (영역별 UI) │ │ ├── __init__.py │ │ ├── info_bar.py # 상단 인포바 (10%) │ │ ├── status_bar.py # 하단 상태바 (10%) │ │ ├── content_panel.py # 중앙 컨텐츠 (80%) │ │ ├── section_panel.py # 왼쪽 섹션 패널 (70%) │ │ └── todo_panel.py # 오른쪽 Todo 패널 (30%) │ │ │ ├── sections/ # 섹션별 UI │ │ ├── __init__.py │ │ ├── instruction_section.py # 지시 섹션 │ │ ├── fault_section.py # 고장 섹션 │ │ ├── work_section.py # 작업 섹션 │ │ └── misc_section.py # 기타 섹션 │ │ │ ├── dialogs/ # 다이얼로그 │ │ ├── __init__.py │ │ ├── login_dialog.py # 로그인 다이얼로그 │ │ ├── settings_dialog.py # 설정 다이얼로그 │ │ ├── user_management_dialog.py # 사용자 관리 │ │ ├── input_dialog.py # 입력 다이얼로그 │ │ ├── train_input_dialog.py # 편성 입력 다이얼로그 │ │ ├── todo_input_dialog.py # Todo 입력 다이얼로그 │ │ └── memo_input_dialog.py # 메모 입력 다이얼로그 │ │ │ └── widgets/ # Todo/메모 관련 위젯 │ ├── __init__.py │ ├── daily_inspection.py # 일상검수 편성 위젯 │ ├── todo_list.py # 할일 목록 위젯 │ └── memo_widget.py # 메모 위젯 │ └── utils/ # 유틸리티 ├── __init__.py ├── helpers.py # 헬퍼 함수 ├── validators.py # 유효성 검사 ├── formatters.py # 포맷터 └── common_methods.py # 공통 메서드 (편성 팝업 등) ``` --- ## 3. 모듈 의존성 다이어그램 ``` ┌─────────────────────────────────────────────────────────────────────────┐ │ main.py │ │ (Application Entry) │ └──────────────────────────────────┬──────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ MainWindow (UI) │ │ ui/main_window.py │ └──────┬───────────────────────────┬──────────────────────────────────────┘ │ │ ▼ ▼ ┌──────────────┐ ┌─────────────────────────────────────────────────┐ │ Services │ │ UI Modules │ │ ────────── │ │ ───────────────────────────────────────────── │ │ auth_service │◄────────┤ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │ │ weather_srv │ │ │ info_bar │ │ sections │ │ todo_panel │ │ │ update_srv │ │ └──────────┘ └──────────┘ └──────────────┘ │ │ backup_srv │ │ │ │ │ │ └──────┬───────┘ │ ▼ ▼ ▼ │ │ │ ┌─────────────────────────────────────────┐ │ │ │ │ Base Components │ │ │ │ │ base_widget, base_section, base_table │ │ │ │ └─────────────────────────────────────────┘ │ │ └─────────────────────────┬───────────────────────┘ │ │ ▼ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ Core Module │ │ config, logger, constants, signals │ └──────────────────────────────────┬──────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ Database Module │ │ db_manager, models, crud, sync │ └─────────────────────────────────────────────────────────────────────────┘ ``` --- ## 4. UI 레이아웃 구조 ``` ┌─────────────────────────────────────────────────────────────────────────┐ │ Title Bar │ │ [앱 아이콘] 전동차 인수인계 시스템 [─][□][X] │ ├─────────────────────────────────────────────────────────────────────────┤ │ Menu Bar │ │ [파일] [편집] [보기] [설정] [도움말] │ ├─────────────────────────────────────────────────────────────────────────┤ │ INFO BAR (10%) │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌──────────────────┐ │ │ │ 2026.01.03 │ A팀 │ 주간 │ 팀변경 │ 🌤 서울 -3°C 맑음 │ │ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └──────────────────┘ │ ├─────────────────────────────────────────────────────────────────────────┤ │ CONTENT AREA (80%) │ │ ┌───────────────────────────────────┬─────────────────────────────┐ │ │ │ SECTION PANEL (70%) │ TODO PANEL (30%) │◄──┼── Splitter │ │ ┌───────────────────────────┐ │ ┌───────────────────────┐ │ │ │ │ │ [지시][고장][작업][기타] │ │ │ 일상검수 (30%) │ │ │ │ │ │ ─────────────────────────│ │ │ ┌─────┬─────────────┐│ │ │ │ │ │ 날짜 │팀│내용 │확인 │ │ │ │주간 │①②③④⑤ ││ │ │ │ │ │──────┼──┼────────┼─────│ │ │ │야간 │①②③④⑤ ││ │ │ │ │ │01/03 │A │지시내용1│✓✓✓ │ │ │ └─────┴─────────────┘│ │ │ │ │ │01/02 │B │지시내용2│✓✓✗ │ │ ├───────────────────────┤ │ │ │ │ │... │ │ │ │ │ │ 할일 목록 (35%) │ │ │ │ │ └───────────────────────────┘ │ │ ┌─────────────────┐ │ │ │ │ │ │ │ │□ 점검 사항 1 │ │ │ │ │ │ │ │ │☑ 점검 사항 2 │ │ │ │ │ │ │ │ └─────────────────┘ │ │ │ │ │ │ ├───────────────────────┤ │ │ │ │ │ │ 메모 (35%) │ │ │ │ │ │ │ ┌─────────────────┐ │ │ │ │ │ │ │ │ 메모 내용... │ │ │ │ │ │ │ │ └─────────────────┘ │ │ │ │ │ │ └───────────────────────┘ │ │ │ └───────────────────────────────────┴─────────────────────────────┘ │ ├─────────────────────────────────────────────────────────────────────────┤ │ STATUS BAR (10%) │ │ [접속자: 홍길동(검수팀)] [DB상태: 정상] [마지막 동기화: 10:30] [v1.0.0] │ └─────────────────────────────────────────────────────────────────────────┘ ``` --- ## 5. 데이터베이스 스키마 ### 5.1 사용자 테이블 (users) ```sql CREATE TABLE users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT UNIQUE NOT NULL, password_hash TEXT NOT NULL, name TEXT NOT NULL, department TEXT NOT NULL, -- 검수팀, 운전팀, 차량팀 등 role TEXT NOT NULL, -- admin, editor, viewer is_active BOOLEAN DEFAULT 1, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ); ``` ### 5.2 팀 테이블 (teams) ```sql CREATE TABLE teams ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, -- A팀, B팀, C팀, D팀 shift_type TEXT, -- 주간, 야간 is_active BOOLEAN DEFAULT 1, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); ``` ### 5.3 지시 섹션 (instructions) ```sql CREATE TABLE instructions ( id INTEGER PRIMARY KEY AUTOINCREMENT, created_date DATE NOT NULL, created_team TEXT NOT NULL, instructor TEXT, -- 지시자 instruction_content TEXT NOT NULL, -- 지시내용 instruction_date DATE, -- 지시일자 is_continuous BOOLEAN DEFAULT 0, -- 지속여부 team_confirmations TEXT, -- JSON: {"A": true, "B": false, ...} is_completed BOOLEAN DEFAULT 0, completed_at DATETIME, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, created_by INTEGER REFERENCES users(id) ); ``` ### 5.4 고장 섹션 (faults) ```sql CREATE TABLE faults ( id INTEGER PRIMARY KEY AUTOINCREMENT, created_date DATE NOT NULL, created_team TEXT NOT NULL, occurrence_date DATE, -- 발생일자 train_number TEXT, -- 편성 car_number TEXT, -- 호차 fault_code TEXT, -- 고장코드 device_category TEXT, -- 장치분류 occurrence_station TEXT, -- 발생역 occurrence_time TIME, -- 발생시간 fault_content TEXT, -- 고장내용 action_content TEXT, -- 조치내용 action_team TEXT, -- 조치팀 team_confirmations TEXT, -- JSON is_completed BOOLEAN DEFAULT 0, completed_at DATETIME, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, created_by INTEGER REFERENCES users(id) ); ``` ### 5.5 작업 섹션 (works) ```sql CREATE TABLE works ( id INTEGER PRIMARY KEY AUTOINCREMENT, created_date DATE NOT NULL, created_team TEXT NOT NULL, work_date DATE, -- 작업일정 work_entity TEXT, -- 작업주체 target_train TEXT, -- 대상편성 target_device TEXT, -- 대상기기 work_content TEXT, -- 작업내용 remarks TEXT, -- 특이사항 team_confirmations TEXT, -- JSON is_completed BOOLEAN DEFAULT 0, completed_at DATETIME, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, created_by INTEGER REFERENCES users(id) ); ``` ### 5.6 기타 섹션 (miscs) ```sql CREATE TABLE miscs ( id INTEGER PRIMARY KEY AUTOINCREMENT, created_date DATE NOT NULL, created_team TEXT NOT NULL, reporter TEXT, -- 전달자 report_content TEXT, -- 전달내용 remarks TEXT, -- 특이사항 related_document TEXT, -- 관련문서 team_confirmations TEXT, -- JSON is_completed BOOLEAN DEFAULT 0, completed_at DATETIME, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, created_by INTEGER REFERENCES users(id) ); ``` ### 5.7 일상검수 (daily_inspections) ```sql CREATE TABLE daily_inspections ( id INTEGER PRIMARY KEY AUTOINCREMENT, inspection_date DATE NOT NULL, shift_type TEXT NOT NULL, -- 주간, 야간 slot_number INTEGER NOT NULL, -- 1~5 train_number TEXT, -- 편성번호 cleaning_type TEXT, -- 없음, 중청소, 대청소 has_work BOOLEAN DEFAULT 0, -- 작업 여부 created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, created_by INTEGER REFERENCES users(id) ); ``` ### 5.8 할일 목록 (todos) ```sql CREATE TABLE todos ( id INTEGER PRIMARY KEY AUTOINCREMENT, todo_date DATE NOT NULL, target_train TEXT, -- 대상편성 schedule TEXT, -- 일정 content TEXT NOT NULL, -- 내용 is_completed BOOLEAN DEFAULT 0, completed_at DATETIME, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, created_by INTEGER REFERENCES users(id) ); ``` ### 5.9 메모 (memos) ```sql CREATE TABLE memos ( id INTEGER PRIMARY KEY AUTOINCREMENT, memo_date DATE NOT NULL, content TEXT NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, created_by INTEGER REFERENCES users(id) ); ``` ### 5.10 설정 (settings) ```sql CREATE TABLE settings ( key TEXT PRIMARY KEY, value TEXT, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ); ``` --- ## 6. 클래스 상속 구조 ### 6.1 위젯 상속 구조 ``` QWidget └── BaseWidget ├── InfoBar ├── StatusBar ├── ContentPanel │ ├── SectionPanel │ └── TodoPanel └── BaseSection ├── InstructionSection ├── FaultSection ├── WorkSection └── MiscSection ``` ### 6.2 다이얼로그 상속 구조 ``` QDialog └── BaseDialog ├── LoginDialog ├── SettingsDialog ├── UserManagementDialog └── InputDialog ├── TrainInputDialog ├── TodoInputDialog └── MemoInputDialog ``` ### 6.3 테이블 상속 구조 ``` QTableWidget └── BaseTable └── SectionTable ├── InstructionTable ├── FaultTable ├── WorkTable └── MiscTable ``` --- ## 7. 권한 시스템 ### 7.1 부서별 권한 | 부서 | 역할 | 권한 | |------|------|------| | 검수팀 | admin | 모든 CRUD 가능, 사용자 관리, 설정 변경 | | 기타 부서 | viewer | 조회만 가능 | ### 7.2 권한 확인 플로우 ``` 사용자 로그인 ↓ 권한 확인 (department, role) ↓ UI 요소 활성화/비활성화 ↓ DB 작업 시 권한 재확인 ``` --- ## 8. 공통 메서드 (편성 팝업 등) ### 8.1 TrainInfoMixin ```python class TrainInfoMixin: """편성 정보 관련 공통 기능을 제공하는 Mixin 클래스""" def show_train_popup(self, train_number: str, position: QPoint): """마우스 호버 시 편성의 최근 고장 목록을 팝업으로 표시""" pass def get_recent_faults(self, train_number: str, limit: int = 10) -> List[dict]: """특정 편성의 최근 고장 목록 조회""" pass def open_train_detail(self, train_number: str): """편성 상세 정보 다이얼로그 열기""" pass ``` --- ## 9. 업데이트 시스템 ### 9.1 업데이트 플로우 ``` 앱 시작 ↓ 버전 확인 (주기적: 1시간마다) ↓ 새 버전 발견 시 알림 ↓ 사용자 확인 후 다운로드 ↓ 앱 재시작 후 업데이트 적용 ``` --- ## 10. 로깅 시스템 ### 10.1 로그 레벨 - DEBUG: 상세 디버그 정보 - INFO: 일반 정보 - WARNING: 경고 - ERROR: 오류 - CRITICAL: 심각한 오류 ### 10.2 로그 저장 - 파일: logs/app_YYYYMMDD.log - 최대 보관: 30일 - 로테이션: 일별 --- ## 11. 테마 시스템 ### 11.1 지원 테마 - Light Theme: 밝은 테마 - Dark Theme: 어두운 테마 ### 11.2 커스텀 스타일 - GmarketSans 폰트 적용 - 현대적인 둥근 모서리 - 그라데이션 효과 - 애니메이션 전환