ํ‹ฐ์Šคํ† ๋ฆฌ ๋ทฐ

์‹œ์ž‘ ์š”์ผ, ์›”๊ฐ„๋งŒ ๋ณด์—ฌ์ฃผ๊ธฐ

 

์›”์š”์ผ๋ถ€ํ„ฐ ์‹œ์ž‘

const localizer = dateFnsLocalizer({
  format,
  parse,
  startOfWeek: () => startOfWeek(new Date(), { weekStartsOn: 1 }), // ์›”์š”์ผ ์‹œ์ž‘
  getDay,
  locales,
});

 

 

์›”๊ฐ„๋งŒ ๋ณด์—ฌ์ฃผ๊ธฐ

   <Calendar
        localizer={localizer}
        events={events} // ์—ฌ๊ธฐ์— ์ด๋ฒคํŠธ ์ถ”๊ฐ€ ๊ฐ€๋Šฅ
        startAccessor='start'
        endAccessor='end'
        defaultView='month' // ๊ธฐ๋ณธ ๋ณด์—ฌ์ฃผ๊ธฐ : ์›”๋ณ„
        views={['month']} // ์›”๊ฐ„ ๋‹ฌ๋ ฅ๋งŒ ๋ณด์—ฌ์ฃผ๊ธฐ
        style={{ height: 500 }}
      />

 

 

 

RBC ์ฃผ์š” ์ปดํฌ๋„ŒํŠธ

 

์ขŒ์ธก ์ƒ๋‹จ์— ๋‚ ์งœ ๋„˜๊ธฐ๊ธฐ / ์˜ค๋Š˜ ๋‚ ์งœ ๋ฒ„ํŠผ์„ ๋‘์–ด ๋‹ฌ๋ ฅ์˜ ์ด๋™์„ ๊ตฌํ˜„ํ•˜๊ณ  ์‹ถ์—ˆ๋‹ค.

์‚ฌ๋ก€๋ฅผ ์ฐพ๋‹ค๋ณด๋‹ˆ RBC์˜ ์š”์†Œ๋“ค์„ ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ๋กœ ์ชผ๊ฐœ์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ๋˜์—ˆ๋‹ค.

 

์ชผ๊ฐค ์ˆ˜ ์žˆ๋Š” ์ฃผ์š” ์ปดํฌ๋„ŒํŠธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

components={{
  toolbar,           // ์ƒ๋‹จ ํˆด๋ฐ”
  event,             // ์ด๋ฒคํŠธ ์…€
  agenda: {
    event,           // agenda view์˜ ์ด๋ฒคํŠธ
  },
  timeSlotWrapper,   // ์‹œ๊ฐ„ ์Šฌ๋กฏ (์‹œ๊ฐ„ ์นธ)
  dateCellWrapper,   // ๋‚ ์งœ ์…€ (์›”๊ฐ„ ๋ทฐ ์…€)
  day,               // ์ผ๊ฐ„ ๋ทฐ
  week,              // ์ฃผ๊ฐ„ ๋ทฐ
  month,             // ์›”๊ฐ„ ๋ทฐ
}}

 

 

Toolbar์˜ props

๊ทธ ์ค‘ ํˆด๋ฐ”์— ํ•ด๋‹นํ•˜๋Š” ์š”์†Œ๋ฅผ ์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ฒ ๋‹ค.

label, onNavigate, localizer, onView, date, view, views

 

label

 

  • ํˆด๋ฐ” ์ค‘์•™์— ๋ณดํ†ต ๋ณด์ด๋Š” ํ˜„์žฌ ๋‚ ์งœ ๋ฒ”์œ„์˜ ํ…์ŠคํŠธ (์˜ˆ: "April 2025")
  • RBC ๋‚ด๋ถ€์—์„œ ์ž๋™์œผ๋กœ ๋งŒ๋“ค์–ด์คŒ
<span>{label}</span>  // "April 2025"

 

 

 

