Schedule
일정 관리를 위한 캘린더 컴포넌트
개요
Schedule은 FullCalendar를 기반으로 Day/Week/WorkWeek/Month/Agenda 뷰, 드래그 & 리사이즈, Collapse 래핑, 카테고리 색상 등을 지원하는 일정 관리 컴포넌트입니다.
주요 특징
- ✅ 다양한 뷰: Day, Week, WorkWeek, Month, Agenda(목록) 뷰 지원
- ✅ 드래그 & 리사이즈: 이벤트 드래그 이동 및 시간 조절
- ✅ Collapse 래핑: title prop으로 접기/펼치기 UI 제공
- ✅ 카테고리 색상: categoryColors로 이벤트 배경색 일괄 설정
- ✅ 읽기 전용: readOnly prop으로 편집 차단
- ✅ 네비게이션: 이전/다음/오늘 버튼, 날짜 선택기, 이동 범위 제한(minDate/maxDate)
- ✅ 요약 팝업: 일정 클릭 시 요약 + 편집/삭제 (showEventPopup)
- ✅ 셀 제스처 분기: 클릭/더블클릭/드래그를 각각 다른 통로로 통지
- ✅ 형식과 문구 분리:
locale은 날짜 형식,labels는 UI 문구
기본 사용
events를 전달하면 주간 뷰로 일정이 표시됩니다.
Preview
뷰 모드
views prop으로 표시할 뷰를 지정하고, currentView로 현재 뷰를 제어합니다.
뷰를 바꾸면 캘린더를 새로 만듭니다. 전환 직후 스크롤 위치는 초기화됩니다.
Preview
| 뷰 | 설명 |
|---|---|
day | 하루 일정 |
week | 주간 일정 |
workWeek | 업무주 (월~금) |
month | 월간 일정 |
agenda | 목록 형태 (agendaDays, 기본 7일) |
드래그 & 리사이즈
allowEventDrag로 일정 이동과 시간 조절을 엽니다.
구 prop
allowDragAndDrop·allowResizing은 아직 동작합니다. 다음 메이저에서 제거되니allowEventDrag로 옮겨 주세요. 둘 다 넘기면allowEventDrag가 우선합니다.
Preview
Collapse 래핑
title prop을 지정하면 Collapsible로 래핑됩니다.
Preview
카테고리 색상
categoryColors로 이벤트의 categoryField 값에 따라 배경색을 일괄 지정합니다.
Preview
요약 팝업
일정을 클릭하면 요약 팝업이 열립니다(기본 동작). onEventEdit·onEventDelete를 넘긴 경우에만 해당 버튼이 나타납니다. showEventPopup={false}로 끌 수 있습니다.
Preview
일정을 클릭하세요
빈 셀 제스처
빈 셀의 클릭·더블클릭·드래그는 각각 다른 통로로 올라옵니다. 세 콜백 모두 선택 사항이며, 넘기지 않으면 선택 표시만 되고 아무 동작도 하지 않습니다.
| 콜백 | 언제 | 받는 것 |
|---|---|---|
onCellClick | 한 번 클릭 | 한 칸 |
onCellDoubleClick | 두 번 클릭 | 한 칸 |
onCellSelect | 클릭·더블클릭·드래그 전부 | 실제 선택 구간 + gesture |
Preview
형식과 문구
세 축은 따로입니다. locale은 날짜·요일·시간 형식(Intl·date-fns), labels는 화면 문구, timezone은 일정이 그리드에 놓이는 시간대입니다. 기본 문구는 한국어이며, 영어가 필요하면 SCHEDULE_EN_LABELS를 넘깁니다.
Preview
일정 우클릭
onEventContextMenu로 일정 우클릭을 받습니다. 핸들러를 넘긴 경우에만 브라우저 기본 메뉴를 막습니다. 무엇을 할지는 앱이 정합니다 — 삭제 확인, 자체 컨텍스트 메뉴 등.
Preview
일정을 우클릭하세요
구 prop
onContextDelete는 아직 동작합니다. 다음 메이저에서 제거되니onEventContextMenu로 옮겨 주세요. 둘 다 넘기면onEventContextMenu만 불립니다.
API Reference
Props
| Prop | Type | Default | Description |
|---|---|---|---|
events | ScheduleEvent[] | [] | 일정 이벤트 데이터 |
currentView | ScheduleViewMode | "week" | 현재 보기 모드 |
onViewChange | (mode: ScheduleViewMode) => void | - | 보기 모드 변경 핸들러 |
views | ScheduleViewMode[] | ["day","week","month"] | 사용 가능한 뷰 목록 |
currentDate | Date | - | 현재 표시 날짜 (Controlled) |
onDateChange | (date: Date) => void | - | 날짜 변경 핸들러 |
onNavigate | (date: Date, action: "prev" | "next" | "today") => void | - | 네비게이션 콜백 (이전/다음/오늘) |
minDate | Date | - | 이동 가능한 가장 이른 날짜 |
maxDate | Date | - | 이동 가능한 가장 늦은 날짜 |
onEventClick | (event: ScheduleEvent) => void | - | 이벤트 클릭 핸들러 |
onEventDoubleClick | (event: ScheduleEvent) => void | - | 이벤트 더블클릭 핸들러 (상세 진입) |
onEventEdit | (event: ScheduleEvent) => void | - | 요약 팝업 편집 버튼 — 미지정 시 버튼 없음 |
onEventDelete | (event: ScheduleEvent) => void | - | 요약 팝업 삭제 버튼 — 미지정 시 버튼 없음 |
showEventPopup | boolean | true | 이벤트 클릭 시 요약 팝업 표시 여부 |
onEventContextMenu | (event: ScheduleEvent, nativeEvent: MouseEvent) => void | - | 일정 우클릭 핸들러 — 브라우저 기본 메뉴를 막는다 |
onCellClick | (data: ScheduleDateSelectData) => void | - | 빈 셀 단일 클릭 (한 칸) |
onCellDoubleClick | (data: ScheduleDateSelectData) => void | - | 빈 셀 더블클릭 (한 칸) |
onCellSelect | (data: ScheduleCellSelectData) => void | - | 빈 셀 선택 — 제스처 전부 + 실제 구간 |
onEventChange | (data: ScheduleEventChangeData) => void | - | 드래그/리사이즈 완료 핸들러 (바뀐 필드만) |
allowEventDrag | boolean | false | 일정 이동·크기조절 허용 |
allowDragAndDrop | boolean | - | @deprecated — allowEventDrag 사용 |
allowResizing | boolean | - | @deprecated — allowEventDrag 사용 |
onContextDelete | (event: ScheduleEvent) => void | - | @deprecated — onEventContextMenu 사용 |
readOnly | boolean | false | 읽기 전용 모드 |
dateFormat | string | "yyyy-MM-dd" | 네비게이션 날짜 표기 형식 (date-fns 패턴) |
timezone | string | 브라우저 타임존 | 그리드가 그려지는 시간대 (IANA) |
locale | string | "ko" | 날짜·요일·시간 형식 (문구는 labels) |
labels | ScheduleLabelOverrides | 한국어 기본값 | UI 문구 덮어쓰기 — 지정한 항목만 대체 |
agendaDays | number | 7 | 목록(agenda) 뷰가 한 번에 보여주는 일수 |
startDayOfWeek | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 뷰별 계산 | 주 시작 요일 — 미지정 시 workWeek은 월, 나머지는 일 |
weekStartTime | string | "00:00" | 시간 그리드 시작 시각 ("HH:mm") |
weekEndTime | string | "24:00" | 시간 그리드 종료 시각 ("HH:mm") |
categoryColors | ScheduleCategoryColor[] | [] | 카테고리별 색상 매핑 |
title | string | - | Collapse 헤더 제목 (지정 시 Collapsible 래핑) |
collapsed | boolean | false | 접힘 상태 (Controlled) |
onCollapseChange | (collapsed: boolean) => void | - | 접힘 상태 변경 핸들러 |
collapseDisabled | boolean | false | 접기 잠금 |
visible | boolean | true | 표시 여부 (false → 렌더 안 함) |
height | string | number | "650px" | 캘린더 높이 |
fullSize | boolean | false | 전체 화면 표시 (height 무시) |
loading | boolean | false | 로딩 상태 표시 |
className | string | - | 컨테이너 CSS 클래스 |
style | CSSProperties | - | 인라인 스타일 |
children | ReactNode | - | 툴바 등 추가 콘텐츠 (Collapse 헤더 영역) |
ScheduleViewMode
type ScheduleViewMode = "day" | "week" | "workWeek" | "month" | "agenda"ScheduleEvent
| Field | Type | Required | Description |
|---|---|---|---|
id | string | number | ✅ | 이벤트 고유 식별자 |
title | string | ✅ | 이벤트 제목 |
start | Date | string | ✅ | 시작 시간 |
end | Date | string | - | 종료 시간 |
isAllDay | boolean | - | 종일 이벤트 여부 |
category | string | - | 이벤트 카테고리 |
categoryField | string | - | categoryColors 매핑에 사용할 카테고리 값 |
color | string | - | 이벤트 텍스트 색상 |
backgroundColor | string | - | 이벤트 배경색 |
dragBackgroundColor | string | - | 드래그 사본 배경색 — 미지정 시 배경색에서 파생 |
borderColor | string | - | 이벤트 테두리 색상 |
isReadOnly | boolean | - | 개별 이벤트 읽기 전용 |
isPrivate | boolean | - | 비공개 이벤트 여부 |
body | string | - | 이벤트 본문 (메모) |
location | string | - | 이벤트 장소 |
calendarId | string | - | 캘린더 ID (그룹 구분) |
raw | Record<string, unknown> | - | 원본 데이터 (커스텀 필드) |
ScheduleCategoryColor
| Field | Type | Required | Description |
|---|---|---|---|
value | string | ✅ | 카테고리 필드값 |
color | string | ✅ | 배경색 (hex) |
dragColor | string | - | 드래그 사본 배경색 — 미지정 시 color |
ScheduleDateSelectData
| Field | Type | Description |
|---|---|---|
start | Date | 선택 시작 시간 |
end | Date | 선택 종료 시간 |
isAllDay | boolean | 종일 영역 여부 |
ScheduleCellSelectData
ScheduleDateSelectData에 제스처가 붙은 형태입니다.
| Field | Type | Description |
|---|---|---|
start | Date | 선택 시작 시간 |
end | Date | 선택 종료 시간 |
isAllDay | boolean | 종일 영역 여부 |
gesture | "click" | "doubleClick" | "drag" | 어떤 제스처였는지 |
ScheduleLabelOverrides
ScheduleLabels의 부분 집합입니다. 지정한 항목만 기본 한국어 문구를 대체합니다.
<Schedule labels={{ today: "Today", views: { month: "Month" } }} />| 대표 키 | 기본값 | 쓰이는 곳 |
|---|---|---|
today | "오늘" | 네비게이션 버튼 |
prev / next | "이전" / "다음" | 네비게이션 버튼 aria |
views | 일 · 주 · 일주일 · 달 · 의제 | 뷰 전환 토글 |
edit / delete / close | 편집 · 삭제 · 닫기 | 요약 팝업 |
moreEvents | +N more | 월 뷰 접힘 표시 |
미리 만들어 둔 묶음: SCHEDULE_KO_LABELS(기본), SCHEDULE_EN_LABELS.
ScheduleEventChangeData
| Field | Type | Description |
|---|---|---|
event | ScheduleEvent | 변경된 이벤트 객체 |
changes | { start?: Date; end?: Date } | 바뀐 필드만 들어온다 — 리사이즈는 end만 |
접근성
권장 사항
- ✅ Foundation FullCalendar 내부에서
role="grid"시맨틱 자동 적용 - ✅ 네비게이션 버튼에
aria-label제공 (이전, 다음, 오늘) - ✅ 이벤트 요소에 포커스 및 키보드 접근 가능
- ✅ 로딩 시
aria-busy="true"자동 적용 - ❌ 색상만으로 카테고리를 구분하지 말고 title/body에 카테고리 정보를 포함할 것을 권장
관련 컴포넌트
- Foundation FullCalendar: 기반 캘린더 프리미티브
- DateTimePicker: 날짜/시간 입력 컴포넌트