FullCalendar의 리소스 타임라인과 리소스 열은 Premium 기능이라, 상용 앱에서 쓰려면 유료 라이선스 키가 필요합니다. 라이선스 페이지에는 무료로 쓸 수 있는 경우로 앱 전체가 AGPL인 경우와 등록된 비영리 단체인 경우가 나와 있습니다. Needless UI 스케줄러는 둘 다 MIT 라이선스로 제공하며, 반복 일정과 iCalendar 파일도 지원합니다. 이 가이드에서는 Angular 앱을 FullCalendar에서 Needless UI로 옮기면서, 그대로 옮겨지는 것과 그렇지 않은 것, 변환해야 할 데이터를 살펴봅니다.
FullCalendar 7의 이름을 쓰고, 버전 6의 이름이 다르면 대괄호 안에 함께 적습니다. FullCalendar의 Angular 커넥터는 Angular 16부터 22까지 지원하고, Needless UI는 Angular 22가 필요합니다.
기능 비교
| 기능 | FullCalendar | Needless UI |
|---|---|---|
| 리소스 타임라인: 회의실이나 사람마다 한 행 | Premium | 지원: 하루, 한 주, 한 달 |
| 일 보기와 주 보기에서 리소스를 열로 표시 | Premium | 지원 |
| 월, 주, 일 보기 | 무료 | 지원 |
| 드래그로 이동과 길이 조절 | 무료, 다른 리소스로 옮기기는 Premium | 지원, 다른 리소스로도 이동 가능. 길이 조절은 끝에서만 되고 시작에서는 안 됨. |
| 시간을 선택해 일정 만들기 | 무료 | 지원: 포인터, 길게 누르기, 키보드로 가능 |
| 겹침 금지 같은 규칙 | 무료: overlap, constraint 옵션 | 지원: 모든 변경 전에 묻는 allow 함수 하나 |
| 키보드로 일정 이동과 길이 조절 | 접근성 문서에 언급 없음(ARIA 레이블과 Tab 포커스만 다룸) | 지원, 스크린 리더로 안내됨 |
| 반복 일정 | 무료, rrule 플러그인과 라이브러리 사용 | 기본 내장: RFC 5545 규칙(EXRULE, RDATE, 시간 단위 규칙은 제외) |
| iCalendar(.ics) | 무료: 피드 읽기 | .ics 파일 읽기와 쓰기 |
| 목록 보기와 연간 보기 | 무료 | 앞으로 며칠간의 일정 목록, 연간 보기는 없음 |
| 시간대 | 무료: 로컬, UTC, 이름 있는 시간대 | 미지원: 받은 시각을 그대로 표시 |
| 그룹화, 중첩, 여러 열의 리소스 | Premium | 미지원: 템플릿으로 그리는 열 하나 |
| 외부 드래그 앤 드롭, 배경 이벤트 | 무료 | 미지원 |
| 인쇄, 가상 렌더링 | Premium | 미지원 |
| 프레임워크 | Angular 16~22, React, Vue, 순수 JavaScript 등 | Angular 22 및 React 19 |
옵션 대응
| FullCalendar | Needless UI 스케줄러 |
|---|---|
<full-calendar [options]>, plugins, schedulerLicenseKey | <nui-scheduler>, 옵션마다 입력이 있고 플러그인도 키도 필요 없음 |
initialView: 'resourceTimelineDay' | view="timeline", 한 주나 한 달은 timelineSpan으로 지정 |
initialView: 'timeGridWeek' | view="week", [(view)]는 양방향 바인딩 |
resources, events | [resources], [events] |
resourceId, extendedProps | resource, data |
editable, selectable | editable, selectable |
select | (slotSelect): { start, end, allDay, resource } |
eventDrop, eventResize | (eventChange): events를 갱신하기 전에는 아무것도 움직이지 않음 |
eventClick | (eventClick) |
eventOverlap, selectOverlap, eventAllow | [allow]: 이동, 길이 조절, 선택을 판단하는 함수 하나 |
slotDuration, snapDuration | slotMinutes, snapMinutes, 분 단위 |
slotMinTime, slotMaxTime, scrollTime | dayStart, dayEnd, scrollHour, 시 단위 |
businessHours | [businessHours], 요일은 1(월요일)부터 7까지 |
datesSet | (rangeChange) |
eventContent, resourceCellContent [resourceLabelContent] | nuiSchedulerEvent와 nuiSchedulerResource 템플릿 |
locale, firstDay | locale(모든 BCP 47 태그), 1부터 7까지의 firstDay, 표시 문구를 정하는 labels |
두 라이브러리로 만드는 회의실 예약 타임라인
회의실은 리소스이고 예약은 일정입니다. 회의실 행을 가로질러 드래그하면 예약하고 예약을 드래그하면 옮기며, 한 회의실에는 한 번에 예약 하나만 들어갑니다. FullCalendar 7과 Premium 리소스 타임라인으로는 다음과 같습니다.
Needless UI 스케줄러로는 다음과 같습니다.
두 가지가 다르게 동작합니다. FullCalendar는 예약을 직접 옮기고 앱이 그 변경을 따라 복사하지만, Needless UI 스케줄러는 변경을 알려 주기만 하고 events를 갱신해야 변경이 남으므로, 데이터의 출처가 늘 하나로 유지됩니다. 또 allow는 평범한 코드로, 포인터든 키보드든 모든 변경 전에 호출되므로 규칙을 직접 테스트할 수 있습니다. 회의실 예약 캘린더 가이드에서 이 앱을 단계별로 만들어 봅니다.
데이터 변환
| FullCalendar | Needless UI |
|---|---|
종일 일정의 end는 일정 다음 날 | 종일 일정의 end는 마지막 날이므로 하루를 빼야 함 |
시각 끝에 Z나 +02:00 같은 오프셋이 붙을 수 있음 | 오프셋 없는 시각, 예: 2026-11-02T09:30 |
요일은 0(일요일)부터 6까지, businessHours와 firstDay에서 사용 | 요일은 1(월요일)부터 7(일요일)까지 |
기간은 '00:30' 같은 문자열 | 숫자: 분 또는 시간 |
| 리소스는 id, 그다음 제목 순으로 정렬 | 리소스는 배열 순서대로 |
객체로 된 rrule과 exrule | FREQ=WEEKLY;BYDAY=MO,FR 같은 RFC 5545 문자열과 exdate |
America/New_York 같은 시간대 | 먼저 시각을 변환해야 함. nuiSchedulerFromIcs(text, { timeZone })는 .ics 파일을 읽으면서 변환함. |
빠진 기능이 필요하다면
앱이 시간대, 그룹화된 리소스, 외부 드래그 앤 드롭, 인쇄에 의존한다면 아직은 스케줄러가 FullCalendar를 대신할 수 없습니다. 필요한 기능은 이슈로 등록해 주세요. 그 밖의 것은 스케줄러 페이지에서 모든 입력, 출력, 예제를 확인하세요.