VOC_Monitor/docs/project_spec.md

22 KiB

📋 Project Specification: VOC 모니터링 시스템

1. 프로젝트 비전

목표

부산교통공사 1호선 차량 관련 VOC(Voice of Customer)를 실시간으로 모니터링하고, 자동으로 보고서를 생성하여 업무 효율을 극대화합니다.

핵심 가치

  • 자동화: 수동으로 웹사이트를 확인하던 작업을 자동화
  • 신속성: 신규 VOC 발생 시 즉시 알림
  • 정확성: 열차 정보 자동 추출 및 시각표 기반 검증
  • 편의성: 한글(HWP) 보고서 자동 생성

핵심 페르소나

  • 직무: 부산교통공사 차량 부서 직원
  • 환경: Windows 10/11, 사내망
  • 사용 패턴: 백그라운드 상시 실행, 알림 기반 대응

2. 시스템 범위 (Scope)

포함 기능

  • 웹 크롤링: 부산교통공사 VOC 게시판 자동 수집
  • 데이터베이스: SQLite 기반 로컬 저장
  • 실시간 알림: Windows 토스트 알림
  • 보고서 생성: HWP/PDF 자동 작성
  • 열차 정보 분석: 시각표 기반 열차번호, 입고지 자동 추출
  • 히스토리 관리: 과거 VOC 조회 및 필터링
  • 설정 관리: 크롤링 주기, 알림 키워드 등

제외 기능 (Out of Scope)

  • 웹 기반 UI (데스크톱 전용)
  • 다중 사용자 지원 (1인 사용 전제)
  • 클라우드 동기화
  • 모바일 앱

3. 핵심 비즈니스 로직 (Core Logic)

3.1 크롤링 사이클

1. 로그인 세션 확인 (만료 시 재로그인)
2. 목록 페이지 수집 (최대 N페이지)
3. 키워드/부서 필터링
4. DB 저장 (Upsert)
5. 상세 내용 수집 (조건부)

3.2 알림 사이클 (v2.1 개선)

3.2.1 신규 알림 사이클 (기본 3분, 설정 가능)

1. 마지막 체크 이후 신규 데이터 조회 (get_new_posts_since)
   - 설정 `noti.use_related_filter = true`: 관심글(is_related=1)만 조회
   - 설정 `noti.use_related_filter = false`: 신규글 전체 조회
2. 중복 알림 필터링 (notified_post_ids 체크)
3. 모든 관심글(is_related=1)에 대해 알림 ⭐ 변경: 키워드 필터링 제거
4. 소리 재생 (설정 시)
5. 토스트 알림 및 팝업 표시
6. last_check_time 영속화 저장 ⭐ 신규

3.2.2 미확인 알림 사이클 (기본 10분, 설정 가능) 신규

1. 확인하지 않은 관심글 조회 (get_unchecked_related_posts)
   - 설정 `noti.use_related_filter = true`: 관심글(is_related=1)의 미확인만 조회
   - 설정 `noti.use_related_filter = false`: 전체 미확인글 조회
2. 30분 경과 조건 ON/OFF에 따라 필터링
   - ON: 30분 이상 지난 글만 알림
   - OFF: 미확인 글 전체 알림
3. 미확인 알림 발송 (⚠️ 표시)
4. 사용자가 확인할 때까지 반복 알림

3.2.3 알림 개선 사항

  • 키워드 필터링 제거: 모든 관심글에 대해 알림 발송
  • 중복 방지: notified_post_ids 세트로 동일 글 중복 알림 방지
  • 영속화: last_check_time을 scheduler_state.json에 저장하여 프로그램 재시작 시에도 유지
  • 미확인 체크: 사용자가 확인하지 않은 글에 대해 주기적 재알림
  • 주기 설정화: 신규 알림 주기 및 미확인 알림 주기를 설정 UI에서 변경 가능
  • 미확인 조건 토글: "30분 경과 후 알림" 옵션 ON/OFF 지원
  • 관심조건 토글: "관심 조건(키워드/부서)만 알림" 옵션 ON/OFF 지원