onNavigate(action)

  • ์ด์ „/๋‹ค์Œ/์˜ค๋Š˜ ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ์‚ฌ์šฉํ•˜๋Š” ํ•จ์ˆ˜
  • action ๊ฐ’์€ ๋‹ค์Œ ์ค‘ ํ•˜๋‚˜: 'PREV', 'NEXT', 'TODAY', 'DATE'
 
<button onClick={() => onNavigate('TODAY')}>Today</button>
<button onClick={() => onNavigate('PREV')}>{'<'}</button>
<button onClick={() => onNavigate('NEXT')}>{'>'}</button>

 

 

localizer

  • ๋‹ฌ๋ ฅ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋‚ ์งœ/์‹œ๊ฐ„ ๊ด€๋ จ ๊ธฐ๋Šฅ๋“ค์„ ์ง€์—ญ(locale)์— ๋งž๊ฒŒ ์ฒ˜๋ฆฌ
  • ๋‚ ์งœ๋ฅผ "2025๋…„ 4์›” 7์ผ"์ฒ˜๋Ÿผ ํฌ๋งท
  • ์š”์ผ์„ "Mon", "Tue"๊ฐ€ ์•„๋‹ˆ๋ผ "์›”", "ํ™”"์ฒ˜๋Ÿผ ๋ณ€๊ฒฝ
  • ์ฃผ์˜ ์‹œ์ž‘ ์š”์ผ์„ ์›”์š”์ผ๋กœ ์„ค์ •

 

onView(viewName)

  • ๋ทฐ(์˜ˆ: month, week, day, agenda)๋ฅผ ์ „ํ™˜ํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ํ•จ์ˆ˜
  • views props์— ํ•ด๋‹น ๋ทฐ๊ฐ€ ๋“ฑ๋ก๋˜์–ด์žˆ์–ด์•ผ ์ž‘๋™ํ•œ๋‹ค.
<button onClick={() => onView('month')}>Month</button>
<button onClick={() => onView('week')}>Week</button>

 

 

date

 

  • ํ˜„์žฌ ๋ณด์—ฌ์ง€๊ณ  ์žˆ๋Š” ์บ˜๋ฆฐ๋” ๋‚ ์งœ ๊ธฐ์ค€์˜ Date ๊ฐ์ฒด (์˜ˆ: 2025-04-01)
  • ์ง์ ‘ ๋‚ ์งœ ์กฐ์ž‘ํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์œ ์šฉ

 

 

view

  • ํ˜„์žฌ ๋ณด๊ณ  ์žˆ๋Š” ๋ทฐ์˜ ์ด๋ฆ„ ('month', 'week', 'day', 'agenda')
if (view === 'month') {
  // ์›”๊ฐ„ ๋ทฐ ์ „์šฉ UI ๋ณด์—ฌ์ฃผ๊ธฐ
}

 

 

views

 

  • ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ทฐ๋“ค์˜ ๋ฐฐ์—ด (์˜ˆ: ['month', 'week', 'day'])
  • ์ด๊ฑธ๋กœ view ์ „ํ™˜ ๋ฒ„ํŠผ์„ ๋™์ ์œผ๋กœ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

์ด์ „, ๋‹ค์Œ ๋‹ฌ ๋„˜๊ธฐ๊ธฐ

onNavigate()์™€ date๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

 

๊ณต์‹ ๋ฌธ์„œ์—์„œ๋Š” onNavigate์™€ date๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ค๋ช…ํ•˜๊ณ  ์žˆ๋‹ค.

๋‘˜์€ ํ•จ๊ป˜ ์‚ฌ์šฉ๋˜๋ฉฐ onNavigate ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด date๋ฅผ ์ œ์–ดํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

 

๋™์ ์œผ๋กœ ๋ณ€ํ•˜๋Š” ๋‚ ์งœ๋ฅผ state๋กœ ๋‘๊ณ  onNavigate ํ•จ์ˆ˜๋กœ ์ด๋ฅผ ์ œ์–ดํ–ˆ๋‹ค.

