# ๐Ÿ” ์•„ํ‚คํ…์ฒ˜ ์˜ํ–ฅ๋„ ๋ถ„์„: VOC ํ†ต๊ณ„/ํ†ตํ•ฉ ๋ถ„์„๋ณด๊ณ ์„œ ## ๐Ÿ“‹ ๊ธฐ๋Šฅ ๊ฐœ์š” **๊ธฐ๋Šฅ๋ช…**: VOC ํ†ต๊ณ„/ํ†ตํ•ฉ ๋ถ„์„๋ณด๊ณ ์„œ **์ œ์•ˆ์ผ**: 2026-02-17 **์ œ์•ˆ์ž**: KH.Choi **๋ชฉํ‘œ**: ์ˆ˜์ง‘๋œ VOC ๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ†ต๊ณ„ ๋ถ„์„ ๋ฐ ํ†ตํ•ฉ ๋ณด๊ณ ์„œ ์ž๋™ ์ƒ์„ฑ --- ## ๐Ÿ—๏ธ ํ˜„์žฌ ์•„ํ‚คํ…์ฒ˜ ๋ถ„์„ ### ๊ธฐ์กด ๊ตฌ์กฐ ``` AppController โ”œโ”€โ”€ SchedulerManager (ํฌ๋กค๋ง, DB ์ฒดํฌ) โ”œโ”€โ”€ NotificationManager (์•Œ๋ฆผ) โ”œโ”€โ”€ ReportService (HWP/PDF ๋ณด๊ณ ์„œ ์ƒ์„ฑ) โ”œโ”€โ”€ VOCDatabase (SQLite) โ””โ”€โ”€ SystemTray (ํŠธ๋ ˆ์ด ์•„์ด์ฝ˜) ``` ### ๋ฐ์ดํ„ฐ ํ๋ฆ„ ``` ์›น์‚ฌ์ดํŠธ โ†’ VOCScraper โ†’ VOCPost (Pydantic) โ†’ VOCDatabase (SQLite) โ†“ HistoryDialog (์กฐํšŒ) โ†“ ReportService (HWP ์ƒ์„ฑ) ``` --- ## ๐Ÿ“Š ์˜ํ–ฅ๋„ ๋ถ„์„ ### 1. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ ˆ์ด์–ด (Low Impact) **ํ˜„์žฌ ์ƒํƒœ**: - SQLite ๊ธฐ๋ฐ˜ - `voc_posts` ํ…Œ์ด๋ธ” (id, title, writer, department, date, status, content ๋“ฑ) - ๊ธฐ๋ณธ CRUD ์ž‘์—…๋งŒ ์ง€์› **ํ•„์š”ํ•œ ๋ณ€๊ฒฝ**: - โœ… **์ถ”๊ฐ€ ํ…Œ์ด๋ธ” ๋ถˆํ•„์š”** (๊ธฐ์กด ๋ฐ์ดํ„ฐ๋กœ ์ถฉ๋ถ„) - โœ… **์ธ๋ฑ์Šค ์ถ”๊ฐ€ ํ•„์š”** (์„ฑ๋Šฅ ์ตœ์ ํ™”) - `CREATE INDEX idx_date ON voc_posts(date);` - `CREATE INDEX idx_department ON voc_posts(department);` - `CREATE INDEX idx_status ON voc_posts(status);` - โœ… **์ง‘๊ณ„ ์ฟผ๋ฆฌ ๋ฉ”์„œ๋“œ ์ถ”๊ฐ€** (`VOCDatabase` ํด๋ž˜์Šค) - `get_stats_by_period(start_date, end_date)` - `get_stats_by_department()` - `get_keyword_frequency()` **์˜ํ–ฅ๋„**: ๐ŸŸข ๋‚ฎ์Œ (๊ธฐ์กด ๊ตฌ์กฐ ์œ ์ง€, ๋ฉ”์„œ๋“œ ์ถ”๊ฐ€๋งŒ) --- ### 2. ์„œ๋น„์Šค ๋ ˆ์ด์–ด (Medium Impact) **ํ˜„์žฌ ์ƒํƒœ**: - `ReportService`: HWP/PDF ๋ณด๊ณ ์„œ ์ƒ์„ฑ - `ScraperService`: ์›น ํฌ๋กค๋ง - `TimetableService`: ์‹œ๊ฐํ‘œ ์กฐํšŒ **ํ•„์š”ํ•œ ๋ณ€๊ฒฝ**: - โš ๏ธ **์‹ ๊ทœ ์„œ๋น„์Šค ์ถ”๊ฐ€**: `StatisticsService` - ํ†ต๊ณ„ ๋ฐ์ดํ„ฐ ์ง‘๊ณ„ - ์ฐจํŠธ ์ƒ์„ฑ (matplotlib/plotly) - Excel/PDF ๋ณด๊ณ ์„œ ์ƒ์„ฑ - โš ๏ธ **ReportService์™€์˜ ๊ด€๊ณ„** - `ReportService`: ๊ฐœ๋ณ„ VOC ๋ณด๊ณ ์„œ (HWP) - `StatisticsService`: ํ†ตํ•ฉ ๋ถ„์„ ๋ณด๊ณ ์„œ (Excel/PDF) - ์—ญํ•  ๋ถ„๋ฆฌ ๋ช…ํ™• โ†’ ์ถฉ๋Œ ์—†์Œ **์˜ํ–ฅ๋„**: ๐ŸŸก ์ค‘๊ฐ„ (์‹ ๊ทœ ์„œ๋น„์Šค ์ถ”๊ฐ€, ๊ธฐ์กด ์„œ๋น„์Šค ์˜ํ–ฅ ์—†์Œ) --- ### 3. ์ปจํŠธ๋กค๋Ÿฌ ๋ ˆ์ด์–ด (Low Impact) **ํ˜„์žฌ ์ƒํƒœ**: - `AppController`: UI ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ - `SchedulerManager`: ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ž‘์—… - `NotificationManager`: ์•Œ๋ฆผ **ํ•„์š”ํ•œ ๋ณ€๊ฒฝ**: - โœ… **AppController์— ๋ฉ”์„œ๋“œ ์ถ”๊ฐ€** - `request_generate_statistics(period, options)` - `open_statistics_view()` - โœ… **๊ธฐ์กด ๋กœ์ง ์˜ํ–ฅ ์—†์Œ** **์˜ํ–ฅ๋„**: ๐ŸŸข ๋‚ฎ์Œ (๋ฉ”์„œ๋“œ ์ถ”๊ฐ€๋งŒ) --- ### 4. ๋ทฐ ๋ ˆ์ด์–ด (Medium Impact) **ํ˜„์žฌ ์ƒํƒœ**: - `HistoryDialog`: VOC ๋ชฉ๋ก ์กฐํšŒ - `SettingsDialog`: ์„ค์ • ๊ด€๋ฆฌ - `ReportOptionDialog`: ๋ณด๊ณ ์„œ ์˜ต์…˜ **ํ•„์š”ํ•œ ๋ณ€๊ฒฝ**: - โš ๏ธ **์‹ ๊ทœ ๋‹ค์ด์–ผ๋กœ๊ทธ ์ถ”๊ฐ€**: `StatisticsDialog` - ๊ธฐ๊ฐ„ ์„ ํƒ (์‹œ์ž‘์ผ, ์ข…๋ฃŒ์ผ) - ๋ถ„์„ ์˜ต์…˜ (๋ถ€์„œ๋ณ„, ํ‚ค์›Œ๋“œ๋ณ„, ์—ญ๋ณ„) - ์ฐจํŠธ ๋ฏธ๋ฆฌ๋ณด๊ธฐ - ๋ณด๊ณ ์„œ ์ƒ์„ฑ ๋ฒ„ํŠผ - โš ๏ธ **HistoryDialog ํ™•์žฅ** (์„ ํƒ) - "ํ†ต๊ณ„ ๋ณด๊ธฐ" ๋ฒ„ํŠผ ์ถ”๊ฐ€ **์˜ํ–ฅ๋„**: ๐ŸŸก ์ค‘๊ฐ„ (์‹ ๊ทœ UI ์ถ”๊ฐ€, ๊ธฐ์กด UI ์˜ํ–ฅ ์—†์Œ) --- ### 5. ๋ชจ๋ธ ๋ ˆ์ด์–ด (Low Impact) **ํ˜„์žฌ ์ƒํƒœ**: - `VOCPost`: ๊ฐœ๋ณ„ VOC ๋ฐ์ดํ„ฐ ๋ชจ๋ธ **ํ•„์š”ํ•œ ๋ณ€๊ฒฝ**: - โœ… **์‹ ๊ทœ ๋ชจ๋ธ ์ถ”๊ฐ€**: `StatisticsReport` ```python class StatisticsReport(BaseModel): period_start: str period_end: str total_count: int by_department: dict by_status: dict top_keywords: list charts: dict # ์ฐจํŠธ ์ด๋ฏธ์ง€ ๊ฒฝ๋กœ ``` - โœ… **๊ธฐ์กด ๋ชจ๋ธ ์˜ํ–ฅ ์—†์Œ** **์˜ํ–ฅ๋„**: ๐ŸŸข ๋‚ฎ์Œ (์‹ ๊ทœ ๋ชจ๋ธ ์ถ”๊ฐ€๋งŒ) --- ### 6. ์œ ํ‹ธ๋ฆฌํ‹ฐ ๋ ˆ์ด์–ด (Low Impact) **ํ˜„์žฌ ์ƒํƒœ**: - `voc_parser.py`: VOC ํ…์ŠคํŠธ ํŒŒ์‹ฑ - `train_analyzer.py`: ์—ด์ฐจ ์ •๋ณด ๋ถ„์„ - `date_utils.py`: ๋‚ ์งœ ์ฒ˜๋ฆฌ **ํ•„์š”ํ•œ ๋ณ€๊ฒฝ**: - โœ… **์‹ ๊ทœ ์œ ํ‹ธ๋ฆฌํ‹ฐ ์ถ”๊ฐ€**: `chart_generator.py` - matplotlib/plotly ๊ธฐ๋ฐ˜ ์ฐจํŠธ ์ƒ์„ฑ - ์›Œ๋“œ ํด๋ผ์šฐ๋“œ ์ƒ์„ฑ - โœ… **๊ธฐ์กด ์œ ํ‹ธ๋ฆฌํ‹ฐ ์˜ํ–ฅ ์—†์Œ** **์˜ํ–ฅ๋„**: ๐ŸŸข ๋‚ฎ์Œ (์‹ ๊ทœ ์œ ํ‹ธ๋ฆฌํ‹ฐ ์ถ”๊ฐ€๋งŒ) --- ## ๐Ÿ”— ์˜์กด์„ฑ ๋ถ„์„ ### ์‹ ๊ทœ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ•„์š” ```python # ๋ฐ์ดํ„ฐ ๋ถ„์„ pandas>=1.5.0 # ์‹œ๊ฐํ™” matplotlib>=3.5.0 plotly>=5.0.0 # Excel ์ƒ์„ฑ openpyxl>=3.0.0 # ์›Œ๋“œ ํด๋ผ์šฐ๋“œ wordcloud>=1.8.0 # ํ•œ๊ธ€ ํฐํŠธ (์„ ํƒ) matplotlib-fontpkg-nanum ``` ### ๊ธฐ์กด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€์˜ ์ถฉ๋Œ ๊ฐ€๋Šฅ์„ฑ - โŒ **์ถฉ๋Œ ์—†์Œ**: ๋ชจ๋‘ ๋…๋ฆฝ์ ์ธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ - โœ… **ํ˜ธํ™˜์„ฑ ํ™•์ธ ํ•„์š”**: Python 3.8+ ์ง€์› ํ™•์ธ --- ## ๐Ÿ“ ํŒŒ์ผ ๊ตฌ์กฐ ๋ณ€๊ฒฝ ### ์‹ ๊ทœ ํŒŒ์ผ ``` app/ โ”œโ”€โ”€ services/ โ”‚ โ””โ”€โ”€ statistics_service.py (์‹ ๊ทœ) โ”œโ”€โ”€ models/ โ”‚ โ””โ”€โ”€ statistics.py (์‹ ๊ทœ) โ”œโ”€โ”€ utils/ โ”‚ โ””โ”€โ”€ chart_generator.py (์‹ ๊ทœ) โ”œโ”€โ”€ view/ โ”‚ โ””โ”€โ”€ dialogs/ โ”‚ โ””โ”€โ”€ statistics_dialog.py (์‹ ๊ทœ) ``` ### ์ˆ˜์ • ํŒŒ์ผ ``` app/ โ”œโ”€โ”€ controllers/ โ”‚ โ””โ”€โ”€ controller.py (๋ฉ”์„œ๋“œ ์ถ”๊ฐ€) โ”œโ”€โ”€ utils/ โ”‚ โ””โ”€โ”€ database.py (์ง‘๊ณ„ ์ฟผ๋ฆฌ ์ถ”๊ฐ€) โ”œโ”€โ”€ view/ โ”‚ โ””โ”€โ”€ dialogs/ โ”‚ โ””โ”€โ”€ history_dialog.py (ํ†ต๊ณ„ ๋ฒ„ํŠผ ์ถ”๊ฐ€, ์„ ํƒ) ``` --- ## โš ๏ธ ์ž ์žฌ์  ๋ฆฌ์Šคํฌ ### 1. ์„ฑ๋Šฅ ์ด์Šˆ **๋ฌธ์ œ**: ๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ง‘๊ณ„ ์‹œ SQLite ์„ฑ๋Šฅ ์ €ํ•˜ **ํ•ด๊ฒฐ**: - ์ธ๋ฑ์Šค ์ถ”๊ฐ€ - ๊ธฐ๊ฐ„ ์ œํ•œ (์ตœ๋Œ€ 1๋…„) - ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์Šค๋ ˆ๋“œ ์ฒ˜๋ฆฌ ### 2. ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ **๋ฌธ์ œ**: ์ฐจํŠธ ์ƒ์„ฑ ์‹œ ๋ฉ”๋ชจ๋ฆฌ ์ฆ๊ฐ€ **ํ•ด๊ฒฐ**: - ์ฐจํŠธ ์ƒ์„ฑ ํ›„ ์ฆ‰์‹œ ํŒŒ์ผ ์ €์žฅ - ๋ฉ”๋ชจ๋ฆฌ ํ•ด์ œ (plt.close()) ### 3. UI ์‘๋‹ต์„ฑ **๋ฌธ์ œ**: ๋ณด๊ณ ์„œ ์ƒ์„ฑ ์ค‘ UI ๋ฉˆ์ถค **ํ•ด๊ฒฐ**: - ํ”„๋กœ๊ทธ๋ ˆ์Šค ๋ฐ” ํ‘œ์‹œ - ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์Šค๋ ˆ๋“œ ์‚ฌ์šฉ --- ## ๐ŸŽฏ ๊ถŒ์žฅ ๊ตฌํ˜„ ์ˆœ์„œ ### Phase 1: ๊ธฐ๋ฐ˜ ๊ตฌ์ถ• (1์ฃผ) 1. `StatisticsService` ๊ธฐ๋ณธ ๊ตฌ์กฐ ์ƒ์„ฑ 2. `VOCDatabase` ์ง‘๊ณ„ ์ฟผ๋ฆฌ ์ถ”๊ฐ€ 3. `StatisticsReport` ๋ชจ๋ธ ์ •์˜ ### Phase 2: ๋ฐ์ดํ„ฐ ๋ถ„์„ (3์ผ) 4. ๊ธฐ๊ฐ„๋ณ„/๋ถ€์„œ๋ณ„/์ƒํƒœ๋ณ„ ํ†ต๊ณ„ ๋กœ์ง 5. ํ‚ค์›Œ๋“œ ๋นˆ๋„ ๋ถ„์„ 6. ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ๋กœ ๊ฒ€์ฆ ### Phase 3: ์‹œ๊ฐํ™” (3์ผ) 7. `chart_generator.py` ๊ตฌํ˜„ 8. matplotlib ๊ธฐ๋ฐ˜ ์ฐจํŠธ ์ƒ์„ฑ 9. ์›Œ๋“œ ํด๋ผ์šฐ๋“œ ์ƒ์„ฑ ### Phase 4: UI ํ†ตํ•ฉ (3์ผ) 10. `StatisticsDialog` ๊ตฌํ˜„ 11. Controller ๋ฉ”์„œ๋“œ ์ถ”๊ฐ€ 12. HistoryDialog ๋ฒ„ํŠผ ์ถ”๊ฐ€ ### Phase 5: ๋ณด๊ณ ์„œ ์ƒ์„ฑ (2์ผ) 13. Excel ๋ณด๊ณ ์„œ ์ƒ์„ฑ 14. PDF ๋ณด๊ณ ์„œ ์ƒ์„ฑ 15. ์ด๋ฉ”์ผ ๋ฐœ์†ก (์„ ํƒ) --- ## โœ… ๊ฒฐ๋ก  ### ์˜ํ–ฅ๋„ ์š”์•ฝ | ๋ ˆ์ด์–ด | ์˜ํ–ฅ๋„ | ๋ณ€๊ฒฝ ์œ ํ˜• | ๋ฆฌ์Šคํฌ | |--------|--------|-----------|--------| | Database | ๐ŸŸข ๋‚ฎ์Œ | ๋ฉ”์„œ๋“œ ์ถ”๊ฐ€ | ๋‚ฎ์Œ | | Service | ๐ŸŸก ์ค‘๊ฐ„ | ์‹ ๊ทœ ์„œ๋น„์Šค | ๋‚ฎ์Œ | | Controller | ๐ŸŸข ๋‚ฎ์Œ | ๋ฉ”์„œ๋“œ ์ถ”๊ฐ€ | ๋‚ฎ์Œ | | View | ๐ŸŸก ์ค‘๊ฐ„ | ์‹ ๊ทœ UI | ์ค‘๊ฐ„ | | Model | ๐ŸŸข ๋‚ฎ์Œ | ์‹ ๊ทœ ๋ชจ๋ธ | ๋‚ฎ์Œ | | Utils | ๐ŸŸข ๋‚ฎ์Œ | ์‹ ๊ทœ ์œ ํ‹ธ๋ฆฌํ‹ฐ | ๋‚ฎ์Œ | ### ์ „์ฒด ํ‰๊ฐ€ - **์ „์ฒด ์˜ํ–ฅ๋„**: ๐ŸŸก ์ค‘๊ฐ„ - **๊ธฐ์กด ๊ธฐ๋Šฅ ์˜ํ–ฅ**: โœ… ์—†์Œ (๋…๋ฆฝ์  ๊ธฐ๋Šฅ) - **๊ตฌํ˜„ ๋‚œ์ด๋„**: ๐ŸŸก ์ค‘๊ฐ„ - **์˜ˆ์ƒ ๊ฐœ๋ฐœ ๊ธฐ๊ฐ„**: 2์ฃผ - **๊ถŒ์žฅ ์‹œ๊ธฐ**: v2.5 (2026-03-31) ### ์Šน์ธ ๊ถŒ์žฅ ์‚ฌํ•ญ โœ… **์Šน์ธ ๊ถŒ์žฅ** - ๊ธฐ์กด ์•„ํ‚คํ…์ฒ˜์™€ ์ถฉ๋Œ ์—†์Œ - ๋…๋ฆฝ์ ์ธ ๋ชจ๋“ˆ๋กœ ๊ตฌํ˜„ ๊ฐ€๋Šฅ - ์‚ฌ์šฉ์ž ๊ฐ€์น˜ ๋†’์Œ (ํ†ต๊ณ„ ๋ถ„์„ ์ž๋™ํ™”) - ๋‹จ๊ณ„์  ๊ตฌํ˜„ ๊ฐ€๋Šฅ (Phase๋ณ„ ๋ถ„๋ฆฌ) --- ์ž‘์„ฑ์ž: KH.Choi ์ž‘์„ฑ์ผ: 2026-02-17 ๋ฒ„์ „: 1.0