3.3 보고서 생성 프로세스

1. VOC 데이터 수신
2. VOCParser로 기본 정보 추출 (호선, 편성, 호차, 열차번호)
3. DateScheduleUtils로 날짜 타입 판별 (평일/주말/휴일)
4. TrainAnalyzer로 열차 정보 분석 (종별, 방향, 입고지)
5. TimetableService로 시각표 조회 및 검증
6. HWP 템플릿에 데이터 입력
7. 파일 저장 (중복 체크)

3.4 통계 분석 프로세스 (신규)

1. 사용자 입력 수신 (기간, 분석 옵션)
2. 입력 검증 (날짜 형식, 기간 제한)
3. DB에서 데이터 집계
   ├── 기간별 통계 (일/주/월/년)
   ├── 부서별 분포
   ├── 상태별 현황
   └── 키워드 빈도 분석
4. 차트 생성 (matplotlib/plotly)
   ├── 막대 그래프 (부서별, 상태별)
   ├── 선 그래프 (시계열 추이)
   ├── 파이 차트 (비율)
   └── 워드 클라우드 (키워드)
5. 보고서 생성 (Excel/PDF)
6. 파일 저장 및 열기

3.4.1 데이터 집계 로직

기간별 통계:

SELECT 
    DATE(date) as day,
    COUNT(*) as count
FROM voc_posts
WHERE date BETWEEN ? AND ?
GROUP BY DATE(date)
ORDER BY day

부서별 분포:

SELECT 
    department,
    COUNT(*) as count,
    ROUND(COUNT(*) * 100.0 / (SELECT COUNT(*) FROM voc_posts WHERE date BETWEEN ? AND ?), 2) as percentage
FROM voc_posts
WHERE date BETWEEN ? AND ?
GROUP BY department
ORDER BY count DESC

키워드 빈도 분석:

# 1. 모든 제목 + 내용 추출
# 2. 형태소 분석 (선택, 한글 처리)
# 3. 불용어 제거 ("의", "를", "이" 등)
# 4. 빈도 계산
# 5. TOP 10 추출

3.4.2 예외 케이스 처리

예외 상황 처리 방법 사용자 메시지
기간 내 데이터 없음 빈 보고서 생성 "선택한 기간에 VOC 데이터가 없습니다."
기간이 너무 긺 (1년 초과) 기간 제한 "최대 1년까지만 조회 가능합니다."
차트 생성 실패 텍스트 표만 생성 "차트 생성 실패. 표 형식으로 제공됩니다."
메모리 부족 데이터 샘플링 "데이터가 많아 일부만 표시됩니다."
Excel/PDF 생성 실패 에러 다이얼로그 "보고서 생성 중 오류 발생: [상세 메시지]"

3.4.3 성능 최적화

인덱스 추가:

CREATE INDEX IF NOT EXISTS idx_date ON voc_posts(date);
CREATE INDEX IF NOT EXISTS idx_department ON voc_posts(department);
CREATE INDEX IF NOT EXISTS idx_status ON voc_posts(status);
CREATE INDEX IF NOT EXISTS idx_date_department ON voc_posts(date, department);

쿼리 최적화:

  • 기간 제한: 최대 1년
  • 페이징: 대량 데이터 시 배치 처리
  • 캐싱: 동일 기간 재조회 시 캐시 사용 (선택)

메모리 관리:

  • 차트 생성 후 즉시 파일 저장
  • plt.close() 호출하여 메모리 해제
  • 대용량 데이터 시 청크 단위 처리

4. 에러 처리 전략

4.1 부분 실패 허용 원칙

보고서 생성 시 일부 정보 조회 실패는 전체 작업을 중단하지 않습니다.

