본문 바로가기

TIL

월간 달력 출력하기 (FullCalendar / Shadcn)

FullCalendar

FullCalendar: 복잡한 일정 관리가 필요한 경우 (예: 회사 일정 관리, 예약 시스템)

장점 단점
  • 월/주/일 등 다양한 뷰 제공
  • 이벤트 표시 및 관리 기능이 풍부
  • 시간대별 일정 관리 가능
  • 드래그 앤 드롭으로 일정 이동 가능
  • 번들 사이즈가 큼
  • 초기 설정이 복잡할 수 있음
  • 스타일링 커스터마이징이 까다로움
  • 무료 버전과 프로 버전의 기능 차이

 

1. FullCalendar 관련 종속성 설치 명령어

yarn add @fullcalendar/core @fullcalendar/react @fullcalendar/daygrid

 

@fullcalendar/core

  • FullCalendar의 핵심 기능을 제공하는 기본 패키지
  • Calendar 클래스와 같은 핵심 기능을 포함하고 있어 캘린더를 생성하고 관리하는 데 필수적

@fullcalendar/react

  • FullCalendar를 React 애플리케이션에서 사용할 수 있게 해주는 React 컴포넌트를 제공
  • React 프로젝트에서 FullCalendar를 쉽게 통합할 수 있도록 해주는 래퍼(wrapper) 컴포넌트

@fullcalendar/daygrid

  • 월별 , 주별 , 일별 날짜 그리드 형식의 캘린더 뷰를 제공

 

Next.js 13부터는 app 디렉토리 내의 컴포넌트가 기본적으로 서버 컴포넌트로 취급된다.

* FullCalendar는 클라이언트 측 JavaScript를 필요로 하므로, 'use client' 지시문을 사용하여 클라이언트 컴포넌트로 명시해야 함!

 

 

2. 기본 캘린더 생성

컴포넌트에서 FullCalendar를 import하고 기본 설정으로 렌더링

"use client";

import FullCalendar from "@fullcalendar/react";
import dayGridPlugin from "@fullcalendar/daygrid";
import interactionPlugin from '@fullcalendar/interaction';


const Calendar = () => {
  return <FullCalendar plugins={[dayGridPlugin, interactionPlugin]} initialView="dayGridMonth" />;
};

export default Calendar;

 

추가한 플러그인

dayGridPlugin - 월간, 주간, 일간 그리드 레이아웃을 제공

interactionPlugin - 사용자 상호작용과 관련된 기능을 제공(날짜 클릭, 날짜 범위 선택, 드래그 . 앤드롭, 이벤트 클릭)

 

 

3. 클릭한 날짜의 정보 출력하기

"use client";

import FullCalendar from "@fullcalendar/react";
import dayGridPlugin from "@fullcalendar/daygrid";
import interactionPlugin from "@fullcalendar/interaction";
import { DateClickArg } from "@fullcalendar/interaction";

const Calendar = () => {
  const handleDateClick = (arg: DateClickArg) => {
    console.log(arg.dateStr);
    console.log(arg.date);
  };

  return (
    <FullCalendar
      plugins={[dayGridPlugin, interactionPlugin]}
      initialView="dayGridMonth"
      dateClick={handleDateClick}
    />
  );
};

export default Calendar;

 

interactionPlugin 에서 제공하는 dateClick 기능을 추가해 클릭한 날짜의 정보를 가져올 수 있다.

클릭한 날짜의 정보는 아래와 같은 객체 형태로 출력된다.

해당 값의 type은 FullCalendar에서 제공하는 타입인 DateClickArg 를 import 해서 지정해주었다.

 

 

4. 날짜 클릭 이벤트에 라우팅 처리해주기

콘솔에 클릭한 날짜의 값이 정상적으로 출력되는 것을 확인했으니 선택한 날짜에 해당하는 페이지로 이동하는 라우팅 처리를 해주었다.

const router = useRouter();
  const handleDateClick = (arg: DateClickArg) => {
    router.push(`/study/${studyId}/${arg.dateStr}`);
  };

 

 


Shadcn/ui

Shadcn Calendar: 단순 날짜 선택이 필요한 경우 (예: 생년월일 선택, 특정 날짜 선택)

장점 단점
  • 가볍고 심플한 디자인
  • 설치와 사용이 매우 간단
  • Tailwind CSS와 잘 어울림
  • 날짜 선택 기능에 충실
  • 월별 보기만 제공
  • 이벤트 표시 기능 없음
  • 고급 기능이 제한적
  • 단순 날짜 선택 용도로만 적합

 

 

 

1. Shadcn/ui Calendar 설치

npx shadcn@latest add calendar

 

 

2. 기본 캘린더 생성

import { Calendar } from "@/components/ui/calendar"
import { useState } from "react"

const CalendarDemo = () => {
  // 선택된 날짜를 관리할 state
  const [date, setDate] = useState<Date | undefined>(new Date())

  return (
    <Calendar
      mode="single"          // 단일 날짜 선택 모드
      selected={date}        // 선택된 날짜
      onSelect={setDate}     // 날짜 선택 시 호출될 함수
      className="rounded-md border"
    />
  )
}

 

 

3. 클릭한 날짜의 정보 출력해서 확인

 

 

 

4. 클릭한 날짜로 라우팅 처리 해주기

클릭한 날짜를 yyyy-MM-dd 형태로 변환해서 라우팅 처리를 해주었다.

const GroupCalendar = ({ studyId }: { studyId: string }) => {
  const [date, setDate] = useState<Date | undefined>(undefined); // 초기값 undefined 설정
  const router = useRouter();

  const handleDateClick = (selectedDate: Date | undefined) => {
    if (selectedDate) {
      const formattedDate = format(selectedDate, "yyyy-MM-dd"); // 날짜를 yyyy-MM-dd 형태로 변환
      setDate(selectedDate);
      router.push(`/study/${studyId}/${formattedDate}`);
    }
  };

  return (
    <Calendar
      mode="single" // 단일 날짜 선택 모드
      selected={date} // 선택된 날짜
      onSelect={handleDateClick} // 날짜 선택 시 호출될 함수
      className="rounded-md w-full p-4 flex justify-center items-center"
      classNames={{
        day_today: "bg-black text-white font-bold hover:bg-gray-800",
      }}
    />
  );
};

 

 

 

 

🧐 느낀점

처음에는 월간/주간 별 캘린더 기능을 제공하는 FullCalendar 를 사용하려 했으나 스타일링 커스터마이징이 복잡하다는 부분을 고려해 대안을 찾아보았다.

프로젝트에 필요한 기능으로는 월간/주간별 캘린더와 날짜 선택 기능이었기에, 가벼우면서 깔끔한 디자인을 제공하고 Tailwind css를 통해 편리하게 스타일링이 가능한 shadcn/ui 를 월간 캘린더&일정 선택 기능 구현으로 선택하게 되었다.

주간 캘린더의 경우, shadcn/ui 에서는 제공하지 않아 FullCalendar 또는 다른 라이브러리를 별도로 사용하기로 결정했다.

각 기능별로 최적화된 라이브러리를 선택함으로써 다양한 기술을 경험할 수 있었고 앞으로도 이어질 프로젝트에서 어떤식으로 기술을 선택해야할지 좀 더 생각해볼 수 있게된 과정이었던 것 같다.