diff --git a/app/components/EmotionForecastPopup.tsx b/app/components/EmotionForecastPopup.tsx
new file mode 100644
index 0000000..64b6155
--- /dev/null
+++ b/app/components/EmotionForecastPopup.tsx
@@ -0,0 +1,231 @@
+'use client';
+
+import { useState, useEffect, useRef } from 'react';
+import { motion, AnimatePresence, PanInfo } from 'framer-motion';
+import { useRouter } from 'next/navigation';
+import { CATEGORY_COLORS } from '../types/common';
+
+interface EmotionForecast {
+ timeSlot: string;
+ emotion: string;
+ temperature: number;
+ image: string;
+ category: string;
+}
+
+interface EmotionForecastPopupProps {
+ isOpen: boolean;
+ onClose: () => void;
+ forecasts: EmotionForecast[];
+}
+
+const getEmotionImage = (imageUrl: string) => {
+ // DB에서 받은 이미지 URL을 SVG big 버전으로 변환
+ console.log('원본 이미지 URL:', imageUrl);
+
+ if (!imageUrl) {
+ console.error('이미지 URL이 없습니다');
+ return '/icon/기쁜-big.svg'; // 기본 이미지
+ }
+
+ let processedUrl = imageUrl;
+
+ // PNG를 SVG로 변경하고 big 버전 사용
+
+ // small을 big으로 변경
+
+ console.log('최종 SVG URL:', processedUrl);
+ return processedUrl;
+};
+
+const getTimeSlotLabel = (timeSlot: string) => {
+ const timeLabels: { [key: string]: string } = {
+ 'morning': '아침',
+ 'afternoon': '점심',
+ 'evening': '저녁'
+ };
+
+ return timeLabels[timeSlot] || timeSlot;
+};
+
+const getCategoryColor = (category: string) => {
+ return CATEGORY_COLORS[category as keyof typeof CATEGORY_COLORS] || '#666666';
+};
+
+export default function EmotionForecastPopup({ isOpen, onClose, forecasts }: EmotionForecastPopupProps) {
+ const [currentIndex, setCurrentIndex] = useState(0);
+ const router = useRouter();
+ const [dragDirection, setDragDirection] = useState<'left' | 'right' | null>(null);
+ const [hasSwiped, setHasSwiped] = useState(false);
+
+ const handleClose = () => {
+ onClose();
+ router.push('/baby');
+ };
+
+ useEffect(() => {
+ if (isOpen) {
+ setCurrentIndex(0);
+ setHasSwiped(false);
+ console.log('팝업 열림 - 감정 데이터:', forecasts);
+ }
+ }, [isOpen, forecasts]);
+
+ // 키보드 이벤트 처리
+ useEffect(() => {
+ const handleKeyDown = (event: KeyboardEvent) => {
+ if (!isOpen || forecasts.length <= 1) return;
+
+ switch (event.key) {
+ case 'ArrowLeft':
+ event.preventDefault();
+ setCurrentIndex((prev) => (prev + 1) % forecasts.length);
+ setHasSwiped(true);
+ break;
+ case 'ArrowRight':
+ event.preventDefault();
+ setCurrentIndex((prev) => (prev - 1 + forecasts.length) % forecasts.length);
+ setHasSwiped(true);
+ break;
+ }
+ };
+
+ if (isOpen) {
+ document.addEventListener('keydown', handleKeyDown);
+ }
+
+ return () => {
+ document.removeEventListener('keydown', handleKeyDown);
+ };
+ }, [isOpen, forecasts.length]);
+
+ const nextSlide = () => {
+ setCurrentIndex((prev) => (prev + 1) % forecasts.length);
+ };
+
+ const prevSlide = () => {
+ setCurrentIndex((prev) => (prev - 1 + forecasts.length) % forecasts.length);
+ };
+
+ const handleDragEnd = (event: any, info: PanInfo) => {
+ const threshold = 50; // 슬라이드 임계값
+
+ if (info.offset.x > threshold) {
+ // 오른쪽으로 드래그 - 이전 슬라이드
+ setCurrentIndex((prev) => (prev - 1 + forecasts.length) % forecasts.length);
+ setHasSwiped(true);
+ } else if (info.offset.x < -threshold) {
+ // 왼쪽으로 드래그 - 다음 슬라이드
+ setCurrentIndex((prev) => (prev + 1) % forecasts.length);
+ setHasSwiped(true);
+ }
+
+ setDragDirection(null);
+ };
+
+ if (!isOpen || forecasts.length === 0) return null;
+
+ const currentForecast = forecasts[currentIndex];
+
+ return (
+
+ {TIME_PERIODS[step]?.text} {currentEmotion.emotion.name}으로 {currentEmotion.emotion.temp > 0 ? '+' : ''}{currentEmotion.emotion.temp}° 예정이에요.
+
+ "{currentEmotion.memo}"
+ {
+ console.error('이미지 로딩 실패:', currentForecast.image);
+ console.error('감정 데이터:', currentForecast);
+ // 이미지 로딩 실패 시 기본 이모지 표시
+ e.currentTarget.style.display = 'none';
+ const fallbackDiv = document.createElement('div');
+ fallbackDiv.className = 'w-full h-full flex items-center justify-center text-4xl';
+ fallbackDiv.textContent = '😐';
+ e.currentTarget.parentNode?.appendChild(fallbackDiv);
+ }}
+ onLoad={() => {
+ console.log('이미지 로딩 성공:', currentForecast.image);
+ }}
+ />
+
+ {currentForecast.temperature}° 예정이에요.
+
+
감정 데이터를 찾을 수 없습니다.