-
[ React Native ] React Native Big Calendar 공휴일 커스텀Application/React Native 2026. 3. 14. 17:54반응형
https://yumedev.tistory.com/103
[ Next ] 공휴일 Open Api 만들기
만드는 프로젝트에 캘린더가 들어가면 항상 공공데이터포털에서 api를 호출해서 사용해야하기 때문에이전 라이브러리는 직접 공공데이터포털 api를 호출해서 뿌려주기때문에 결국에는 직접 공
yumedev.tistory.com
이전 공휴일 open api를 만들고 나서 앱에서 해당 api를 호출하도록 했다.
redis를 사용했지만 redis도 무료 제한이 있기때문에 나중에는 해당 부분이 문제가 생기면
따로 local에 저장해서 날짜 업데이트 하는 시기에 맞춰서만 api를 호출하도록 수정해야할 수도..
우선 공휴일 데이터를 불러왔으니 이제 캘린더에 공휴일 표시를 해줘야한다.
React Native Big Calendar
https://yumedev.tistory.com/101
[ React Native ] React Native Calendar 커스텀
React Native에서 캘린더를 구현할려고하는데처음에는 React Native Calendar를 사용했는데 캘린더의 일정 표시를 하루는 되지만 범위가 안되어서 다른 라이브러리를 사용. React Native Big Calendar는 일정 ran
yumedev.tistory.com
이전 라이브러리에서 날짜 커스텀이 안되서 직접 건드려서 날짜의 style을 바꾼 것처럼이번에도 직접 라이브러리를 바꿔서 사용할려고 한다.
우선 공휴일 데이터를 가져왔으니 이걸 캘린더에 props로 전달해줘야한다.
그래서 캘린더 props 타입에 holidayEvent 타입을 추가
export interface CalendarContainerProps<T extends ICalendarEventBase> { /.../ holidayEvent?: Record<string, string>; }이후 props로 전달 받은 것을 받아올 수 있도록
renderEvent =. a.renderEvent가 붙은 곳에 전부 붙혀주었다.
( 일단 renderEvent는 할일 렌더링을 해주는 부분이니까 그냥 사용하는 부분에는 다 공휴일 데이터가 필요할 수도.. 하면서 다 붙혀주었다. )
renderEvent = _a.renderEvent, holidayEvent = _a.holidayEvent이후 공휴일 데이터는 결국 db에서 데이터를 가져오는 것이므로 await로 가져와야하다보니
캘린더에서도 데이터가 들어오고 나서 렌더링 하는게 아닌이상 데이터가 가져오면 다시 재렌더링 시켜줘야한다.
그래서 기존 로직에서 holidayEvent를 감지할 수 있도록해야한다.
index.js에 보면 calendarContainer 부분이 있는데
여기서 월 모드만 쓰기때문에
return 부분에 마지막 createElement 부분에 holidayeEvent: holidayEvent를 추가해주었다.
function _CalendarContainer(_a) { /.../ if (mode === 'month') { /.../ return (React__default["default"].createElement(React__default["default"].Fragment, null, React__default["default"].createElement(HeaderComp_1, tslib.__assign({}, headerProps_1)), React__default["default"].createElement(.... renderEvent: renderEvent, holidayEvent: holidayEvent,...)
Calendar Component
공휴일 데이터는 날짜가 바뀌면 이전 저장된 년도를 비교해서
다르면 데이터를 가져오고 같으면 그대로 유지하도록 처리
useEffect(() => { if(props.date.year() !== currentYear) { setCurrentYear(props.date.year()) } }, [monthKey]); const [holidays, setHolidays] = useState<Record<string, string>>({}); useEffect(() => { const fetchHolidays = async () => { const data = await appStore.getYearHolidays(currentYear); setHolidays(data || {}); }; fetchHolidays(); }, [currentYear]);이후 store에서도 캐싱된 데이터가 존재하면 존재하는 데이터로 없다면 api를 호출해서 데이터를 가져오도록 설정
interface AppState { /.../ // 휴일 정보 캐싱 holidayMap: Record<string, string> getYearHolidays: (year: number) => Promise<Record<string,string>> loadHolidays: (year: number) => Promise<void> } export const useAppStore = create<AppState>((set,get) => ({ /.../ holidayMap: {}, getYearHolidays: async (year) => { const { holidayMap } = get(); if (holidayMap[year] && Object.keys(holidayMap[year]).length > 0) { return holidayMap[year]; } const holidays = await getHolidays(year) set((state) => ({ holidayMap: { ...state.holidayMap, [year]: holidays } })) return holidays; }, loadHolidays: async (year) => { const { getYearHolidays } = get(); getYearHolidays(year) }, }))이후 props를 전달
<Calendar<CalendarEvent> /.../ holidayEvent={holidays} /.../ />
Test
이후 이전에 수정한 renderDateCell함수에 holidayEvent를 찍어서 데이터가 정상적으로 들어오는지 확인
var renderDateCell = function (date, index) { /.../ console.log(holidayEvent) }이후 시간은 좀 걸리지만 데이터가 나오는 것을 확인 할 수 있다.
현재 처음 캘린더가 로딩되고 이후 공휴일 데이터가 들어오면서 재렌더링 해서 속도가 좀 느려서 이부분을
좀 더 데이터 처리 방식 아니면 캘린더 렌더링 방식을 변경해서 추가 작업을 해야할 것 같다.

이후 이제 날짜와 holidayEvent와 비교해서 존재하면 날짜를 빨간색으로 바꾸고 토요일을 그냥 파란색으로 나오도록 처리
var renderDateCell = function (date, index) { if (date && renderCustomDateForMonth) { return renderCustomDateForMonth(date.toDate()); } // 1. 공통 변수 설정 var isToday = (date === null || date === void 0 ? void 0 : date.format(SIMPLE_DATE_FORMAT)) === now.format(SIMPLE_DATE_FORMAT); var isCurrentMonth = (date === null || date === void 0 ? void 0 : date.month()) === targetDate.month(); var day = date === null || date === void 0 ? void 0 : date.day(); var dateStr = date ? date.format('YYYYMMDD') : null; var holidayName = (dateStr && holidayEvent) ? holidayEvent[dateStr] : null; // 2. 색상 결정 로직 var getTextColor = function () { if (isToday) return theme.palette.primary.main; if (day === 0 || holidayName) { // 일요일 return isCurrentMonth ? '#FF3B30' : 'rgba(255,59,48,0.2)'; // 이번 달 아니면 30% 투명도 (HEX 뒤에 4D 추가) } if (day === 6) { // 토요일 return isCurrentMonth ? '#007AFF' : 'rgba(0,122,255,0.2)'; // 이번 달 아니면 30% 투명도 } // 평일 return isCurrentMonth ? theme.palette.gray['800'] : theme.palette.gray['500']; }; var todayContainerStyle = isToday ? { backgroundColor: theme.palette.primary.main, color: theme.palette.gray['800'], width: 18, height: 18, padding: 2, borderRadius: 100, } : { padding: 2, }; return ( React__namespace.createElement(reactNative.View, { style: { flexDirection: 'row', alignItems: 'center', justifyContent: 'start', paddingVertical: 2, width: '100%', paddingHorizontal: 2 } }, // 날짜 숫자 React__namespace.createElement(reactNative.Text, { style: [ { textAlign: 'center' }, theme.typography.sm, { color: getTextColor() }, todayContainerStyle, tslib.__assign({}, getCalendarCellTextStyle(date === null || date === void 0 ? void 0 : date.toDate(), index)), ] }, date && date.format('D')), // 공휴일 명칭 holidayName && React__namespace.createElement(reactNative.Text, { style: { fontSize: 8, fontWeight: 'bold', color: isCurrentMonth ? '#FF3B30' : 'rgba(255,59,48,0.2)', marginLeft: 2, flexShrink: 1, }, numberOfLines: 1, ellipsizeMode: 'clip' }, holidayName) ) ); };그럼 이렇게 공휴일 데이터가 정상적으로 들어가서 화면에 나오는 것을 확인할 수 있다.

728x90반응형'Application > React Native' 카테고리의 다른 글
[ React Native ] 캘린더 공휴일 데이터 API (0) 2026.03.08 [ React Native ] React Native Calendar 커스텀 (0) 2026.01.17 [ React Native ] Bottom Sheet (0) 2025.10.19 [ React Native ] FlatList + slide card (0) 2025.10.15 [ React Native ] i18n 적용 언어변경하기 (0) 2025.10.12