react-big-calendar 커스터마이징

Moon Works·2022년 12월 19일
2

next.js 로 사이드 프로젝트 시작 하면서 달력 자체를 만드는 것보다는 달력을 활용한 것을 만들어보고 싶었다. 그래서 기존 캘린더 라이브러리를 검토하게 되었다.

검토 대상 및 선정 기준

마지막까지 고민했던 대상은 nhn 에서 만든 tui calendarreact-big-calendar이다.

초기 선택의 기준은 모바일 대응이 얼마나 잘되고 있는지 여부였다.

tui-calendar 는 react-big-calendar 에 비해 더 높은 star 수를 확보했지만 mobile 모드로 전환 시 예제가 스크린샷으로만 제공되는 아쉬움이 있었다. 반면 react-big-calendar 는 resposive 한 대응으로 모바일까지 잘 대응되는 모습에 react-big-calendar 를 선택하게 되었다.

tui calendar 도 모바일에서 잘 동작할 것이라는 예상을 하지만 예제에서 모바일에 대한 대응이 되지 않았던 점이 아쉬움으로 작용했던 것 같다.

react-big-calendar 의 커스터마이징 용이성

결론적으로 보면 react-big-calendar 의 선택은 만족스럽다. 그 중 가장 만족스럽게 여기는 부분은 calendar 의 커스터마이징이 용이하다는 점이다.

특히 rendering 할 컴포넌트 대상을 재정의하여 파라미터로 지정할 수 있다는 점이 굉장히 만족스러웠다.

아래 components 옵션을 보면 재정의할 수 있는 컴포넌트가 얼마나 다양한지를 확인할 수 있다.

components: PropTypes.shape({
  event: PropTypes.elementType,
  eventWrapper: PropTypes.elementType,
  eventContainerWrapper: PropTypes.elementType,
  dateCellWrapper: PropTypes.elementType, /* 이번 예제에서 재정의한 대상 #1*/
  dayColumnWrapper: PropTypes.elementType,
  timeSlotWrapper: PropTypes.elementType,
  timeGutterHeader: PropTypes.elementType,
  timeGutterWrapper: PropTypes.elementType,
  resourceHeader: PropTypes.elementType,

  toolbar: PropTypes.elementType,

  agenda: PropTypes.shape({
    date: PropTypes.elementType,
    time: PropTypes.elementType,
    event: PropTypes.elementType,
  }),

  day: PropTypes.shape({
    header: PropTypes.elementType,
    event: PropTypes.elementType,
  }),
  week: PropTypes.shape({
    header: PropTypes.elementType,
    event: PropTypes.elementType,
  }),
  month: PropTypes.shape({
    header: PropTypes.elementType,
    dateHeader: PropTypes.elementType,/* 이번 예제에서 재정의한 대상 #2*/
    event: PropTypes.elementType,
  }),
}),

적용 사례 #1

실례로 나는 음력 날짜 표기를 위해 dateHeader 를 재정의했고, 선택된 날짜에 하이라이팅 효과를 주기 위해 dateCellWrapper 를 재정의했다.

<Calendar
	components={{
		month: {
			dateHeader: MyDateHeader,
		},
		dateCellWrapper: MyDateCellWrapper,
    }}
/>

month 의 dateHeader 영역을 재정의한 MyDateHeader 는 다음과 같았다.
(실제는 약간의 최적화가 추가되어 형태는 조금 다르지만 거의 대동소이하다.)

const MyDateHeader = ({lable, date}) => {
  return (
    <div>
        <button className="rbc-button-link" role="cell">
          {label}
        </button>
      	/* 음력날짜를 추가로 표기 */
        <div className={styles.MyDateHeaderLunarDate}>
          {moment(date).lunar().format("MM.DD")}
        </div>
   </div>)
}

이로 인해 아래와 같이 음력 날짜를 표기할 수 있게 되었다.

적용 사례 #2

dateCellWrapper 을 재정의한 MyDateCellWrapper 부분은 다음과 같다.

현재 선태된 날짜의 경우 isSelected 플래그를 활성화하고 isSelected 인 경우 selected 스타일을 적용하였다.

const MyDateCellWrapper = (props) => {
  // 선택상태가 변경되었을 때에만 다시 렌더링 한다.
  return (
    <div
      className={`${styles.wrap} ${isSelected ? styles.selected : ""}`}>
      {children}
    </div>
  );
};

적용 결과는 아래 사이트를 통해 그 결과를 확인해 볼 수 있다.

https://www.month2k.com

현재는 음력 달력만 적용해 보았다.

이 외에도 총 20개의 주요 요소에 대한 렌더링 커스터마이징을 통해 달력을 제공할 수 있다는 점이 매력적으로 느껴지는데 달력 서비스를 제공하면서 커스터마이징이 필요한 것을 고려한다면 꽤 괜찮은 달력 라이브러리 같다.

profile
계속 성장하고 싶은 개발자. 사이드프로젝트(https://www.month2k.com)

0개의 댓글