[Feature] 친구 API 연결 및 리팩토링#99
Merged
Merged
Conversation
2 tasks
There was a problem hiding this comment.
Pull request overview
캘린더 공유 일정(친구 검색/초대)과 반복 일정 scope 처리, 그리고 CustomCalendar 비대화 로직을 훅/유틸로 분리하면서 읽기 전용(비소유자) 편집 차단까지 포함한 대규모 리팩토링 PR입니다.
Changes:
- 친구 검색 API 연동 및 일정 생성/수정 payload에
friendIds반영 - 반복 일정/할 일 scope 상수화 및 patch/delete 흐름 정리
CustomCalendar책임을 컨트롤러 훅/드래그&드롭/뷰 생성 등으로 분리 + 읽기 전용 UX 보강
한 줄 요약
구조 분리 방향은 좋지만, TS 경로 alias 설정(tsconfig.app.json)과 이벤트 recurrence scope 타입, unsaved-change 감지/키보드 접근성에서 실제 동작을 깨는 이슈가 확인됩니다.
발견된 위반 항목
tsconfig.app.json:paths유지한 채baseUrl제거 →@/alias 해석 실패 가능(빌드/타입체크 크리티컬)src/shared/constants/recurrenceScope.ts: 이벤트 scope에 todo용 값 혼입 → API 타입이 유효하지 않은 scope를 허용src/shared/ui/Modals/ScheduleEditor/ScheduleEditorContent.tsx:hasUserEdited기반 dirty 판정으로 변경했지만 일부 변경(예: 색상 변경)이 누락되어 무경고 종료로 데이터 유실 가능src/shared/ui/scheduleTodo/TitleSuggestionInput/TitleSuggestionInput.tsx: readOnly에서 모든 keydownpreventDefault→ Tab 포커스 이동 차단(접근성/포커스 트랩)src/shared/hooks/form/useEditorFormLifecycle.ts:registeredFields배열 레퍼런스가 매 렌더마다 바뀌면register반복 실행(불필요한 작업)
추천 구조
현재 분리된 방향을 유지하되, “공용 상수/타입의 단일 출처”와 “readOnly/dirty 감지의 단일 정책”을 명확히 하는 쪽이 안전합니다.
src/
shared/
constants/
recurrenceScope.ts # 이벤트/투두 scope를 완전히 분리(이벤트는 series scope만)
api/
calendar/api.ts # patch/delete scope 타입을 series scope로 제한
hooks/
form/
useEditorFormLifecycle.ts # 등록 필드 안정화(배열 memo or 내부 1회 등록)
ui/
Modals/ScheduleEditor/
ScheduleEditorContent.tsx # dirty 판정(색상 포함) 누락 없는 단일 경로로 수렴
scheduleTodo/TitleSuggestionInput/
TitleSuggestionInput.tsx # readOnly 키보드 접근성 보장(Tab 등)
features/
Calendar/
hooks/
utils/
최소 리팩토링 단계
tsconfig.app.json에서baseUrl/paths조합을 정상화해@/alias가 확실히 동작하도록 수정RECURRENCE_EVENT_SCOPE에서 todo용 값을 제거하고, 이벤트 patch/delete는RecurrenceEventSeriesScope만 받도록 타입/시그니처 정리ScheduleEditorContent의hasUserEdited정책을 보완(색상 변경 포함)하거나formState.isDirty와 결합해 누락 제거TitleSuggestionInput의 readOnly keydown 처리에서 Tab 등 내비게이션 키는 막지 않도록 조정useEditorFormLifecycle의 field 등록이 매 렌더 반복되지 않도록 호출부/훅 중 한쪽에서 안정화
Reviewed changes
Copilot reviewed 83 out of 83 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| tsconfig.app.json | TS alias 경로 설정 변경 |
| src/shared/utils/itemEditorDraft.ts | 시간 포맷 유틸 분리 사용 |
| src/shared/utils/eventParticipants.ts | 공유 일정 참가자 friendId 유틸 추가 |
| src/shared/utils/editorDateTime.ts | 에디터 날짜/시간 유틸 신설 |
| src/shared/ui/scheduleTodo/TitleSuggestionInput/TitleSuggestionInput.tsx | readOnly/attempt 콜백 추가 |
| src/shared/ui/scheduleTodo/SelectColor/SelectColor.tsx | readOnly 동작 차단 추가 |
| src/shared/ui/scheduleTodo/SearchFriend/SearchFriend.tsx | 친구 검색 API 연동 및 throttling 적용 |
| src/shared/ui/scheduleTodo/SearchFriend/SearchFriend.style.ts | 검색 결과 스타일(선택 상태) 보강 |
| src/shared/ui/Modals/TodoEditor/TodoRepeatSection.tsx | 반복 상세 패널 토글 로직 보정 |
| src/shared/ui/Modals/TodoEditor/TodoEditorContent.tsx | buildDateTime 유틸로 정리 |
| src/shared/ui/Modals/ScheduleEditor/ShareSchedulePanel.tsx | friendIds 폼 연동 + readOnly 표시/차단 |
| src/shared/ui/Modals/ScheduleEditor/ScheduleTitleField.tsx | 제목 히스토리 조회 throttling/ readOnly 제어 |
| src/shared/ui/Modals/ScheduleEditor/ScheduleRepeatSection.tsx | 반복 섹션 readOnly 차단/사용자 편집 트래킹 |
| src/shared/ui/Modals/ScheduleEditor/ScheduleEditorFields.tsx | readOnly/participants props 전달 확장 |
| src/shared/ui/Modals/ScheduleEditor/ScheduleEditorContent.tsx | 비소유자 편집 차단 + dirty 추적 변경 |
| src/shared/ui/Modals/ScheduleEditor/ScheduleDetailsSection.tsx | 메모/장소 readOnly 차단 및 onUserEdit 연동 |
| src/shared/ui/Modals/ScheduleEditor/ScheduleDateTimeSection.tsx | 날짜/시간 readOnly 차단 및 onUserEdit 연동 |
| src/shared/ui/Modals/ScheduleEditor/index.style.ts | 공유 친구 UI padding 조정 |
| src/shared/ui/Modals/ItemEditorModal/index.tsx | 비소유자 일정 편집 차단(탭/액션 숨김) |
| src/shared/ui/Modals/ItemEditorModal/EditorModalLayout.tsx | hideActions 옵션 추가 |
| src/shared/ui/Modals/DeleteConfirmModal/DeleteConfirmModal.tsx | recurrence scope 상수/타입 적용 |
| src/shared/ui/common/Checkbox/Checkbox.tsx | readOnly 차단 동작 추가 |
| src/shared/ui/calendar/CustomTimePicker/CustomTimePicker.tsx | readOnly 차단 동작 추가 |
| src/shared/types/scheduleTodo/titleSuggestionInput.ts | TitleSuggestionInput props 확장 |
| src/shared/types/recurrence/recurrence.ts | recurrence scope 타입 재export로 정리 |
| src/shared/types/modal/scheduleEditor.ts | schedule editor props 확장(invitedParticipants 등) |
| src/shared/types/friend/types.ts | 친구 검색 응답 타입 추가 |
| src/shared/types/calendar/types.ts | 공유 일정 필드(friendIds/participants/isOwner) 확장 |
| src/shared/schemas/schedule.ts | friendIds 스키마 추가 |
| src/shared/hooks/repeat/useRepeatConfigController.ts | 반복 컨트롤러 콜백 기반으로 리팩토링 |
| src/shared/hooks/query/useFriendQueries.ts | 친구 검색 query 훅 추가 |
| src/shared/hooks/query/useCalendarMutation.ts | 이벤트 delete scope 타입 정리 |
| src/shared/hooks/form/useTodoFormFields.ts | 폼 라이프사이클 공통 훅 적용 |
| src/shared/hooks/form/useTodoEditorForm.ts | 반복 컨트롤러 공통 훅 적용 + scope 상수 사용 |
| src/shared/hooks/form/useScheduleFormFields.ts | friendIds 기본값/시간 정규화 + 라이프사이클 공통 훅 적용 |
| src/shared/hooks/form/useScheduleEditorForm.ts | 반복 컨트롤러 콜백 기반 적용 |
| src/shared/hooks/form/useEditorFormLifecycle.ts | 폼 등록/리셋/드래프트 공통 훅 신설 |
| src/shared/hooks/form/index.ts | useEditorFormLifecycle export 추가 |
| src/shared/hooks/common/useUnsavedCloseGuard.ts | 라우팅 이동(a 클릭) unsaved 가드 추가 |
| src/shared/hooks/addTodo/useTodoSubmitFlow.ts | todo scope 상수 사용 |
| src/shared/hooks/addTodo/useTodoFooter.tsx | todo scope 상수 사용 |
| src/shared/hooks/addSchedule/useScheduleSubmitFlow.ts | 이벤트 scope 상수 사용 + readOnly 차단 |
| src/shared/hooks/addSchedule/useSchedulePatchController.ts | friendIds 포함 patch/create 반영 |
| src/shared/hooks/addSchedule/useSchedulePatch.ts | friendIds diff 반영 + scope 상수 적용 |
| src/shared/hooks/addSchedule/useScheduleFooter.tsx | readOnly 차단 및 ref 기반 핸들러 정리 |
| src/shared/constants/recurrenceScope.ts | recurrence scope 상수/타입 신설 |
| src/shared/api/queryKeys/index.ts | friend queryKeys export 추가 |
| src/shared/api/friend/queryKeys.ts | friend 검색 queryKeys 추가 |
| src/shared/api/friend/api.ts | 친구 검색 API 추가 |
| src/shared/api/calendar/api.ts | event friendIds, scope 타입 반영 |
| src/pages/main/CalendarPage/CalendarPage.tsx | settings 기반 초기 view 주입 |
| src/features/Calendar/utils/weekViewLayout.ts | 주간 뷰 레이아웃 유틸 분리 |
| src/features/Calendar/utils/helpers/calendarRecurrenceScope.ts | recurrence scope 매핑 헬퍼 추가 |
| src/features/Calendar/utils/helpers/calendarPageHelpers.ts | 더미 이벤트 friendIds 기본값 추가 |
| src/features/Calendar/utils/helpers/calendarModalEvent.ts | 모달 대상 이벤트 선택 유틸 추가 |
| src/features/Calendar/hooks/useStoredCalendarView.ts | settings defaultView 매핑 + 초기값 처리 변경 |
| src/features/Calendar/hooks/useCustomCalendarMutations.ts | 캘린더 mutation 묶음 훅 추가 |
| src/features/Calendar/hooks/useCustomCalendarController.tsx | CustomCalendar 컨트롤러 훅으로 대규모 분리 |
| src/features/Calendar/hooks/useCalendarViewCreationHandlers.ts | 뷰별 생성/선택 핸들러 분리 |
| src/features/Calendar/hooks/useCalendarTodoTimingPatch.ts | todo 타이밍 patch 분리 |
| src/features/Calendar/hooks/useCalendarTodoActions.ts | todo 토글 액션 분리 |
| src/features/Calendar/hooks/useCalendarSelectionBridge.ts | 선택 훅과 모달 상태 브리지 추가 |
| src/features/Calendar/hooks/useCalendarRecurringDropConfirm.ts | 반복 드롭 confirm 분리 |
| src/features/Calendar/hooks/useCalendarPortals.ts | 포털 훅 제거 |
| src/features/Calendar/hooks/useCalendarKeyDelete.ts | todo 삭제 scope 타입 정리 |
| src/features/Calendar/hooks/useCalendarDragDrop.ts | 비소유자 편집 차단 + scope 상수 적용 |
| src/features/Calendar/hooks/useCalendarDeleteConfirm.ts | 삭제 confirm 상태/로직 분리 |
| src/features/Calendar/hooks/useCalendarDayViewTiming.ts | 일간 뷰 타이밍 patch 분리 + 비소유자 차단 |
| src/features/Calendar/hooks/useCalendarDateCellWrapper.tsx | 날짜 셀 wrapper 분리 |
| src/features/Calendar/hooks/useCalendarApiEvents.ts | eventParticipantInfo 기본값 반영 |
| src/features/Calendar/hooks/index.ts | 신규 훅 export 정리 |
| src/features/Calendar/domain/config.ts | defaultView/tooltipAccessor 설정 변경 |
| src/features/Calendar/components/CustomView/weekView.ts | 주간 뷰 텍스트 overflow 스타일 보강 |
| src/features/Calendar/components/CustomView/dayView/renderGeometry.ts | 일간 뷰 렌더 지오메트리 유틸 분리 |
| src/features/Calendar/components/CustomView/dayView/renderers.tsx | 지오메트리 계산 분리 적용 |
| src/features/Calendar/components/CustomView/dayView/dragMath.ts | 드래그 스냅/계산 분리 |
| src/features/Calendar/components/CustomView/dayView/dragHandlers.ts | 드래그 계산 분리 적용 |
| src/features/Calendar/components/CustomView/CustomWeekView.tsx | 주간 뷰 레이아웃 계산 유틸화 |
| src/features/Calendar/components/CustomEvent/CustomEvent.style.ts | 텍스트 overflow/레이아웃 보강 |
| src/features/Calendar/components/CustomCalendar/CustomCalendarDialogs.tsx | 상태 타입 분리 적용 |
| src/features/Calendar/components/CustomCalendar/CustomCalendar.types.ts | 캘린더 타입 정의 분리 |
| src/features/Calendar/components/CustomCalendar/CustomCalendar.tsx | 컨트롤러 훅 기반으로 대규모 단순화 |
| src/features/Calendar/components/CustomCalendar/CalendarModals.tsx | 라우트 기반 모달 렌더 조건 추가 |
Comments suppressed due to low confidence (1)
src/shared/ui/Modals/ScheduleEditor/ScheduleEditorContent.tsx:95
- UnsavedCloseGuard 판단을 formState.isDirty 대신 hasUserEdited로 대체했는데, 현재 markUserEdited가 컬러 변경(footer SelectColor) 등 일부 변경 경로에서는 호출되지 않아 변경 후에도 경고 없이 닫혀 데이터가 유실될 수 있습니다. 색상 변경/삭제 등 모든 사용자 변경 지점에서 markUserEdited를 호출하도록 연결하거나, isDirty와 조합해 누락이 없도록 해주세요.
yujin5959
approved these changes
May 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🔗 관련 이슈
🧩 작업 요약 (TL;DR)
🔄 변경 유형
해당되는 항목에 체크해주세요.
📌 주요 변경 사항
CustomCalendar에 몰려 있던 캘린더 컨트롤러, 드래그/드롭, 삭제 확인, 반복 일정 확인, 뷰 생성 로직을 전용 훅/유틸로 분리했습니다.🖼️ 스크린샷 / 영상 (선택)
[공유 일정 owner가 아닌 경우 - view 전용(일정 수정 불가)]

[공유 일정 owner인 경우]



🧠 리뷰 요청 포인트
🚧 미완 / 후속 작업
💬 기타 참고 사항
이번 PR은 캘린더 공유 일정 기능과 반복 일정(백엔드 변경) 수정 흐름을 중심으로 변경 범위가 큽니다.
기존 훅에 공유 일정 기능을 붙여보려했으나 훅이 너무 방대해지고 책임이 모호해져서
CustomCalendar의 책임이 커져 있던 부분을useCustomCalendarController,useCalendarDeleteConfirm,useCalendarRecurringDropConfirm,useCalendarTodoTimingPatch,useCalendarViewCreationHandlers등으로 분리했습니다.@copilot 이 PR을 아래 기준으로 검토해주세요:
.github/instructions/capstone.instructions.md 파일을 지침으로 삼으세요.
응답은 한국어로, 발견된 위반 항목과 추천 구조를 포함해주세요.
리뷰를 달아주세요.