실패 유형 처리 방법 사용자 경험
열차번호 조회 실패 필드 비움 드롭박스 비활성화
시각표 조회 실패 "정보 없음" 표시 경고 로그
템플릿 파일 없음 전체 중단 에러 다이얼로그

4.2 로그 레벨 구분

  • INFO: 정상 동작 (크롤링 완료, 보고서 생성 등)
  • WARNING: 부분 실패 (열차 정보 미조회 등)
  • ERROR: 전체 실패 (로그인 실패, DB 오류 등)

4.3 사용자 친화적 메시지

모든 에러 메시지는 한국어로 작성하며, 기술적 용어를 최소화합니다.

예시:

  • (Bad) TimetableServiceError: train_number not found in dataframe
  • (Good) 열차 정보를 조회할 수 없습니다. 보고서는 생성되지만 열차번호 필드가 비어있습니다.

5. 보고서 생성 규칙

5.1 필수 정보 vs 선택 정보

구분 필드 실패 시 처리
필수 제목, 내용, 날짜, 부서 전체 중단
선택 열차번호, 편성, 호차 필드 비움
선택 입고 정보, 비고 "정보 없음" 표시

5.2 UI 동작 규칙

  • 열차번호 조회 성공: 드롭박스에 후보 목록 표시
  • 열차번호 조회 실패: 드롭박스 비활성화 + 수동 입력 허용
  • 시각표 미로드: 관련 기능 전체 비활성화

5.3 파일명 규칙

[날짜]_[부서]_[제목(정제)].hwp
예: 2026-02-17_차량_1호선_서면역_소음발생.hwp

6. 데이터 모델

6.1 VOCPost (Pydantic)

class VOCPost(BaseModel):
    id: str                    # 게시글 ID
    title: str                 # 제목
    writer: str                # 작성자
    department: str            # 담당 부서
    date: str                  # 작성일 (YYYY-MM-DD HH:MM:SS)
    status: str                # 처리 상태
    channel: str               # 접수 경로
    is_public: int             # 공개 여부 (0/1)
    content: Optional[str]     # 상세 내용
    attachment: Optional[str]  # 첨부파일명
    is_related: int = 0        # 관심글 여부

6.2 데이터베이스 스키마

CREATE TABLE voc_posts (
    id TEXT PRIMARY KEY,
    title TEXT NOT NULL,
    writer TEXT,
    department TEXT,
    date TEXT,
    status TEXT,
    channel TEXT,
    is_public INTEGER DEFAULT 1,
    content TEXT,
    attachment TEXT,
    is_related INTEGER DEFAULT 0,
    checked_at TEXT,
    created_at TEXT DEFAULT CURRENT_TIMESTAMP
);

7. UI/UX 요구사항

7.1 메인 화면 (트레이 아이콘)

  • 시스템 트레이에 상주
  • 우클릭 메뉴: 수동 크롤링, 목록 보기, 설정, 종료

7.2 히스토리 다이얼로그

  • 테이블 뷰: ID, 제목, 작성자, 부서, 날짜, 상태
  • 필터: 부서별, 키워드, 날짜 범위
  • 더블클릭: 상세 팝업
  • 우클릭 메뉴: 보고서 생성, 인쇄, 첨부파일 보기

7.3 보고서 옵션 다이얼로그

  • 사업소 선택 (신평/노포)
  • 팀 선택 (검수1/검수2/...)
  • 작성자 정보
  • 열차번호 드롭박스 (자동 추출 시)

8. 제약 및 요구사항

8.1 기술 제약

  • Python: 3.8 이상
  • OS: Windows 10/11
  • 필수 라이브러리:
    • customtkinter: UI
    • selenium: 크롤링
    • pywin32: HWP 자동화
    • pydantic: 데이터 검증
    • pandas: 시각표 처리

8.2 성능 목표

  • 크롤링 주기: 10분 (설정 가능)
  • 알림 지연: 5분 이내
  • 보고서 생성: 3초 이내
  • DB 조회: 1초 이내