// MainCalendar.tsx

const MainCalendar = () => {
  const [month, setMonth] = useState(new Date());
  
  return (
    <div>
   	 <Calendar
        localizer={localizer}
        events={events}
        date={month} // ํ˜„์žฌ ๋‚ ์งœ(๋‹ฌ)
        onNavigate={(newDate) => {
          setMonth(newDate); // ๋‚ ์งœ(๋‹ฌ) ๋ณ€๋™
        }}
        startAccessor='start'
        endAccessor='end'
        defaultView='month'
        views={['month']}
        components={{
          toolbar: CustomToolbar, // ์ƒ๋‹จ ํˆด๋ฐ” ๋ถ„๋ฆฌ
        }}
        style={{ height: 500 }}
      />
    </div>
  );
};
// CustomToolbar.tsx

import React from 'react';
import { NavigateAction } from 'react-big-calendar';

interface Props {
  label: string;
  onNavigate: (action: NavigateAction) => void;
}

const CustomToolbar = ({ label, onNavigate }: Props) => {
  return (
    <div>
      <button onClick={() => onNavigate('PREV')}>โฌ…๏ธ</button>
      <span>{label}</span>
      <button onClick={() => onNavigate('NEXT')}>โžก๏ธ</button>
      <button onClick={() => onNavigate('TODAY')}>Today</button>
    </div>
  );
};

export default CustomToolbar;

 

 

๐Ÿค” ๋ฒ„ํŠผ์€ CustomToolbar ์•ˆ์— ์žˆ๋Š”๋ฐ ์™ธ๋ถ€์— date๋ž‘ onNavigate๋ฅผ ๋‘์–ด๋„ ์ž‘๋™๋˜๋Š” ์ด์œ ๊ฐ€ ๋ญ˜๊นŒ?

 

์บ˜๋ฆฐ๋” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํˆด๋ฐ”์—๊ฒŒ props๋ฅผ ๋„˜๊ฒจ์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ๋‘˜์ด ์—ฐ๊ฒฐ๋  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

 

์ข€ ๋” ์ž์„ธํžˆ ์‚ดํŽด๋ณด์ž๋ฉด,

<Calendar
  date={month}                          // ๐Ÿ‘‰๐Ÿป ํ˜„์žฌ ๋‚ ์งœ state
  onNavigate={(newDate) => setMonth(newDate)} // ๐Ÿ‘‰๐Ÿป ๋‚ ์งœ ๋ณ€๊ฒฝ ํ•จ์ˆ˜
  components={{ toolbar: CustomToolbar }}      // ๐Ÿ‘‰๐Ÿป ์ปค์Šคํ…€ ํˆด๋ฐ” ์ ์šฉ
/>

 

 

  1. ์‚ฌ์šฉ์ž๊ฐ€ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•œ๋‹ค.
  2. CustomToolbar์—์„œ onNavigate('PREV')
  3. RBC ์ž์ฒด์ ์œผ๋กœ PREV์— ๋งž๋Š” newDate ๊ณ„์‚ฐ
  4. Calendar์˜ onNavigate(newDate) ํ˜ธ์ถœ
  5. Calendar์˜ setMonth(newDate) → state ์—…๋ฐ์ดํŠธ
  6. Calendar ๋‹ค์‹œ ๋ Œ๋”๋ง + CustomToolbar๋„ ๋ฆฌ๋ Œ๋”๋ง

 

 

localizer ์„ค์ • : 2025 4์›”

์‚ฌ์‹ค ์ตœ์ƒ๋‹จ์— ์ •๋ฆฌํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ํˆด๋ฐ”๊ฐ€ ์•„๋‹Œ ์บ˜๋ฆฐ๋”์—์„œ ์›”์š”์ผ ์‹œ์ž‘์„ ๊ตฌํ˜„ํ–ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์บ˜๋ฆฐ๋”์—์„œ์™€ ํˆด๋ฐ”์—์„œ์˜ localizer ์—ญํ•  ์ฐจ์ด๋„ ๊ถ๊ธˆํ–ˆ๋‹ค.

 

 

