diff --git a/articles/2026-02-11.md b/articles/2026-02-11.md new file mode 100644 index 0000000..b645c09 --- /dev/null +++ b/articles/2026-02-11.md @@ -0,0 +1,83 @@ +[2026년 02월 11일] 일정 CRUD 연동 및 대규모 리팩토링을 통한 시스템 안정화 + +오늘 팀 "Calio"는 캘린더 서비스의 핵심인 일정 CRUD(생성, 조회, 수정, 삭제) 기능을 서버 스펙에 맞춰 최종 연동하고, 복잡도가 높았던 기존 폼 로직을 대대적으로 리팩토링했습니다. 프런트엔드와 백엔드 간의 데이터 규격을 동기화함과 동시에, 코드의 재사용성과 유지보수성을 높이기 위해 컴포넌트 및 훅의 구조를 세밀하게 분리하는 작업에 집중했습니다. + +--- + +## 🌿 Branch: feature/#25-일정-crud-연결 + +### [Yeonjin Kim] 기술 분석 및 작업 상세 + +Yeonjin Kim 개발자는 서버 API 명세 변경에 따른 타입 대응과 더불어, 비대해진 `AddScheduleForm` 컴포넌트를 기능별로 모듈화하는 고도화 작업을 수행했습니다. + +#### 1. 서버 스펙 동기화 및 타입 정제 +기존 `allDay`로 혼용되던 필드명을 서버 규격인 `isAllDay`로 통일하고, 캘린더 이벤트 타입을 `CalendarEvent`에서 `Event`로 점진적으로 교체하여 도메인 모델의 일관성을 확보했습니다. + +```typescript +// src/features/Calendar/components/CustomEvent/CustomMonthEvent.tsx 변경 사항 +const formatTimeRange = (event: CalendarEvent) => { +- if (event.allDay) { ++ if (event.isAllDay) { + return '종일' + } +``` + +#### 2. 복잡한 폼 로직의 모듈화 (Hooks & Components 분리) +기존에 하나의 파일에 몰려있던 일정 추가/수정 로직을 `useScheduleSubmitFlow`, `useSchedulePatch`, `useScheduleFooter` 등의 커스텀 훅으로 분리했습니다. 이는 단일 책임 원칙(SRP)을 준수하며, 향후 일정 관리 로직의 확장성을 고려한 설계입니다. + +* **훅 분리**: `useSchedulePatch`를 통해 수정 페이로드 생성을 전담하게 하고, `useScheduleSubmitFlow`로 제출 프로세스를 관리합니다. +* **컴포넌트 파편화**: `AddScheduleFormContent`, `AddScheduleFormFields`, `AddScheduleFormContext` 등으로 나누어 UI 렌더링 최적화와 데이터 흐름을 명확히 했습니다. + +#### 3. API Mutation 및 삭제/수정 컨펌 로직 구현 +`useCalendarMutation` 훅을 신설하여 `post`, `patch`, `delete` 요청을 중앙 집중화했으며, 일정 삭제 시 반복 일정 처리(이 일정만, 향후 일정 모두 등)를 위한 컨펌 모달 로직을 강화했습니다. + +```typescript +// src/shared/hooks/query/useCalendarMutation.ts +export function useCalendarMutation() { + function usePostEvent() { + return useCustomMutation(postEvents) + } + function usePatchEvent() { + return useCustomMutation( + ({ eventId, eventData }: { eventId: number; eventData: Parameters[1] }) => + patchEvent(eventId, eventData), + ) + } + // ... delete logic +} +``` + +#### 4. 유효성 검사 스키마 고도화 +`yup`을 활용한 `addScheduleSchema`에서 `isAllday` 여부에 따라 시작/종료 시간의 필수 입력 조건을 동적으로 제어하도록 수정했습니다. + +```typescript +// src/shared/schemas/schedule.ts +const eventStartTime = yup + .string() + .when('isAllday', (isAllday, schema) => + isAllday + ? schema.notRequired().nullable() + : schema.required('시작 시간은 필수 입력 사항입니다.'), + ) +``` + +#### 5. 반복 일정(Recurrence) 로직 정교화 +반복 일정 설정 시 `dayOfWeekInMonth`를 배열로 처리할 수 있도록 타입을 확장하고, 반복 종료 조건에 '종료 없음(never)' 옵션을 추가하여 사용자 경험을 개선했습니다. + +```typescript +// src/shared/types/event/recurrence/recurrence.ts +export interface recurrenceGroup { + // ... + daysOfWeek?: Array + dayOfWeekInMonth?: Array // 단일 값에서 배열로 확장 +} +``` + +#### 6. UI/UX 디테일 수정 +* 모바일 환경에서의 캘린더 최소 높이 제한(`min-height`)을 제거하여 뷰포트 대응력을 높였습니다. +* `TerminationPanel`에서 종료 날짜 선택 시, 해당 타입이 활성화되지 않았을 경우 입력을 비활성화(`disabled`) 처리하여 오입력을 방지했습니다. + +--- + +**시니어 개발자 총평:** +오늘 작업은 단순히 기능을 연결하는 것을 넘어, 서비스의 근간이 되는 데이터 구조를 견고히 다지는 중요한 과정이었습니다. 특히 `AddSchedule` 관련 로직의 대규모 리팩토링은 코드 리뷰 시 가독성을 크게 향상시켰으며, 서버와의 통신 규약을 엄격히 맞춤으로써 런타임 에러 가능성을 최소화했습니다. 내일부터는 연동된 CRUD 기능을 바탕으로 실제 사용자 시나리오 기반의 QA를 진행할 예정입니다. \ No newline at end of file