# ๐Ÿ›  Issue & Task Log ## ๐Ÿ”ด ์šฐ์„ ์ˆœ์œ„: ๋†’์Œ (Current Sprint) ### [์™„๋ฃŒ] Controller ๋ฆฌํŒฉํ† ๋ง ๋ฐ ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๊ฐ•ํ™” โœ… - **๋ชฉํ‘œ**: Controller 730์ค„ โ†’ 350์ค„๋กœ ๊ฐ์†Œ, Manager ํŒจํ„ด ์ ์šฉ, ์—๋Ÿฌ ์ฒ˜๋ฆฌ ์ฒด๊ณ„ ๊ตฌ์ถ• - **๊ด€๋ จ ํŒŒ์ผ**: - `app/controllers/controller.py` (730์ค„ โ†’ 487์ค„) - `app/controllers/scheduler_manager.py` - `app/controllers/notification_manager.py` - `app/controllers/report_manager.py` (์‹ ๊ทœ) - `app/controllers/file_manager.py` (์‹ ๊ทœ) - `app/controllers/ui_manager.py` (์‹ ๊ทœ) - `app/core/exceptions.py` - **์™„๋ฃŒ ๋‚ด์—ญ**: - [x] ์—๋Ÿฌ ์ฒ˜๋ฆฌ ์ฒด๊ณ„ ๊ตฌ์ถ• (`core/exceptions.py`) - [x] SchedulerManager ๋ถ„๋ฆฌ (ํฌ๋กค๋ง, DB ์ฒดํฌ ๋กœ์ง) - [x] NotificationManager ๋ถ„๋ฆฌ (์•Œ๋ฆผ ๋กœ์ง) - [x] ReportManager ์‹ ๊ทœ ์ƒ์„ฑ (๋ณด๊ณ ์„œ ์ƒ์„ฑ/์ธ์‡„/PDF) - [x] FileManager ์‹ ๊ทœ ์ƒ์„ฑ (์ฒจ๋ถ€ํŒŒ์ผ ์ฒ˜๋ฆฌ) - [x] UIManager ์‹ ๊ทœ ์ƒ์„ฑ (UI ์ฐฝ ๊ด€๋ฆฌ) - [x] Controller์—์„œ Manager ์œ„์ž„ ํŒจํ„ด ์ ์šฉ - **์™„๋ฃŒ์ผ**: 2026-02-18 --- ### [์™„๋ฃŒ] ์•Œ๋žŒ ์‹œ์Šคํ…œ ๊ฐœ์„  โœ… - **๋ชฉํ‘œ**: ๋ฏธํ™•์ธ ๊ธ€ ์•Œ๋ฆผ, ์ค‘๋ณต ๋ฐฉ์ง€, ์„ค์ • ์˜์†ํ™” - **๊ด€๋ จ ํŒŒ์ผ**: - `app/controllers/scheduler_manager.py` - `app/utils/database.py` - **์™„๋ฃŒ ๋‚ด์—ญ**: - [x] ํ‚ค์›Œ๋“œ ๊ธฐ๋ฐ˜ ์•Œ๋ฆผ ํ•„ํ„ฐ๋ง ์ œ๊ฑฐ (๋ชจ๋“  ๊ด€์‹ฌ๊ธ€ ์•Œ๋ฆผ) - [x] ๋ฏธํ™•์ธ ๊ธ€ ์ฃผ๊ธฐ์  ์•Œ๋ฆผ ๊ธฐ๋Šฅ ์ถ”๊ฐ€ (30๋ถ„๋งˆ๋‹ค ์ฒดํฌ) - [x] last_check_time ์˜์†ํ™” (scheduler_state.json ์ €์žฅ) - [x] ์ค‘๋ณต ์•Œ๋ฆผ ๋ฐฉ์ง€ ๋ฉ”์ปค๋‹ˆ์ฆ˜ ์ถ”๊ฐ€ (notified_post_ids ์„ธํŠธ) - **์™„๋ฃŒ์ผ**: 2026-02-18 ### [์™„๋ฃŒ] ์•Œ๋ฆผ ์ฃผ๊ธฐ ์„ค์ •ํ™” ๋ฐ ๋ฏธํ™•์ธ ์กฐ๊ฑด ํ† ๊ธ€ โœ… - **๋ชฉํ‘œ**: ์‹ ๊ทœ/๋ฏธํ™•์ธ ์•Œ๋ฆผ ์ฃผ๊ธฐ๋ฅผ ์„ค์ •์—์„œ ์ œ์–ดํ•˜๊ณ , ๋ฏธํ™•์ธ 30๋ถ„ ๊ฒฝ๊ณผ ์กฐ๊ฑด์„ ON/OFF๋กœ ์ œ์–ด - **๊ด€๋ จ ํŒŒ์ผ**: - `app/view/dialogs/settings_dialog.py` - `app/controllers/scheduler_manager.py` - `app/controllers/controller.py` - `app/data/settings.json` - **์™„๋ฃŒ ๋‚ด์—ญ**: - [x] ์‹ ๊ทœ ์•Œ๋ฆผ ์ฃผ๊ธฐ ์„ค์ • ์ถ”๊ฐ€ (`noti.db_check_interval_minutes`, ๊ธฐ๋ณธ 3๋ถ„) - [x] ๋ฏธํ™•์ธ ์•Œ๋ฆผ ์ฃผ๊ธฐ ์„ค์ • ์ถ”๊ฐ€ (`noti.unchecked_check_interval_minutes`, ๊ธฐ๋ณธ 10๋ถ„) - [x] ๋ฏธํ™•์ธ 30๋ถ„ ๊ฒฝ๊ณผ ์กฐ๊ฑด ํ† ๊ธ€ ์ถ”๊ฐ€ (`noti.unchecked_delay_enabled`) - [x] ๊ด€์‹ฌ ์กฐ๊ฑด ์•Œ๋ฆผ ํ† ๊ธ€ ์ถ”๊ฐ€ (`noti.use_related_filter`) - [x] ์„ค์ • ํ† ๊ธ€ ์„ค๋ช…์šฉ `?` ํˆดํŒ ์ถ”๊ฐ€ (๊ด€์‹ฌ ์กฐ๊ฑด ํ† ๊ธ€, 30๋ถ„ ์ง€์—ฐ ํ† ๊ธ€) - [x] ์„ค์ • ์—ญํ•  ๋ถ„๋ฆฌ ์ •๋ฆฌ: ์•Œ๋ฆผ ํƒญ์˜ ์ค‘๋ณต ํ‚ค์›Œ๋“œ UI ์ œ๊ฑฐ, ํ‚ค์›Œ๋“œ/๋ถ€์„œ๋Š” ์ˆ˜์ง‘ ์„ค์ •์œผ๋กœ ์ผ์›ํ™” - [x] ์„ค์ • UI ์ž…๋ ฅ ์œ„์ ฏ ์ถฉ๋Œ ๋ฒ„๊ทธ ์ˆ˜์ • (`entry_kw` ๋ถ„๋ฆฌ) - [x] ์•Œ๋ฆผ ํŒ์—…์— `์ „์ฒด๋‚ด์—ญ ๋ณด๊ธฐ` ๋ฒ„ํŠผ ์ถ”๊ฐ€ (์‹ ๊ทœ/๋ฏธํ™•์ธ ๊ณตํ†ต), ๋‹ค๊ฑด ์•Œ๋ฆผ์—์„œ๋„ ๋ชฉ๋ก ์ฆ‰์‹œ ์—ด๊ธฐ ์ง€์› - [x] ๋‹ค๊ฑด ๋ฏธํ™•์ธ ์•Œ๋ฆผ ๋ชฉ๋ก ํ‘œ์‹œ ๋กœ์ง ๋™์ž‘ ํ™•์ธ - [x] ์ˆ˜์ง‘ ํ‚ค์›Œ๋“œ ๊ธฐ๋ณธ๊ฐ’์„ `1ํ˜ธ์„  + 1ํ˜ธ์„  ์ „์ฒด ์—ญ์‚ฌ`๋กœ ๋ฐ˜์˜, ๊ด€์‹ฌ ๋ถ€์„œ ๊ธฐ๋ณธ๊ฐ’ `์ฐจ๋Ÿ‰` ์œ ์ง€ - **์™„๋ฃŒ์ผ**: 2026-02-18 ### [์ง„ํ–‰์ค‘] ์—…๋ฐ์ดํ„ฐ ๋ชจ๋“ˆ ๋‹จ๋… ๊ฒ€์ฆ/์•ˆ์ •ํ™” ๐Ÿ”„ - **๋ชฉํ‘œ**: ํ†ตํ•ฉ ์ „ updater ๋ชจ๋“ˆ ๋‹จ๋… ์‹คํ–‰ ๊ฒ€์ฆ, ์—๋Ÿฌ์ฒ˜๋ฆฌ ๊ฐ•ํ™”, ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ํ™•๋ณด - **๊ด€๋ จ ํŒŒ์ผ**: - `app/updater/update_manager.py` - `app/updater/updater_gui.py` - `docs/updater_validation.md` - **์ง„ํ–‰ ๋‚ด์—ญ**: - [x] Supabase ์„ค์ • ๋ˆ„๋ฝ ์‚ฌ์ „ ๊ฒ€์ฆ - [x] config.json ์›์ž์  ์ €์žฅ ์ ์šฉ - [x] updater.exe ๋ˆ„๋ฝ ์‹œ ๋ช…์‹œ์  ์‹คํŒจ ์ฒ˜๋ฆฌ - [x] ์••์ถ• ํ•ด์ œ/๊ต์ฒด ๊ฒฝ๋กœ ์•ˆ์ •ํ™” ๋ฐ ๋กค๋ฐฑ ๋ณด๊ฐ• - [x] updater ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ์ž‘์„ฑ ๋ฐ ์‹คํ–‰ - ๋ฒ„์ „ ๋น„๊ต - Supabase ์„ค์ • ๋ˆ„๋ฝ ์˜ˆ์™ธ - updater.exe ๋ˆ„๋ฝ/๊ถŒํ•œ ์˜ค๋ฅ˜ - ์†์ƒ zip ์ฒ˜๋ฆฌ - ์„ค์น˜ ์‹คํŒจ ์‹œ ๋กค๋ฐฑ ๊ฒ€์ฆ - [x] ์ƒ˜ํ”Œ zip ์ˆ˜๋™ ๋ฆฌํ—ˆ์„ค ์ ˆ์ฐจ ๋ฌธ์„œํ™” (`docs/updater_validation.md`) - [x] ์—ฐ๊ฒฐ์ •๋ณด ์™ธ๋ถ€ํ™”: `app/updater/config.json` + `settings.json(update)` ๊ธฐ๋ฐ˜ ๋กœ๋“œ - [x] m1tcloud ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ ์‹ค์กฐํšŒ ๊ฒ€์ฆ (`program_id=voc_monitor`, `program_versions`) - **์ƒํƒœ**: ์™„๋ฃŒ ### [์ง„ํ–‰์ค‘] ์—…๋ฐ์ดํ„ฐ ๋ฉ”์ธ ์•ฑ ํ†ตํ•ฉ ๐Ÿ”„ - **๋ชฉํ‘œ**: ๋‹จ๋… ๊ฒ€์ฆ ์™„๋ฃŒ๋œ updater๋ฅผ ์ปจํŠธ๋กค๋Ÿฌ/ํŠธ๋ ˆ์ด์™€ ์—ฐ๊ฒฐ - **๊ด€๋ จ ํŒŒ์ผ**: - `app/controllers/controller.py` - `app/view/tray_icon.py` - **์ง„ํ–‰ ๋‚ด์—ญ**: - [x] ์•ฑ ์‹œ์ž‘ ์‹œ updater ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ฒดํฌ ์‹œ์ž‘ - [x] ํŠธ๋ ˆ์ด ๋ฉ”๋‰ด `์—…๋ฐ์ดํŠธ ํ™•์ธ` ์ถ”๊ฐ€ - [x] ์—…๋ฐ์ดํŠธ ๋ฐœ๊ฒฌ ์‹œ ์‚ฌ์šฉ์ž ์Šน์ธ ๋‹ค์ด์–ผ๋กœ๊ทธ ์—ฐ๊ฒฐ - [x] ์Šน์ธ ์‹œ `prepare_update`/`launch_updater` ์‹คํ–‰ ํ›„ ์•ฑ ์ข…๋ฃŒ - [x] ์ข…๋ฃŒ ์‹œ updater ๋ฐฑ๊ทธ๋ผ์šด๋“œ/์ž„์‹œํŒŒ์ผ ์ •๋ฆฌ - [x] m1tcloud ์‹ค์—ฐ๊ฒฐ ํ™•์ธ (`voc_monitor`, `program_versions`, ์ตœ์‹  ๋ฒ„์ „ 3.5.5 ์กฐํšŒ) - [x] ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ ๊ฐ•ํ™” (์„ค์ • ์˜ค๋ฅ˜/๋„คํŠธ์›Œํฌ ์˜ค๋ฅ˜/updater.exe ๋ˆ„๋ฝ ์‹œ ์‚ฌ์šฉ์ž ๋ฉ”์‹œ์ง€+๋กœ๊ทธ) - [x] ํ…Œ์ŠคํŠธ ๋ชจ๋“œ ์ฆ‰์‹œ ํ™•์ธ ์˜ต์…˜ ์ถ”๊ฐ€ (`--test --test-update-now`) - [x] ์—…๋ฐ์ดํŠธ ์•ˆ๋‚ด ์ค‘๋ณต ํŒ์—… ๋ฐฉ์ง€ (ํ‘œ์‹œ์ค‘ ๋ฝ + ๋™์ผ ๋ฒ„์ „ 60์ดˆ ์ฟจ๋‹ค์šด) - [x] ์—…๋ฐ์ดํ„ฐ ๋‹จ๋… ๋นŒ๋“œ ์Šคํฌ๋ฆฝํŠธ ์ถ”๊ฐ€ (`app/update_build_setup.py`) - [x] ๋ฉ”์ธ ํŒจํ‚ค์ง•์— `updater.exe`/`app/updater/config.json` ํฌํ•จ ๋กœ์ง ๋ฐ˜์˜ - [x] ์‹ค์ œ ๋นŒ๋“œ ์‹คํ–‰ ๋ฐ ์‚ฐ์ถœ๋ฌผ ๊ฒ€์ฆ - `app/updater_build/dist/updater.exe` - `app/build/exe.win-amd64-3.11/updater.exe` - **์ƒํƒœ**: ์™„๋ฃŒ --- ## ๐ŸŸก ์šฐ์„ ์ˆœ์œ„: ๋ณดํ†ต (In Progress / Pending) ### [์™„๋ฃŒ] CTkComboBox ์—ด์ฐจ๋ฒˆํ˜ธ ํ‘œ์‹œ ๋ฌธ์ œ ํ•ด๊ฒฐ โœ… - **๋ฌธ์ œ**: ์—ด์ฐจ๋ฒˆํ˜ธ ์กฐํšŒ ์‹คํŒจ ์‹œ ๋“œ๋กญ๋ฐ•์Šค์— "CTkComboBox" ํ…์ŠคํŠธ ํ‘œ์‹œ - **ํ•ด๊ฒฐ**: - ComboBox ๊ธฐ๋ณธ๊ฐ’์„ ๋นˆ ๋ฌธ์ž์—ด `""`๋กœ ์„ค์ • - `startswith("CTk")` ์ฒดํฌ๋กœ ์œ„์ ฏ ์ด๋ฆ„ ํ•„ํ„ฐ๋ง - ์—ด์ฐจ๋ฒˆํ˜ธ ์—†์„ ์‹œ ํŒŒ์ผ๋ช…/์กฐ์น˜์‚ฌํ•ญ์—์„œ ์ž๋™ ์ œ๊ฑฐ - **๊ด€๋ จ ํŒŒ์ผ**: - `app/view/dialogs/report_option_dialog.py` - `app/services/report_service.py` - **์™„๋ฃŒ์ผ**: 2026-02-18 ### [์™„๋ฃŒ] ์„ค์ • ๋‹ค์ด์–ผ๋กœ๊ทธ Z-order ๋ฌธ์ œ ํ•ด๊ฒฐ โœ… - **๋ฌธ์ œ**: HistoryDialog์—์„œ ์„ค์ • ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ SettingsDialog๊ฐ€ ๋’ค๋กœ ํ‘œ์‹œ - **ํ•ด๊ฒฐ**: - SettingsDialog์— parent ํŒŒ๋ผ๋ฏธํ„ฐ ์ถ”๊ฐ€ - `transient(parent)` ์„ค์ •์œผ๋กœ Z-order ๊ณ ์ • - `lift()` + `focus_force()`๋กœ ํฌ์ปค์Šค ๋ณด์žฅ - **๊ด€๋ จ ํŒŒ์ผ**: - `app/controllers/ui_manager.py` - `app/view/dialogs/settings_dialog.py` - **์™„๋ฃŒ์ผ**: 2026-02-18 ### [์™„๋ฃŒ] ํ†ต๊ณ„๋ถ„์„ ๋‹ค์ด์–ผ๋กœ๊ทธ ์ž์‹ ์ฐฝ Z-order ๋ฌธ์ œ ํ•ด๊ฒฐ โœ… - **๋ฌธ์ œ**: StatisticsDialog์—์„œ ๋ฏธ๋ฆฌ๋ณด๊ธฐ/๋ณด๊ณ ์„œ์ƒ์„ฑ ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ์ž์‹ ๋‹ค์ด์–ผ๋กœ๊ทธ๊ฐ€ ๋’ค๋กœ ํ‘œ์‹œ - **ํ•ด๊ฒฐ**: - ๋ฏธ๋ฆฌ๋ณด๊ธฐ ์ฐฝ์— `transient(self)`, `lift()`, `focus_force()` ์ถ”๊ฐ€ - ํ”„๋กœ๊ทธ๋ ˆ์Šค ๋‹ค์ด์–ผ๋กœ๊ทธ์— `lift()`, `focus_force()` ์ถ”๊ฐ€ - **๊ด€๋ จ ํŒŒ์ผ**: - `app/view/dialogs/statistics_dialog.py` - **์™„๋ฃŒ์ผ**: 2026-02-18 ### [๋Œ€๊ธฐ] HWP ๋น„๊ณ ๋ž€ ๊ฐœ์„  - **๋ฌธ์ œ**: ์šดํ–‰ ์ •๋ณด ๋ฏธ์กฐํšŒ ์‹œ "์šดํ–‰์ •๋ณด ๋ฏธ์กฐํšŒ" ํ…์ŠคํŠธ ์‚ฝ์ž… - **ํ•ด๊ฒฐ ๋ฐฉ์•ˆ**: - ๋ถ€๋ถ„ ์‹คํŒจ ์‹œ ๋น„๊ณ ๋ž€ ๋น„์›Œ๋‘๊ธฐ - ๋˜๋Š” "์ •๋ณด ์—†์Œ" ๋“ฑ ์ค‘๋ฆฝ์  ํ‘œํ˜„ ์‚ฌ์šฉ - **๊ด€๋ จ ํŒŒ์ผ**: `app/services/report_service.py` ### [๋Œ€๊ธฐ] ๋กœ๊ทธ ๋ทฐ์–ด ๊ฐœ์„  - **ํ˜„์žฌ ์ƒํƒœ**: ์„ค์ • ์ฐฝ์—์„œ ๋กœ๊ทธ ํ™•์ธ ๊ฐ€๋Šฅ - **๊ฐœ์„  ์‚ฌํ•ญ**: - ๋กœ๊ทธ ๋ ˆ๋ฒจ๋ณ„ ํ•„ํ„ฐ๋ง (INFO/WARNING/ERROR) - ๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ - ์ž๋™ ์Šคํฌ๋กค ## ๐ŸŸข ์™„๋ฃŒ๋จ (Resolved) ### [2026-02-17] Controller ๋ฆฌํŒฉํ† ๋ง ๋ฐ ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๊ฐ•ํ™” โœ… - **๋‚ด์šฉ**: Controller 601์ค„ โ†’ 3๊ฐœ ํŒŒ์ผ๋กœ ๋ถ„๋ฆฌ, ์—๋Ÿฌ ์ฒ˜๋ฆฌ ์ฒด๊ณ„ ๊ตฌ์ถ• - **๋ถ„๋ฆฌ ๋ชจ๋“ˆ**: - `controllers/controller.py`: ํ•ต์‹ฌ ํ๋ฆ„ ์ œ์–ด (~700์ค„, ์ฃผ์„ ํฌํ•จ) - `controllers/scheduler_manager.py`: ์Šค์ผ€์ค„๋ง ๋กœ์ง (~400์ค„) - `controllers/notification_manager.py`: ์•Œ๋ฆผ ๋กœ์ง (~150์ค„) - **๊ฐœ์„  ํšจ๊ณผ**: - ๋‹จ์ผ ์ฑ…์ž„ ์›์น™ ์ค€์ˆ˜ - ์˜์กด์„ฑ ์ฃผ์ž… ๋ฐฉ์‹ ์ ์šฉ - ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๊ฐ•ํ™” (try-except, ์‚ฌ์šฉ์ž ์นœํ™”์  ๋ฉ”์‹œ์ง€) - ์ฝ”๋“œ ๊ฐ€๋…์„ฑ ํ–ฅ์ƒ ### [2026-02-17] ๋ฐ์ดํ„ฐ ๋ชจ๋ธ ๊ฐ•ํ™” (Pydantic Validator) - **๋‚ด์šฉ**: VOCPost ๋ชจ๋ธ์— ๋ฐ์ดํ„ฐ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ์ถ”๊ฐ€ - **์ถ”๊ฐ€ Validator**: - `validate_id`: ID ๋น„์–ด์žˆ์ง€ ์•Š์Œ ๊ฒ€์ฆ - `validate_required_strings`: ํ•„์ˆ˜ ๋ฌธ์ž์—ด ํ•„๋“œ ๊ฒ€์ฆ - `validate_binary_int`: 0 ๋˜๋Š” 1๋งŒ ํ—ˆ์šฉ - `validate_date_format`: ๋‚ ์งœ ํ˜•์‹ ๊ฒ€์ฆ - `validate_attachment`: "์—†์Œ" โ†’ None ์ •๊ทœํ™” - **๊ด€๋ จ ํŒŒ์ผ**: `app/models/model.py` ### [2026-02-17] ReportService ๋ฆฌํŒฉํ† ๋ง (v2.0) - **๋‚ด์šฉ**: 1056์ค„ โ†’ 400์ค„ (62% ๊ฐ์†Œ) - **๋ถ„๋ฆฌ ๋ชจ๋“ˆ**: - `utils/voc_parser.py`: VOC ํ…์ŠคํŠธ ํŒŒ์‹ฑ - `utils/date_utils.py`: ๋‚ ์งœ ์ฒ˜๋ฆฌ - `utils/train_analyzer.py`: ์—ด์ฐจ ์ •๋ณด ๋ถ„์„ - **๊ฐœ์„  ํšจ๊ณผ**: - ๋‹จ์ผ ์ฑ…์ž„ ์›์น™ ์ค€์ˆ˜ - ์žฌ์‚ฌ์šฉ์„ฑ ํ–ฅ์ƒ - ํ…Œ์ŠคํŠธ ์šฉ์ด์„ฑ ์ฆ๊ฐ€ ### [2026-02-17] ๊ธฐ์กด ๋ณด๊ณ ์„œ ์ค‘๋ณต ์ฒดํฌ ๊ธฐ๋Šฅ - **๋‚ด์šฉ**: ๋™์ผํ•œ ๋ณด๊ณ ์„œ ์ƒ์„ฑ ์‹œ ์‚ฌ์šฉ์ž ์„ ํƒ ๋‹ค์ด์–ผ๋กœ๊ทธ ํ‘œ์‹œ - **์˜ต์…˜**: ๊ธฐ์กด ํŒŒ์ผ ์—ด๊ธฐ / ์ƒˆ๋กœ ์ƒ์„ฑ / ์ทจ์†Œ - **๊ด€๋ จ ํŒŒ์ผ**: - `app/services/report_service.py` - `app/controllers/controller.py` ### [2026-02-17] ํžˆ์Šคํ† ๋ฆฌ ๋‹ค์ด์–ผ๋กœ๊ทธ ์„ค์ • ๋ฒ„ํŠผ ์ถ”๊ฐ€ - **๋‚ด์šฉ**: "โš™๏ธ ์„ค์ •" ๋ฒ„ํŠผ ์ถ”๊ฐ€๋กœ ๋น ๋ฅธ ์ ‘๊ทผ ๊ฐ€๋Šฅ - **๊ด€๋ จ ํŒŒ์ผ**: `app/view/dialogs/history_dialog.py` ### [2026-02-14] ์‹œ๊ฐํ‘œ ๊ธฐ๋ฐ˜ ์—ด์ฐจ ์ •๋ณด ์œ ์ถ” - **๋‚ด์šฉ**: ์—ญ๋ช…, ์‹œ๊ฐ„ ๊ธฐ๋ฐ˜ ์—ด์ฐจ๋ฒˆํ˜ธ ์ž๋™ ์ถ”์ถœ - **๊ด€๋ จ ํŒŒ์ผ**: - `app/services/timetable_service.py` - `app/services/report_service.py` ### [2026-02-14] ์ฃผ๋ฐ•์ง€ ์ž…์ถœ๊ณ  ๋กœ์ง ๊ตฌํ˜„ - **๋‚ด์šฉ**: ๋‹ค๋Œ€ํฌ ์ฃผ๋ฐ•์ง€ ์ž…์ถœ๊ณ  ์ˆœ์„œ ๋งคํ•‘ ๋ฐ ์ต์ผ ์˜ˆ์ธก - **๊ด€๋ จ ํŒŒ์ผ**: `app/services/report_service.py` --- ## โš ๏ธ ์•Œ๋ ค์ง„ ๋ฌธ์ œ (Known Bugs) ### BUG-001: ์—ด์ฐจ๋ฒˆํ˜ธ ์กฐํšŒ ์‹คํŒจ ์‹œ UI ์˜ค๋ฅ˜ โœ… ํ•ด๊ฒฐ๋จ (2026-02-18) - **ํ˜„์ƒ**: ๋“œ๋กญ๋ฐ•์Šค์— "CTK" ๋“ฑ ์—๋Ÿฌ ๊ฐ์ฒด ํ‘œ์‹œ - **์›์ธ**: ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋ถ€์žฌ, ์—๋Ÿฌ ๊ฐ์ฒด๊ฐ€ UI๋กœ ์ „ํŒŒ - **ํ•ด๊ฒฐ**: ComboBox ๊ธฐ๋ณธ๊ฐ’ ์„ค์ • ๋ฐ CTk ๋ฌธ์ž์—ด ํ•„ํ„ฐ๋ง - **์ƒํƒœ**: ์™„๋ฃŒ ### BUG-002: ์„ธ์…˜ ๋งŒ๋ฃŒ ์‹œ ๋ฌดํ•œ ์žฌ์‹œ๋„ โœ… ํ•ด๊ฒฐ๋จ (2026-02-18) - **ํ˜„์ƒ**: ๋กœ๊ทธ์ธ ์„ธ์…˜ ๋งŒ๋ฃŒ ์‹œ ์žฌ๋กœ๊ทธ์ธ ๋ฌดํ•œ ๋ฐ˜๋ณต - **์›์ธ**: ์žฌ๋กœ๊ทธ์ธ ์‹คํŒจ ์‹œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋ถ€์žฌ - **ํ•ด๊ฒฐ**: `max_retries`, `retry_delay` ์„ค์ • ์ถ”๊ฐ€ (settings.json) - **์ƒํƒœ**: ์™„๋ฃŒ --- ## ๐ŸŽ‰ ์ตœ๊ทผ ์™„๋ฃŒ๋œ ์ฃผ์š” ๊ฐœ์„ ์‚ฌํ•ญ (2026-02-18) ### ํฌ๋กค๋ง ์‹œ์Šคํ…œ ๊ฐœ์„  โœ… - **ํ•˜๋“œ์ฝ”๋”ฉ ์ œ๊ฑฐ**: `scraper_service.py`์˜ `target_depts = ['์ฐจ๋Ÿ‰', '๊ฒ€์ˆ˜']` ํ•˜๋“œ์ฝ”๋”ฉ ์ œ๊ฑฐ - **์„ค์ • ์—ฐ๋™**: ๋ชจ๋“  ํ•„ํ„ฐ๋ง ์„ค์ •์„ `settings.json`์—์„œ ๋™์  ๋กœ๋“œ - **ํ•„ํ„ฐ๋ง ๊ณ ๋„ํ™”**: - AND/OR ๋ชจ๋“œ ์ง€์› (`filter_mode` ์„ค์ •) - `_check_filter_match()` ๋ฉ”์„œ๋“œ๋กœ ํ•„ํ„ฐ๋ง ๋กœ์ง ์ค‘์•™ํ™” - ํ‚ค์›Œ๋“œ ๋ฐ ๋ถ€์„œ ๋งค์นญ ๋กœ์ง ๊ฐœ์„  - **์˜ˆ์™ธ์ฒ˜๋ฆฌ ๊ฐ•ํ™”**: `max_retries`, `retry_delay` ์„ค์ • ์ถ”๊ฐ€ - **๊ด€๋ จ ํŒŒ์ผ**: - `app/services/scraper_service.py` - `app/controllers/controller.py` - `app/data/settings.json` ### BUG-002: ์„ธ์…˜ ๋งŒ๋ฃŒ ์‹œ ๋ฌดํ•œ ์žฌ์‹œ๋„ - **ํ˜„์ƒ**: ๋กœ๊ทธ์ธ ์„ธ์…˜ ๋งŒ๋ฃŒ ์‹œ ์žฌ๋กœ๊ทธ์ธ ๋ฌดํ•œ ๋ฐ˜๋ณต - **์›์ธ**: ์žฌ๋กœ๊ทธ์ธ ์‹คํŒจ ์‹œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋ถ€์žฌ - **์˜ํ–ฅ๋„**: ๋‚ฎ (์ˆ˜๋™ ์žฌ์‹œ์ž‘์œผ๋กœ ํ•ด๊ฒฐ) - **์ˆ˜์ • ๊ณ„ํš**: ์žฌ์‹œ๋„ ํšŸ์ˆ˜ ์ œํ•œ ์ถ”๊ฐ€ --- ## ๐Ÿ“ ๊ธฐ์ˆ  ๋ถ€์ฑ„ (Technical Debt) ### DEBT-001: Pydantic ๋ฏธ์ ์šฉ ์˜์—ญ - **ํ˜„์žฌ**: Controller์—์„œ dict ์ง์ ‘ ์ „๋‹ฌ - **๋ชฉํ‘œ**: ๋ชจ๋“  ๋ฐ์ดํ„ฐ ๊ตํ™˜์„ Pydantic ๋ชจ๋ธ๋กœ ๋ณ€ํ™˜ - **์šฐ์„ ์ˆœ์œ„**: ๋‚ฎ (๋™์ž‘์—๋Š” ๋ฌธ์ œ ์—†์Œ) ### DEBT-002: ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ๋ถ€์žฌ - **ํ˜„์žฌ**: ์ˆ˜๋™ ํ…Œ์ŠคํŠธ๋งŒ ์ง„ํ–‰ - **๋ชฉํ‘œ**: ์ฃผ์š” ๋ชจ๋“ˆ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ์ž‘์„ฑ - **์šฐ์„ ์ˆœ์œ„**: ์ค‘ --- ์ž‘์„ฑ์ž: KH.Choi ์ตœ์ข… ์ˆ˜์ •: 2026-02-18