8.3 보안 요구사항

  • 로그인 정보: 로컬 JSON 파일 (평문 저장, 사내망 전제)
  • HWP 보안 모듈: 레지스트리 자동 등록

9. 시스템 아키텍처

9.1 계층 구조 (v3.0 - Manager 패턴 적용)

┌─────────────────────────────────────────────────────┐
│                   View (CustomTkinter)              │
│     HistoryDialog, SettingsDialog, Notification     │
└─────────────────────────────────────────────────────┘
                         ↕
┌─────────────────────────────────────────────────────┐
│              Controller (MVC) - 위임 패턴           │
│                                                     │
│  AppController (487줄)                              │
│  ├── SchedulerManager    : 크롤링, DB 체크, 스케줄링│
│  ├── NotificationManager : 토스트/팝업 알림         │
│  ├── ReportManager       : 보고서 생성/인쇄/PDF     │
│  ├── FileManager         : 첨부파일 다운로드/열기   │
│  └── UIManager           : UI 창 관리               │
└─────────────────────────────────────────────────────┘
                         ↕
┌─────────────────────────────────────────────────────┐
│           Services (Business Logic)                 │
│  ReportService, ScraperService, TimetableService    │
└─────────────────────────────────────────────────────┘
                         ↕
┌─────────────────────────────────────────────────────┐
│           Utils & Models (Data)                     │
│  VOCParser, TrainAnalyzer, VOCDatabase, ...        │
└─────────────────────────────────────────────────────┘

9.2 주요 모듈 책임

모듈 책임 라인 수
AppController 전체 흐름 제어, Manager 위임 487줄
SchedulerManager 크롤링 사이클, DB 체크, 스케줄링 399줄
NotificationManager Windows 토스트 알림, 팝업 다이얼로그 192줄
ReportManager 보고서 생성 요청, 인쇄, PDF 생성 위임 283줄
FileManager 첨부파일 다운로드 및 열기 151줄
UIManager UI 창 생성 및 포커스 관리 198줄
VOCScraper 웹 크롤링, 로그인 관리 -
ReportService HWP/PDF 생성, 인쇄 691줄
TimetableService 시각표 조회, 열차 검색 -
VOCParser VOC 텍스트 파싱 -
TrainAnalyzer 열차 정보 분석, 입고지 추적 355줄
DateScheduleUtils 날짜 처리, 공휴일 판별 -

10. 자동 업데이트 시스템 (Auto Update System) 신규

10.1 개요

목표: 프로그램의 자동 업데이트 기능 구현

  • Supabase 기반 원격 버전 관리
  • 1시간마다 자동 업데이트 체크
  • 사용자友好的 업데이트 알림 및 설치
  • 멀티프로젝트 지원: 다른 프로젝트에서도 재사용 가능한 모듈 설계

10.2 데이터베이스 테이블 정의 (Supabase)

테이블명: program_version

필드명 타입 설명 필수
id SERIAL Primary Key
program_id TEXT 프로그램 식별자 (예: "voc_monitor")
version TEXT 버전 번호 (예: "3.1.0")
is_stable BOOLEAN 안정版 여부
release_note TEXT 배포 노트
download_url TEXT 다운로드 URL
min_required_version TEXT 최소 요구 버전 (업그레이드 시)
created_at TIMESTAMP 생성일시
updated_at TIMESTAMP 수정일시

예시 데이터:

{
    "program_id": "voc_monitor",
    "version": "3.1.0",
    "is_stable": true,
    "release_note": "- 크롤링 필터링 개선\n- Z-order 문제 해결\n- 자동 업데이트 기능 추가",
    "download_url": "https://example.com/releases/voc_monitor_3.1.0.exe",
    "min_required_version": "2.0.0",
    "created_at": "2026-02-18T10:00:00Z"
}

10.3 로컬 버전 관리 파일

1. __version__.py

