# ๐Ÿ“… ๋‹ฌ๋ ฅ ์œ„์ ฏ ๊ตฌํ˜„ ๊ณ„ํš ## ๊ฐœ์š” ๋Œ€์‹œ๋ณด๋“œ์— ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋Š” ๋‹ฌ๋ ฅ ์œ„์ ฏ์„ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ๋‚ ์งœ๋ฅผ ํ™•์ธํ•˜๊ณ  ์ผ์ •์„ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒํ•œ ๋‹ฌ๋ ฅ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ## ์ฃผ์š” ๊ธฐ๋Šฅ ### 1. ๋‹ฌ๋ ฅ ๋ทฐ ํƒ€์ž… - **์›”๊ฐ„ ๋ทฐ**: ํ•œ ๋‹ฌ ์ „์ฒด๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๊ธฐ๋ณธ ๋ทฐ - **์ฃผ๊ฐ„ ๋ทฐ**: ์ผ์ฃผ์ผ์„ ์„ธ๋กœ๋กœ ๋ณด์—ฌ์ฃผ๋Š” ๋ทฐ - **์ผ๊ฐ„ ๋ทฐ**: ํ•˜๋ฃจ์˜ ์‹œ๊ฐ„๋Œ€๋ณ„ ์ผ์ • ๋ทฐ ### 2. ๋‹ฌ๋ ฅ ์„ค์ • - **์‹œ์ž‘ ์š”์ผ**: ์›”์š”์ผ ์‹œ์ž‘ / ์ผ์š”์ผ ์‹œ์ž‘ ์„ ํƒ - **์ฃผ๋ง ๊ฐ•์กฐ**: ์ฃผ๋ง ์ƒ‰์ƒ ๋‹ค๋ฅด๊ฒŒ ํ‘œ์‹œ - **์˜ค๋Š˜ ๋‚ ์งœ ๊ฐ•์กฐ**: ์˜ค๋Š˜ ๋‚ ์งœ ํ•˜์ด๋ผ์ดํŠธ - **๊ณตํœด์ผ ํ‘œ์‹œ**: ํ•œ๊ตญ ๊ณตํœด์ผ ํ‘œ์‹œ (์„ ํƒ ์‚ฌํ•ญ) ### 3. ํ…Œ๋งˆ ๋ฐ ์Šคํƒ€์ผ - **Light ํ…Œ๋งˆ**: ๋ฐ์€ ๋ฐฐ๊ฒฝ - **Dark ํ…Œ๋งˆ**: ์–ด๋‘์šด ๋ฐฐ๊ฒฝ - **์‚ฌ์šฉ์ž ์ง€์ •**: ์ปค์Šคํ…€ ์ƒ‰์ƒ ์„ ํƒ ### 4. ์ผ์ • ๊ธฐ๋Šฅ (ํ–ฅํ›„ ํ™•์žฅ) - ๊ฐ„๋‹จํ•œ ๋ฉ”๋ชจ ์ถ”๊ฐ€ - ์ผ์ • ํ‘œ์‹œ (์™ธ๋ถ€ ์—ฐ๋™) ## ๊ตฌํ˜„ ๋‹จ๊ณ„ ### โœ… Step 1: ํƒ€์ž… ์ •์˜ - [ ] `CalendarConfig` ์ธํ„ฐํŽ˜์ด์Šค ์ •์˜ - [ ] `types.ts`์— ๋‹ฌ๋ ฅ ์„ค์ • ํƒ€์ž… ์ถ”๊ฐ€ - [ ] ์š”์†Œ ํƒ€์ž…์— 'calendar' subtype ์ถ”๊ฐ€ ### โœ… Step 2: ๊ธฐ๋ณธ ๋‹ฌ๋ ฅ ์ปดํฌ๋„ŒํŠธ - [ ] `CalendarWidget.tsx` - ๋ฉ”์ธ ์œ„์ ฏ ์ปดํฌ๋„ŒํŠธ - [ ] `MonthView.tsx` - ์›”๊ฐ„ ๋‹ฌ๋ ฅ ๋ทฐ - [ ] `WeekView.tsx` - ์ฃผ๊ฐ„ ๋‹ฌ๋ ฅ ๋ทฐ (์„ ํƒ) - [ ] ๋‚ ์งœ ๊ณ„์‚ฐ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜ ### โœ… Step 3: ๋‹ฌ๋ ฅ ๋„ค๋น„๊ฒŒ์ด์…˜ - [ ] ์ด์ „/๋‹ค์Œ ์›” ์ด๋™ ๋ฒ„ํŠผ - [ ] ์˜ค๋Š˜๋กœ ๋Œ์•„๊ฐ€๊ธฐ ๋ฒ„ํŠผ - [ ] ์›”/์—ฐ๋„ ์„ ํƒ ๋“œ๋กญ๋‹ค์šด ### โœ… Step 4: ์„ค์ • UI - [ ] `CalendarSettings.tsx` - Popover ๋‚ด์žฅ ์„ค์ • ์ปดํฌ๋„ŒํŠธ - [ ] ๋ทฐ ํƒ€์ž… ์„ ํƒ (์›”๊ฐ„/์ฃผ๊ฐ„/์ผ๊ฐ„) - [ ] ์‹œ์ž‘ ์š”์ผ ์„ค์ • - [ ] ํ…Œ๋งˆ ์„ ํƒ - [ ] ํ‘œ์‹œ ์˜ต์…˜ (์ฃผ๋ง ๊ฐ•์กฐ, ๊ณตํœด์ผ ๋“ฑ) ### โœ… Step 5: ์Šคํƒ€์ผ๋ง - [ ] ๋‹ฌ๋ ฅ ๊ทธ๋ฆฌ๋“œ ๋ ˆ์ด์•„์›ƒ - [ ] ๋‚ ์งœ ์…€ ๋””์ž์ธ - [ ] ์˜ค๋Š˜ ๋‚ ์งœ ํ•˜์ด๋ผ์ดํŠธ - [ ] ์ฃผ๋ง/ํ‰์ผ ๊ตฌ๋ถ„ - [ ] ๋ฐ˜์‘ํ˜• ๋””์ž์ธ (ํฌ๊ธฐ๋ณ„ ์ตœ์ ํ™”) ### โœ… Step 6: ํ†ตํ•ฉ - [ ] `DashboardSidebar`์— ๋‹ฌ๋ ฅ ์œ„์ ฏ ์ถ”๊ฐ€ - [ ] `CanvasElement`์—์„œ ๋‹ฌ๋ ฅ ์œ„์ ฏ ๋ Œ๋”๋ง - [ ] `DashboardDesigner`์— ๊ธฐ๋ณธ๊ฐ’ ์„ค์ • ### โœ… Step 7: ๊ณตํœด์ผ ๋ฐ์ดํ„ฐ - [ ] ํ•œ๊ตญ ๊ณตํœด์ผ ๋ฐ์ดํ„ฐ ์ •์˜ - [ ] ๊ณตํœด์ผ ํ‘œ์‹œ ๊ธฐ๋Šฅ - [ ] ๊ณตํœด์ผ ์ด๋ฆ„ ํˆดํŒ ### โœ… Step 8: ํ…Œ์ŠคํŠธ ๋ฐ ์ตœ์ ํ™” - [ ] ๋‹ค์–‘ํ•œ ํฌ๊ธฐ์—์„œ ํ…Œ์ŠคํŠธ - [ ] ๋‚ ์งœ ๊ณ„์‚ฐ ๋กœ์ง ๊ฒ€์ฆ - [ ] ์„ฑ๋Šฅ ์ตœ์ ํ™” - [ ] ์ ‘๊ทผ์„ฑ ๊ฐœ์„  ## ๊ธฐ์ˆ  ์Šคํƒ ### UI ์ปดํฌ๋„ŒํŠธ - **shadcn/ui**: Button, Select, Switch, Popover, Card - **lucide-react**: Settings, ChevronLeft, ChevronRight, Calendar ### ๋‚ ์งœ ์ฒ˜๋ฆฌ - **JavaScript Date API**: ๊ธฐ๋ณธ ๋‚ ์งœ ๊ณ„์‚ฐ - **Intl.DateTimeFormat**: ๋‚ ์งœ ํ˜•์‹ํ™” - ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์—†์ด ์ˆœ์ˆ˜ ๊ตฌํ˜„ ### ์Šคํƒ€์ผ๋ง - **Tailwind CSS**: ๋ฐ˜์‘ํ˜• ๊ทธ๋ฆฌ๋“œ ๋ ˆ์ด์•„์›ƒ - **CSS Grid**: ๋‹ฌ๋ ฅ ๋ ˆ์ด์•„์›ƒ ## ์ปดํฌ๋„ŒํŠธ ๊ตฌ์กฐ ``` widgets/ โ”œโ”€โ”€ CalendarWidget.tsx # ๋ฉ”์ธ ์œ„์ ฏ (์„ค์ • ๋ฒ„ํŠผ ํฌํ•จ) โ”œโ”€โ”€ CalendarSettings.tsx # ์„ค์ • UI (Popover ๋‚ด๋ถ€) โ”œโ”€โ”€ MonthView.tsx # ์›”๊ฐ„ ๋ทฐ โ”œโ”€โ”€ WeekView.tsx # ์ฃผ๊ฐ„ ๋ทฐ (์„ ํƒ) โ”œโ”€โ”€ DayView.tsx # ์ผ๊ฐ„ ๋ทฐ (์„ ํƒ) โ””โ”€โ”€ calendarUtils.ts # ๋‚ ์งœ ๊ณ„์‚ฐ ์œ ํ‹ธ๋ฆฌํ‹ฐ ``` ## ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ ```typescript interface CalendarConfig { view: "month" | "week" | "day"; // ๋ทฐ ํƒ€์ž… startWeekOn: "monday" | "sunday"; // ์ฃผ ์‹œ์ž‘ ์š”์ผ highlightWeekends: boolean; // ์ฃผ๋ง ๊ฐ•์กฐ highlightToday: boolean; // ์˜ค๋Š˜ ๊ฐ•์กฐ showHolidays: boolean; // ๊ณตํœด์ผ ํ‘œ์‹œ theme: "light" | "dark" | "custom"; // ํ…Œ๋งˆ customColor?: string; // ์‚ฌ์šฉ์ž ์ง€์ • ์ƒ‰์ƒ showWeekNumbers?: boolean; // ์ฃผ์ฐจ ํ‘œ์‹œ (์„ ํƒ) } ``` ## UI/UX ๊ณ ๋ ค์‚ฌํ•ญ ### ๋ฐ˜์‘ํ˜• ๋””์ž์ธ - **2x2**: ๋ฏธ๋‹ˆ ๋‹ฌ๋ ฅ (์›”๊ฐ„ ๋ทฐ๋งŒ, ๋‚ ์งœ๋งŒ ํ‘œ์‹œ) - **3x3**: ๊ธฐ๋ณธ ๋‹ฌ๋ ฅ (์›”๊ฐ„ ๋ทฐ, ์š”์ผ ํ—ค๋” ํฌํ•จ) - **4x4 ์ด์ƒ**: ํ’€ ๋‹ฌ๋ ฅ (๋ชจ๋“  ๊ธฐ๋Šฅ, ์ผ์ • ํ‘œ์‹œ ๊ฐ€๋Šฅ) ### ์ธํ„ฐ๋ž™์…˜ - ๋‚ ์งœ ํด๋ฆญ ์‹œ ํ•ด๋‹น ๋‚ ์งœ ์ •๋ณด ํ‘œ์‹œ (์„ ํƒ) - ๋“œ๋ž˜๊ทธ๋กœ ์›” ๋ณ€๊ฒฝ (์„ ํƒ) - ํ‚ค๋ณด๋“œ ๋„ค๋น„๊ฒŒ์ด์…˜ ์ง€์› ### ์ ‘๊ทผ์„ฑ - ๋‚ ์งœ ์…€์— ์ ์ ˆํ•œ aria-label - ํ‚ค๋ณด๋“œ ๋„ค๋น„๊ฒŒ์ด์…˜ ์ง€์› - ์Šคํฌ๋ฆฐ ๋ฆฌ๋” ํ˜ธํ™˜ ## ๊ณตํœด์ผ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ ```typescript interface Holiday { date: string; // 'MM-DD' ํ˜•์‹ name: string; // ๊ณตํœด์ผ ์ด๋ฆ„ isRecurring: boolean; // ๋งค๋…„ ๋ฐ˜๋ณต ์—ฌ๋ถ€ } // 2025๋…„ ํ•œ๊ตญ ๊ณตํœด์ผ ์˜ˆ์‹œ const KOREAN_HOLIDAYS: Holiday[] = [ { date: "01-01", name: "์‹ ์ •", isRecurring: true }, { date: "01-28", name: "์„ค๋‚  ์—ฐํœด", isRecurring: false }, { date: "01-29", name: "์„ค๋‚ ", isRecurring: false }, { date: "01-30", name: "์„ค๋‚  ์—ฐํœด", isRecurring: false }, { date: "03-01", name: "์‚ผ์ผ์ ˆ", isRecurring: true }, { date: "05-05", name: "์–ด๋ฆฐ์ด๋‚ ", isRecurring: true }, { date: "06-06", name: "ํ˜„์ถฉ์ผ", isRecurring: true }, { date: "08-15", name: "๊ด‘๋ณต์ ˆ", isRecurring: true }, { date: "10-03", name: "๊ฐœ์ฒœ์ ˆ", isRecurring: true }, { date: "10-09", name: "ํ•œ๊ธ€๋‚ ", isRecurring: true }, { date: "12-25", name: "ํฌ๋ฆฌ์Šค๋งˆ์Šค", isRecurring: true }, ]; ``` ## ํ–ฅํ›„ ํ™•์žฅ ๊ธฐ๋Šฅ ### Phase 2 (์„ ํƒ) - [ ] ์ผ์ • ์ถ”๊ฐ€/์ˆ˜์ •/์‚ญ์ œ - [ ] ๋ฐ˜๋ณต ์ผ์ • ์„ค์ • - [ ] ์นดํ…Œ๊ณ ๋ฆฌ๋ณ„ ์ƒ‰์ƒ ๊ตฌ๋ถ„ - [ ] ๋‹ค๋ฅธ ๋‹ฌ๋ ฅ ์„œ๋น„์Šค ์—ฐ๋™ (Google Calendar, Outlook ๋“ฑ) - [ ] ์ผ์ • ์•Œ๋ฆผ ๊ธฐ๋Šฅ - [ ] ๋“œ๋ž˜๊ทธ ์•ค ๋“œ๋กญ์œผ๋กœ ์ผ์ • ์ด๋™ ### Phase 3 (์„ ํƒ) - [ ] ์—ฌ๋Ÿฌ ๋‹ฌ๋ ฅ ๋ ˆ์ด์–ด ์ง€์› - [ ] ์ผ์ • ๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ - [ ] ์›”๋ณ„ ํ†ต๊ณ„ (์ผ์ • ๊ฐœ์ˆ˜ ๋“ฑ) - [ ] CSV/iCal ๋‚ด๋ณด๋‚ด๊ธฐ ## ์ฐธ๊ณ ์‚ฌํ•ญ ### ์žฅ์  - ์ˆœ์ˆ˜ JavaScript๋กœ ๊ตฌํ˜„ (์™ธ๋ถ€ ์˜์กด์„ฑ ์ตœ์†Œํ™”) - shadcn/ui ์ปดํฌ๋„ŒํŠธ ํ™œ์šฉ์œผ๋กœ ์ผ๊ด€๋œ ๋””์ž์ธ - ์‹œ๊ณ„ ์œ„์ ฏ๊ณผ ๋™์ผํ•œ ํŒจํ„ด (๋‚ด์žฅ ์„ค์ • UI) ### ์ฃผ์˜์‚ฌํ•ญ - ๋‚ ์งœ ๊ณ„์‚ฐ ๋กœ์ง ์ •ํ™•์„ฑ ๊ฒ€์ฆ ํ•„์š” - ์œค๋…„ ์ฒ˜๋ฆฌ - ํƒ€์ž„์กด ๊ณ ๋ ค (ํ•„์š”์‹œ) - ๋‹ค์–‘ํ•œ ํฌ๊ธฐ์—์„œ์˜ ๊ฐ€๋…์„ฑ ## ์™„๋ฃŒ ๊ธฐ์ค€ - [x] ์›”๊ฐ„ ๋ทฐ ๋‹ฌ๋ ฅ์ด ์ •ํ™•ํ•˜๊ฒŒ ํ‘œ์‹œ๋จ - [x] ์ด์ „/๋‹ค์Œ ์›” ๋„ค๋น„๊ฒŒ์ด์…˜์ด ์ž‘๋™ํ•จ - [x] ์˜ค๋Š˜ ๋‚ ์งœ๊ฐ€ ํ•˜์ด๋ผ์ดํŠธ๋จ - [x] ์ฃผ๋ง์ด ๋‹ค๋ฅธ ์ƒ‰์ƒ์œผ๋กœ ํ‘œ์‹œ๋จ - [x] ๊ณตํœด์ผ์ด ํ‘œ์‹œ๋˜๊ณ  ์ด๋ฆ„์ด ๋ณด์ž„ - [x] ์„ค์ • UI์—์„œ ๋ชจ๋“  ์˜ต์…˜์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Œ - [x] ํ…Œ๋งˆ ๋ณ€๊ฒฝ์ด ์ฆ‰์‹œ ๋ฐ˜์˜๋จ - [x] 2x2 ํฌ๊ธฐ์—์„œ๋„ ๊น”๋”ํ•˜๊ฒŒ ํ‘œ์‹œ๋จ - [x] 4x4 ํฌ๊ธฐ์—์„œ ๋ชจ๋“  ๊ธฐ๋Šฅ์ด ์ •์ƒ ์ž‘๋™ํ•จ --- ## ๊ตฌํ˜„ ์‹œ์ž‘ ์ด์ œ ๋‹จ๊ณ„๋ณ„๋กœ ๊ตฌํ˜„์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค!