ํฐ์คํ ๋ฆฌ ๋ทฐ
RBC์ ๋ํ ๊ธฐ๋ณธ์ ์ธ ๊ธฐ๋ฅ ๋ฐ ์ค์ ์ ์ผ์ถ ๋ง๋ฌด๋ฆฌ๋๊ณ , ์ค์ ๋ฐ์ดํฐ์ ์ฐ๋ํ๊ณ ์ ํ๋ค.
supabase ํ ์ด๋ธ์ ์ ์ฉ๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์์ ์บ๋ฆฐ๋์ ์ถ๋ ฅํด๋ณด์๋ค.
supabase ํ ์ด๋ธ ์ฐ๊ฒฐ ์ค์ ์ ๊ฐ๋ตํ ์๋์ ๊ฐ์ด ์งํํ๋ค.
- ํ์ด์ง, ์ปดํฌ๋ํธ ์์ฑ ๋ฐ ์ฐ๊ฒฐ
- supabaseClient ์์ฑ (supabaseClient.ts)
- plans ํ ์ด๋ธ ๊ฐ ๋ถ๋ฌ์ค๊ธฐ ๋ก์ง (supabaseApi.ts)
- plans ํ์ ์ง์
- ์ปดํฌ๋ํธ์์ ํธ์ถ : useState, useEffect
new Date()
์ด๊ธฐ๊ฐ์ ๋น ๋ฐฐ์ด๋ก ๋์ด ์ด๋ฒคํธ ์ํ๋ฅผ ๊ด๋ฆฌํ์๋ค.
ํ์ง๋ง state์ ํ์ ์ <plans[]>๋ก ์ง์ ํ์์ ๋ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
์๋ฌ๋ ๋ค์๊ณผ ๊ฐ์ด ๋ํ๋ฌ๋ค.
"์ด ํธ์ถ๊ณผ ์ผ์นํ๋ ์ค๋ฒ๋ก๋๊ฐ ์์ต๋๋ค. '"start"' ํ์์~ , '"end"' ํ์์~"
์๋ฌ ์์ธ์ supabase์ ๋ฐ์ดํฐ ๊ฐ๊ณผ RBC๊ฐ ํ์ํ ๊ฐ์ด ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ด๋ค.
- supabase : start_date์ end_date ๋ชจ๋ string
- RBC : start์ end ๋ชจ๋ Date ํ์
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ ๋ฐฉ๋ฒ์ supabase์ ๊ฐ์ ์๋ง๊ฒ ๋งคํํ๊ธฐ.
์ฆ, Date ๊ฐ์ฒด๋ก ๋ณํํ๊ธฐ ์ํด new Date()๋ฅผ ์ฌ์ฉํ๋ค.
์ ๋ฆฌํ์๋ฉด
- new Date() ์ฌ์ฉ ์ด์
- number์ string ํ์์ Date ํ์์ ํ ๋นํ ์ ์๋ค.
- ์ฆ, RBC์์๋ "start"์ "end" ํ๋๊ฐ Date ๊ฐ์ฒด์ฌ์ผ ํ๋ค.
- Supabase์์ ๋ฐ์์ค๋ start_date์ end_date์ type์ string.
- ์ด ๋์ ์ง์ Date ๊ฐ์ฒด๋ก ๋ณํ : new Date()
state ํ์ ์ <CalendarEvent[]>๋ก ๋ณ๊ฒฝํ๋ค.
๐Type๊ณผ ์ต์ข ๋ก์ง
export interface PlansType {
plan_id: string;
created_at: number;
user_id: string;
contacts_id: string;
start_date: string;
end_date: string;
title: string | null;
detail: string | null;
priority: string | null;
}
export interface CalendarEventType {
id: string;
title: string | null;
start: Date;
end: Date;
}
// src > components > commons > calendar.tsx
'use client';
import { Calendar, dateFnsLocalizer } from 'react-big-calendar';
import { format, parse, startOfWeek, getDay } from 'date-fns';
import { enUS } from 'date-fns/locale/en-US';
import { ko } from 'date-fns/locale/ko';
import { getPlans } from '@/lib/utils/supabaseApi';
import { useEffect, useState } from 'react';
import { CalendarEventType } from '@/types/plans';
// ๋ก์ผ์ผ(์ง์ญํ) ์ค์
const locales = {
'en-US': enUS, //๋ฏธ๊ตญ-์์ด : ๋ฏธ๊ตญ์ ๋ ์ง
'ko-KR': ko, //ํ๊ตญ-ํ๊ธ : ํ๊ตญ์ ๋ ์ง
};
const localizer = dateFnsLocalizer({
format,
parse,
startOfWeek,
getDay,
locales,
});
const MainCalendar = () => {
const [events, setEvents] = useState<CalendarEventType[]>([]);
useEffect(() => {
const fetchEvents = async () => {
try {
const plans = await getPlans();
const formatted = plans.map(
(plan): CalendarEventType => ({
id: plan.plan_id,
title: plan.title,
start: new Date(plan.start_date),
end: new Date(plan.end_date),
})
);
setEvents(formatted);
} catch (error) {
console.error('์ผ์ ๋ชฉ๋ก ๊ฐ์ ธ์ค๊ธฐ ์๋ฌ', error);
}
};
fetchEvents();
}, []);
return (
<div>
<Calendar
localizer={localizer}
events={events} // ์ฌ๊ธฐ์ ์ด๋ฒคํธ ์ถ๊ฐ ๊ฐ๋ฅ
startAccessor='start'
endAccessor='end'
style={{ height: 500 }}
/>
</div>
);
};
export default MainCalendar;
๋ฌ๋ ฅ๊ณผ DB์ ๊ฐ ์ฐจ์ด : UTC
supabase ๋ฐ์ดํฐ ์ค ์์์ผ๊ณผ ์ข ๋ฃ์ผ์ด ๋ฌ๋ ฅ๊ณผ ๋ค๋ฅด๊ฒ ๋ํ๋ฌ๋ค.
![]() |
![]() |
supabase์ ๋ฐ์ดํฐ ํ์ ์ timestamptz (ํ์์คํฌํ with ํ์์กด)์ผ๋ก ๋๋ฉด
๊ฐ์ด ์ถ๊ฐ๋ ๋ ์์ฒด์ ์ผ๋ก ์ธ๊ณํ์ค์๊ฐ(UTC)์ ์ ์ฉํ๋ค.
๋์ ์ ์ฅ์์๋ ๋ฐ์ดํฐ -> ๋ธ๋ผ์ฐ์ ์ถ๋ ฅ ์ด๋ค. ๋๋ฌธ์ ํ ์ด๋ธ์ ์ ์ฅ๋ ๊ฐ์ผ๋ก๋ถํฐ ํ๋ฃจ๊ฐ ๋ฐ๋ ค์ ์ถ๋ ฅ๋๋ ๊ฒ์ผ๋ก ๋๊ปด์ง์ง๋ง
์ฌ์ฉ์ ์ ์ฅ์์๋ ๋ธ๋ผ์ฐ์ ๋์ -> ๋ฐ์ดํฐ ์ ์ฅ ์ด๋ค. ๋๋ฌธ์ ์ค์ ์ฌ์ฉ์๋ 9์ผ ๋ฐฅ ๋จน๊ธฐ ์ผ์ ์ ์ถ๊ฐํ์ง๋ง -9์๊ฐ(ํ๊ตญ ๊ธฐ์ค UTC์ฒ๋ฆฌ)๊ฐ ๋์ด supabase์ ์ ์ฅ์ด ๋๋ ๊ฒ์ด๋ค.
(๋ธ๋ผ์ฐ์ )4์ 9์ผ 00:00:00 ๋ก ์ ํ -> (supabase) 4์ 8์ผ 15:00:00 ์ ์ฅ
์ฐ์ ์ผ์ ์ฒ๋ฆฌ - ์ข ๋ฃ์ผ ์ ๊ฐ
๋ฐ๋ผ์ ์ฌ์ฉ์๊ฐ ์ ํํ ์๊ฐ์ ๋ง์ถ์ด ๋ฌ๋ ฅ์ ์ ์ถ๋ ฅ๋๋ค.
ํ์ง๋ง ์ด๋ ๋จ์ผ ์ผ์ ์๋ง ์ ์ฉ์ด ๋๊ณ , ์ฐ์ ์ผ์ ์๋ ์กฐ๊ธ ๋ค๋ฅธ ์ฒ๋ฆฌ๋ฅผ ํด์ฃผ์ด์ผ ํ๋ค.

์์ test ์ผ์ ์ ๋ชจ๋ 5์ผ ์ผ์ ์ด๋ค. ํ์ง๋ง test-15๋ 4์ผ ์ผ์ ์ผ๋ก ์ถ๋ ฅ๋๋ค. ์ ๊ทธ๋ด๊น??
๊ฒฐ๋ก ๋ถํฐ ๋งํ์๋ฉด ์ข ๋ฃ์ผ ์๊ฐ์ด ์ ๊ฐ์ด๊ธฐ ๋๋ฌธ์ด๋ค.


test-15์ ์ผ์ ๋ฐ์ดํฐ์ด๋ค.
์ผ์ ์์์ผ์ ๋ณด๋ฉด UTC๊ฐ ์ ์ฉ๋์ด 13์ผ๋ก ์ ์ฅ๋์ด์์ง๋ง formatted ๊ฐ์ 14์ผ ์ ๊ฐ์ด๋ค.
์ผ์ ์ข ๋ฃ์ผ์ ๋ณด๋ฉด UTC๊ฐ ์ ์ฉ๋์ด 17์ผ๋ก ์ ์ฅ๋์ด์๋ค. ๋ง์ฐฌ๊ฐ์ง๋ก formatted ๊ฐ์ ๋ณด๋ฉด 18์ผ ์ ๊ฐ์ด๋ค.
์์์ผ์ formatted ๋ฐ์ดํฐ๊ฐ ์ ๊ฐ์ด์ด๋ ์์ํ๋ ๋ ์ด๊ธฐ์ ์ ์์ ์ผ๋ก ํ์๋์ง๋ง
์ข ๋ฃ์ผ์ ์ ๊ฐ ์๊ฐ์ด ์ ์ฉ๋์ด 18์ผ ์ด์ ๊น์ง๋ง ๋ฌ๋ ฅ์ ํ์๋๋ค.
๋ฐ๋ผ์ ์ข ๋ฃ์ผ์ 1์๊ฐ ์ ๋ ๋๋ ค ์ ์ฉ์ํค๋ฉด(์ผ์ ์ ๋ ฅ ๊ธฐ๋ฅ ๋ด๋น ํ์ ๋ถ์ด ์ ์ฉ)

์ข ๋ฃ์ผ์ด 18์ผ ์ค์ 1์๋ก ์ค์ ๋์ด ์์ ๋ฌ๋ ฅ์ฒ๋ผ(test-16) ์ ์ถ๋ ฅ๋๋ค.