"""
버전 정보

이 파일은 프로그램의 현재 버전을 정의합니다.
업데이트 시 이 파일의 VERSION과 비교하여进行检查합니다.
"""
VERSION = "3.0.0"
PROGRAM_ID = "voc_monitor"
APP_NAME = "VOC 모니터링"

2. updatelog.md (위치: app/updater/updatelog.md)

# 업데이트 로그

## v3.1.0 (2026-02-18)
- 크롤링 필터링 개선 (AND/OR 모드 지원)
- Z-order 문제 해결
- 자동 업데이트 기능 추가

## v3.0.0 (2026-02-17)
- Controller 리팩토링
- Manager 패턴 적용

중요: updatelog.mdapp/updater/ 모듈 내에 위치하며, 개발 과정에서 발생한 변경사항을 기록하는 용도입니다. 모든 버전 업데이트 시 이 파일을 최신화해야 합니다.


10.4 모듈 설계 (utils/auto_updater.py)

class AutoUpdater:
    """
    자동 업데이트 관리자
    
    Supabase에서 버전 정보를 조회하고 업데이트를 처리합니다.
    
    Attributes:
        program_id: 프로그램 식별자
        current_version: 현재 버전
        supabase_url: Supabase 프로젝트 URL
        supabase_key: Supabase API 키
        check_interval: 업데이트 체크 간격 (기본: 1시간)
    
    주요 메서드:
        check_for_updates: 업데이트 확인
        download_update: 업데이트 파일 다운로드
        install_update: 업데이트 설치
        start_background_check: 백그라운드 업데이트 체크 시작
    """

10.5 업데이트 체크 주기

1시간마다 (기본값, 설정 가능)
├── Supabase에서 최신 버전 조회
├── 현재 버전과 비교
├── 업데이트 필요 시:
│   ├── 알림 다이얼로그 표시
│   ├── 사용자가 "지금 설치" 선택
│   │   ├── temp 폴더에 다운로드
│   │   ├── 현재 프로세스 종료
│   │   ├── 새 프로세스 실행 (업데이터)
│   │   └── 업데이터가 기존 파일 교체
│   └── "나중에" 선택 → 다음 주기까지 대기
└── 업데이트 없음 → 로그만 기록

통합 동작 (v3.2.2 반영):

  • 앱 시작 시 UpdateManager 초기화 후 백그라운드 체크 시작
  • 트레이 메뉴에 업데이트 확인 수동 항목 제공
  • 업데이트 발견 시 사용자 확인 다이얼로그 표시
  • 사용자 승인 시 prepare_update() -> launch_updater() -> 메인 앱 종료

로그 명세 (필수 기록):

  • 초기화 성공/실패
  • 백그라운드 체크 시작/오류
  • 수동 확인 수행/결과(최신/업데이트 필요)
  • 준비 실패/실행 실패 원인

10.6 아키텍처: updater.exe 분리 중요

구조:

메인 프로젝트 (cx_freeze 패킹)
├── updater.exe (별도 패킹, 최소 GUI 포함)
├── app/
│   └── updater/
│       ├── __init__.py
│       ├── __version__.py      # 버전 정보
│       ├── update_manager.py   # 메인 프로그램용 업데이트 관리자
│       ├── updater_gui.py      # updater.exe용 GUI
│       └── updatelog.md        # 업데이트 로그
└── ...

실행 흐름:

1. update_manager.py (메인 프로그램 내):
   ├── Supabase에서 새 버전 확인
   ├── 업데이트 config.json 생성 (%TEMP%/voc_updater_config.json)
   │   {
   │     "download_url": "https://supabase.../voc_noti_3.2.0.zip",
   │     "target_path": "C:/Program Files/voc_noti",
   │     "version": "3.2.0",
   │     "restart_exe": "voc_noti.exe"
   │   }
   ├── updater.exe를 %TEMP%로 복사
   └── updater.exe 실행 후 메인 프로그램 종료

2. updater.exe (별도 프로세스):
   ├── config.json 읽기
   ├── zip 다운로드 (진행률 표시 - CustomTkinter GUI)
   ├── 압축 해제 → 파일 교체
   └── 메인 프로그램 재실행