๐Ÿ“์บ˜๋ฆฐ๋”์—์„œ์˜ localizer

์ „์ฒด ์บ˜๋ฆฐ๋”์˜ ๋‚ ์งœ ์ฒ˜๋ฆฌ ๊ธฐ์ค€์„ ์ •ํ•œ๋‹ค.

<Calendar localizer={localizer} ... />

 

  • ๊ธฐ๋ณธ ๋‚ ์งœ ํฌ๋งทํŒ…, ์‹œ์ž‘ ์š”์ผ, ์–ธ์–ด/๋กœ์ผ€์ผ, ๋‚ ์งœ ๊ณ„์‚ฐ ๋กœ์ง ๋“ฑ์„ Calendar์— ์ „๋‹ฌ
  • ๋‚ด๋ถ€์ ์œผ๋กœ localizer.format(...), localizer.startOfWeek(...) ๋“ฑ์„ ์‚ฌ์šฉํ•ด์„œ ๋‚ ์งœ ์ฒ˜๋ฆฌ
  • ์‹œ์ž‘ ์š”์ผ์„ ์›”์š”์ผ: startOfWeek: () => startOfWeek(new Date(), { weekStartsOn: 1 })

 

 

๐Ÿ“ํˆด๋ฐ”์—์„œ์˜ localizer

ํˆด๋ฐ”์— ํ‘œ์‹œ๋˜๋Š” ๋‚ ์งœ ํ…์ŠคํŠธ ํฌ๋งทํ•œ๋‹ค.

const CustomToolbar = ({ localizer }: ToolbarProps<Event>) => {
  const label = localizer.format(date, 'yyyy MMMM', 'ko-KR');
};

 

  • Calendar์—์„œ ๋„˜๊ฒจ์ค€ localizer ๊ฐ์ฒด๊ฐ€ ํˆด๋ฐ”์—๋„ ์ „๋‹ฌ
  • ํˆด๋ฐ”๋Š” ๋ณดํ†ต ํ˜„์žฌ ๋‚ ์งœ์— ๋งž๋Š” ๋ฌธ์ž์—ด(label) ์„ ํ‘œ์‹œํ•˜๊ธฐ ๋•Œ๋ฌธ์—,
    localizer.format(...) ์„ ์ง์ ‘ ํ˜ธ์ถœํ•ด์„œ ์‚ฌ์šฉ์ž๊ฐ€ ๋ณด๊ธฐ ์‰ฌ์šด ํ…์ŠคํŠธ๋ฅผ ๋งŒ๋“ ๋‹ค.
  • "2025๋…„ 4์›”" ํ•œ๊ธ€๋กœ ํ‘œ์‹œํ•˜๊ณ  ์‹ถ์„ ๋•Œ : ์ง์ ‘ format์„ ํ˜ธ์ถœํ•ด์„œ ์ฒ˜๋ฆฌ

 

 

 

์ง€๊ธˆ ํ•„์š”ํ•œ ๊ฑด ๋‚ ์งœ๋ฅผ "2025๋…„ 4์›”"์ฒ˜๋Ÿผ ํฌ๋งท ํ•˜๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.

  • localizer.format(date, formatString, culture)์„ ์‚ฌ์šฉํ•˜์—ฌ ์›ํ•˜๋Š” ํ˜•ํƒœ๋กœ ๋‚ ์งœ ์ถœ๋ ฅ ๊ฐ€๋Šฅํ•˜๋‹ค.

 

ํ•˜์ง€๋งŒ,

์บ˜๋ฆฐ๋”์— const localizer = dateFnsLocalizer() ๋ช…์‹œ๋„ ํ•˜๊ณ , ํˆด๋ฐ”์—๋„ ๋งž๊ฒŒ ์ ์šฉํ–ˆ์ง€๋งŒ ๊ณ„์†ํ•ด์„œ 'message' ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค.

