diff --git a/src/shared/constants/events/eventsData.ts b/src/shared/constants/events/eventsData.ts
deleted file mode 100644
index cf400d6..0000000
--- a/src/shared/constants/events/eventsData.ts
+++ /dev/null
@@ -1,75 +0,0 @@
-export interface EventData {
- id: number;
- name: string;
- address: string;
- description: string;
- startDate: string;
- endDate: string;
- imageSrc?: string;
-}
-
-export const eventData: EventData[] = [
- {
- id: 1,
- name: 'ICPC',
- address: '다솔관',
- description: '야르',
- startDate: '2025-11-01',
- endDate: '2025-11-03',
- imageSrc: '',
- },
- {
- id: 2,
- name: '아우름제',
- address: '울학교',
- description: '야르',
- startDate: '2025-11-01',
- endDate: '2025-11-02',
- imageSrc: '',
- },
- {
- id: 3,
- name: '졸업식',
- address: '가톨릭대학교',
- description: '야르',
- startDate: '2025-10-31',
- endDate: '2025-10-31',
- imageSrc: '',
- },
- {
- id: 4,
- name: '학술제',
- address: '가톨릭대학교',
- description: '야르',
- startDate: '2025-10-30',
- endDate: '2025-10-31',
- imageSrc: '',
- },
- {
- id: 5,
- name: '둡둗다다',
- address: '부천시청',
- description: '야르',
- startDate: '2025-10-30',
- endDate: '2025-10-31',
- imageSrc: '',
- },
- {
- id: 6,
- name: '배고파요',
- address: '부천역',
- description: '야르',
- startDate: '2025-10-31',
- endDate: '2025-11-01',
- imageSrc: '',
- },
- {
- id: 7,
- name: '마짐막 테스트',
- address: '가톨릭대학교',
- description: '야르',
- startDate: '2025-10-31',
- endDate: '2025-11-01',
- imageSrc: '',
- },
-];
diff --git a/src/shared/hooks/events/EventMapper.ts b/src/shared/hooks/events/EventMapper.ts
new file mode 100644
index 0000000..4ee17dc
--- /dev/null
+++ b/src/shared/hooks/events/EventMapper.ts
@@ -0,0 +1,12 @@
+import { EventData, EventResponse } from '@/shared/types/eventtypes';
+
+export const mapEvent = (item: EventResponse): EventData => ({
+ id: item.eventId,
+ name: item.title,
+ description: item.body,
+ address: item.address ?? '',
+ startDate: item.startDate ?? '',
+ endDate: item.endDate ?? '',
+ imageSrc: item.thumbnailUrl ?? item.imageUrl ?? '',
+ liked: item.isBookmarked ?? false,
+});
diff --git a/src/shared/hooks/events/useBookmark.ts b/src/shared/hooks/events/useBookmark.ts
new file mode 100644
index 0000000..90c92e5
--- /dev/null
+++ b/src/shared/hooks/events/useBookmark.ts
@@ -0,0 +1,48 @@
+'use client';
+
+import { useState, useEffect } from 'react';
+import { postBookmark, deleteBookmark } from '@/shared/api/events/event';
+import { getAccessToken } from '@/shared/utils/token';
+import { useQueryClient } from '@tanstack/react-query';
+
+export const useBookmark = (eventId: number, initialState: boolean) => {
+ const [isBookmarked, setIsBookmarked] = useState(initialState);
+ const [requireLogin, setRequireLogin] = useState(false);
+ const queryClient = useQueryClient();
+
+ useEffect(() => {
+ setIsBookmarked(initialState);
+ }, [initialState]);
+
+ const toggleBookmark = async () => {
+ const token = getAccessToken();
+ if (!token) {
+ setRequireLogin(true);
+ return;
+ }
+
+ try {
+ setIsBookmarked((prev) => !prev);
+ if (isBookmarked) {
+ await deleteBookmark(eventId);
+ } else {
+ await postBookmark(eventId);
+ }
+
+
+ queryClient.invalidateQueries({ queryKey: ['events'] });
+ queryClient.invalidateQueries({ queryKey: ['eventDetail', eventId] });
+ queryClient.invalidateQueries({ queryKey: ['myPage'] });
+ await queryClient.refetchQueries({ queryKey: ['myPage'] });
+ } catch (err) {
+ console.error('북마크 토글 실패:', err);
+ setIsBookmarked((prev) => !prev);
+ }
+ };
+
+ return { isBookmarked,
+ setIsBookmarked,
+ toggleBookmark,
+ requireLogin,
+ setRequireLogin,};
+};
diff --git a/src/shared/hooks/events/useEventDetail.ts b/src/shared/hooks/events/useEventDetail.ts
new file mode 100644
index 0000000..6890166
--- /dev/null
+++ b/src/shared/hooks/events/useEventDetail.ts
@@ -0,0 +1,21 @@
+'use client';
+
+import { useQuery } from '@tanstack/react-query';
+import { apiWithToken } from '@/shared/api/instance';
+import type {
+ EventDetailResponse,
+ EventDetail,
+} from '@/shared/types/eventtypes';
+
+const fetchEventDetail = async (eventId: number): Promise
=> {
+ const res = await apiWithToken.get(`/api/events/${eventId}`);
+ return res.data.data;
+};
+
+export const useEventDetail = (eventId: number) => {
+ return useQuery({
+ queryKey: ['eventDetail', eventId],
+ queryFn: () => fetchEventDetail(eventId),
+ enabled: !!eventId,
+ });
+};
diff --git a/src/shared/hooks/events/useEvents.ts b/src/shared/hooks/events/useEvents.ts
new file mode 100644
index 0000000..7ab0bf3
--- /dev/null
+++ b/src/shared/hooks/events/useEvents.ts
@@ -0,0 +1,21 @@
+'use client';
+
+import { useQuery } from '@tanstack/react-query';
+import { fetchEvents } from '@/shared/api/events/event';
+import { formatDateToISO } from '@/shared/utils/date';
+
+export const useEvents = (date?: Date) => {
+ const formattedDate = formatDateToISO(date);
+
+ const { data, isLoading, isError } = useQuery({
+ queryKey: ['events', formattedDate],
+ queryFn: () => fetchEvents(formattedDate!),
+ enabled: !!formattedDate,
+ });
+
+ return {
+ events: data?.data || [],
+ isLoading,
+ isError,
+ };
+};
diff --git a/src/shared/overlay/Overlay.tsx b/src/shared/overlay/Overlay.tsx
index 9f57af9..299d5f5 100644
--- a/src/shared/overlay/Overlay.tsx
+++ b/src/shared/overlay/Overlay.tsx
@@ -9,7 +9,7 @@ const Overlay = ({ onClick, opacity = 30, className }: OverlayProps) => {
{
+ const MAX = 2;
+
+ if (nextEvents.length >= MAX) return nextEvents.slice(0, MAX);
+
+ const emptyItems: RelatedEventOrEmpty[] = Array(MAX - nextEvents.length).fill(
+ { isEmpty: true },
+ );
+
+ return [...nextEvents, ...emptyItems];
+};