updater.exe UI:

  • CustomTkinter 기반 최소 GUI 창
  • 다운로드 진행률 표시 (Progress Bar)
  • 상태 메시지 표시 (다운로드 중, 압축 해제 중, 완료)
  • 성공/실패 결과 표시

파일 교체 방식:

  • 전체 교체: zip 다운로드 후 압축 해제
  • 백업 폴더 생성 (이전 버전 보존)
  • 실패 시 롤백 가능

통신 방식:

  • 임시 JSON 파일 (%TEMP%/voc_updater_config.json)
  • 메인 프로그램이 파일 생성 → updater.exe가 읽기

10.7 예외 케이스 처리

상황 처리 방법
네트워크 오류 업데이트 체크 건너뛰기, 로그 기록
Supabase 연결 실패 재시도 (3회), 실패 시 다음 주기까지 대기
다운로드 실패 에러 메시지 표시, 재시도 옵션 제공
설치 중 오류 롤백 (백업 파일 활용), 에러 로그 기록
자기 자신 업데이트 temp 폴더에 복사 후 별도 프로세스로 실행
버전 불일치 min_required_version 기준 판단

추가 안정화 반영 (통합 전 단독 검증 단계):

  • Supabase URL/KEY 누락 시 사전 설정 오류 반환
  • voc_updater_config.json 원자적 저장(.tmp -> 교체)
  • updater.exe 누락 시 준비 단계에서 즉시 실패 반환
  • 압축 해제 시 임시 폴더 사용 후 대상 경로에 단계적 복사
  • 설치 실패 시 백업 롤백 + 임시 폴더 정리

10.8 멀티프로젝트 지원

설계 원칙:

  • program_id 기반으로 동적 설정
  • Supabase 테이블 구조的统一
  • 설정 파일로 URL/Key 관리

사용 예시:

# VOC 모니터링
updater = AutoUpdater(
    program_id="voc_monitor",
    current_version=VERSION,
    settings=settings
)

# 다른 프로젝트
updater = AutoUpdater(
    program_id="other_app",
    current_version="1.0.0",
    settings=settings
)

10.9 의존성

{
    "supabase": "^2.0.0",
    "requests": "^2.31.0"
}

10.10 연결 설정 관리 (하드코딩 금지)

  • Supabase 연결 정보는 app/updater/config.json에서 관리
    • config_url: 원격 설정 URL
    • fallback.supabase_url, fallback.anon_key: 원격 실패 시 대체값
  • 런타임 동작 설정은 settings.jsonupdate 섹션에서 관리
    • connection_config_path, environment, check_interval_hours, program_id, version_table
  • 버전 체크 시 테이블 자동 폴백 지원
    • program_version 조회 실패(404) 시 program_versions 재시도

10.11 테스트 모드 검증 옵션

  • python app/main.py --test --test-update-now
    • 테스트 DB 모드로 앱을 실행하면서 updater 연결 확인을 시작 직후 1회 수행
    • 네트워크/설정 오류 시 사용자 메시지 + 로그 기록

10.12 업데이터 빌드/통합 절차

  1. 업데이터 단독 빌드
    • python app/update_build_setup.py
    • 결과: app/updater_build/dist/updater.exe
  2. 메인 패키징
    • python app/setup.py build
    • 포함 항목:
      • updater.exe (메인 exe와 동일 경로)
      • app/updater/config.json (연결 설정)
  3. 런타임
    • UpdateManager.prepare_update()가 설치 경로의 updater.exe%TEMP%로 복사 후 실행

11. 향후 개선 사항 (Roadmap 참조)

  • 다중 호선 지원 (2호선, 3호선)
  • 통계 대시보드
  • 엑셀 내보내기
  • 자동 응답 템플릿

작성자: KH.Choi 최종 수정: 2026-02-18 버전: 3.3