์›์ธ์€  dateFnsLocalizer()๋กœ ์ƒ์„ฑํ•œ localizer์™€ Calendar์˜ generic ํƒ€์ž…์ด ์„œ๋กœ ์•ˆ ๋งž์•„์„œ ์ƒ๊ธฐ๋Š” ๋ฌธ์ œ์ด๋‹ค.

์‚ฌ์‹ค ๊ทธ ๋‚ด์šฉ์„ ์•„์ฃผ ์ž์„ธํžˆ ํŒŒ์•…ํ•˜์ง€ ๋ชปํ–ˆ์ง€๋งŒ ๋Œ€๋žต ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ดํ•ดํ–ˆ๋‹ค.

์บ˜๋ฆฐ๋”์—์„œ๋Š” id๊ฐ€ ํฌํ•จ๋œ supabase ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— CalendarEventType(id ํฌํ•จ) ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜์ง€๋งŒ,
ํˆด๋ฐ”์—๋Š” id๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค. ๋”ฐ๋ผ์„œ ๋‘˜์˜ ํƒ€์ž…์ด ๋งž์ง€ ์•Š์•„์„œ ์ƒ๊ธฐ๋Š” ๋ฌธ์ œ

 

 

 

๋”ฐ๋ผ์„œ ๋ฌธ์ œ๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•ด๊ฒฐํ•˜์˜€๋‹ค.

  • ํˆด๋ฐ”์˜ ํƒ€์ž…์„ ์บ˜๋ฆฐ๋”์™€ ๊ฐ™๊ฒŒ ๋ช…์‹œํ•ด์ฃผ๊ธฐ => ์บ˜๋ฆฐ๋”์˜ components > toolbar ์—์„œ ํƒ€์ž… ์˜ค๋ฅ˜ ์‚ฌ๋ผ์ง
  • date-fns์—์„œ ํ•œ๊ธ€ ๋‚ ์งœ๊ฐ’ ๊ฐ€์ ธ์˜ค๊ธฐ
import { CalendarEventType } from '@/types/plans';
import { format } from 'date-fns';
import { ko } from 'date-fns/locale';
import { ToolbarProps } from 'react-big-calendar';

//โญ๏ธ์บ˜๋ฆฐ๋”์™€ ํƒ€์ž… ๋งž์ถค(id ์œ ์‹ค๋กœ ์ธํ•œ ์˜ค๋ฅ˜)โญ๏ธ 
const CustomToolbar = ({ date, onNavigate }: ToolbarProps<CalendarEventType>) => {
  const customLabel = format(date, 'yyyy MMMM', { locale: ko });
  return (
    <div>
      <button onClick={() => onNavigate('PREV')}>โฌ…๏ธ</button>
      <span>{customLabel}</span>
      <button onClick={() => onNavigate('NEXT')}>โžก๏ธ</button>
      <button onClick={() => onNavigate('TODAY')}>Today</button>
    </div>
  );
};

export default CustomToolbar;

 

์–ด์ฐจํ”ผ ์ปค์Šคํ„ฐ๋งˆ์ด์ง• ํ•˜๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ผญ localizer์— ์–ฝ๋ฉ”์ด์ง€ ์•Š๊ณ  date-fns์—์„œ ํ•œ๊ธ€๋กœ ๋งž๊ฒŒ ๋ฒˆ์—ญํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ํƒํ–ˆ๋‹ค.

๊ณต์ง€์‚ฌํ•ญ
์ตœ๊ทผ์— ์˜ฌ๋ผ์˜จ ๊ธ€
์ตœ๊ทผ์— ๋‹ฌ๋ฆฐ ๋Œ“๊ธ€
Total
Today
Yesterday
๋งํฌ
TAG
more
ยซ   2026/03   ยป
์ผ ์›” ํ™” ์ˆ˜ ๋ชฉ ๊ธˆ ํ† 
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
๊ธ€ ๋ณด๊ด€ํ•จ