🌿 Mori 개발 일지 - Day 20 (2025년 7월 23일)
📆 작성일: 2025년 7월 23일 (수)
🎯 작업 목표: 캘린더 반응형 개선 및 ResultMonthly.jsx 렌더링 문제 해결
✅ 오늘의 진행 내용 요약
항목 |
내용 |
📌 주요 파일 |
CalendarView.jsx , index.css , ResultMonthly.jsx , EmotionChart.jsx , LoadingDonut.jsx |
🛠 핵심 수정 |
반응형 달력 리팩토링, 그래프 중복 렌더링 문제 해결, 실시간 UI 반영 로직 개선 |
🧪 테스트 환경 |
Chrome DevTools, Vite 개발 서버 (Hot Reloading) |
📦 기타 |
전체 페이지 흐름 유지 및 스타일 통일화, 사용성 개선 |
🔧 주요 작업 상세 내역
1. 📅 CalendarView.jsx
반응형 레이아웃 리팩토링
- 기존 문제: 모바일에서 달력이 우측으로 밀리는 현상 발생
- 핵심 해결 방식:
aspect-square
사용해 정사각형 유지
min-width: 0
으로 부모 컨테이너 영향 제거
grid grid-cols-7
구조로 날짜가 정렬되도록 유지
- 수정된 코드 발췌:
<div
key={`${type}-${day}-${i}`}
className={... + " aspect-square"}
style={{ minWidth: 0 }}
>
w-full px-2 max-w-sm mx-auto
를 통해 모바일/데스크탑 모두 중앙 정렬 유지
2. 🎨 index.css
수정
- 글로벌 스타일
body
에 overflow-x: hidden
추가
- 기존의 Tailwind와 충돌하지 않게 유지하며, 의도치 않은 좌우 스크롤 방지
- 커스텀 스크롤바 유지 및 감정 분석 박스에 사용
body {
margin: 0;
overflow-x: hidden;
}
3. 📊 ResultMonthly.jsx
2중 렌더링 현상 분석 및 수정
- 문제: 감정 그래프가 처음엔 제대로 보이나, 두 번째 렌더링 시 1개만 출력됨
- 테스트:
console.log(result.emotion)
으로 로딩 중 2회 출력 확인
- 상태가 두 번 세팅되면서 감정 배열이 덮여씀
- 원인:
summarizeWithGPT()
응답 객체가 매번 다르게 구조화됨 (객체 vs 배열)
- 해결:
const sortedEmotions = Array.isArray(result.emotion)
? result.emotion
: Object.entries(result.emotion || {}).sort(...);
- 이후
setEmotions(sortedEmotions)
로 불변성을 유지한 값만 저장
4. ✅ EmotionChart.jsx
는 그대로 유지
- 중요사항:
ResultDaily.jsx
와 공유하므로 절대 수정하지 않음
- 파싱 구조 문제였음을 확인하고 부모 컴포넌트에서 해결
5. 🌀 LoadingDonut.jsx
문구 누락 이슈
- 초기 로딩 중 “모리가 이번달 일기를 읽고 있어요” 텍스트가 사라짐
- 원인: textLines props 전달 누락
- 해결:
ResultMonthly.jsx
내 조건부 렌더링 구조 수정
if (loading) {
return (
<LoadingDonut
textLines={[
"모리가 이번달 일기를",
"읽고 있어요",
"잠시 후 결과를 알려드릴게요",
]}
/>
);
}
6. 🧼 달력 일기 삭제 시 즉시 UI 반영
- 문제: 일기 삭제 후에도 파란 원(작성된 날짜 표시)이 유지됨
- 원인: 상태 업데이트가 선택된 날짜 정보에만 반영됨. 전체 달력용 날짜는 갱신되지 않음
- 해결:
const updatedDates = await getSummariesByMonth(user.id, currentYear, currentMonth);
setSummaryDates(updatedDates.map((d) => parseInt(d.split("-")[2])));
- 이로 인해 모달에서 일기 삭제 시 즉시 달력 UI가 반영되도록 개선
7. 🔄 전체 페이지 레이아웃 흐름 유지
ResultDaily
, ResultMonthly
, CalendarView
에 동일한 max-width, padding 적용
- 상단 여백, 버튼 스타일, 도넛 위치, 그림자 효과까지 완전 통일
🐛 트러블슈팅 상세 분석
❗️[문제1] 캘린더 반응형이 적용되지 않음
w-10 h-10
은 고정값으로 모바일에선 깨짐
aspect-square
만 사용 시 부모가 비율 못 맞추면 깨짐
- 테스트 흐름:
w-10 h-10
→ 반응형 깨짐
aspect-square
→ 부모 공간 부족 시 깨짐
min-width: 0
조합 → 해결됨
❗️[문제2] EmotionChart가 하나만 보임
summarizeWithGPT()
응답이 첫 번째는 정상, 두 번째는 객체 구조로 전달됨
- 원인 분석:
- 두 번째 응답에서
emotion
필드가 { 행복: 60, 슬픔: 40 }
형태로 옴
- 이걸
setEmotions()
에 넘기면 EmotionChart
에서 map 돌릴 수 없어 하나만 출력됨
- 해결 코드:
const sortedEmotions = Array.isArray(result.emotion)
? result.emotion
: Object.entries(result.emotion || {}).sort(...);
❗️[문제3] useEffect가 두 번 실행되어 setState 중복됨
- React 18에서 StrictMode 사용 중
useEffect
두 번 실행됨
- 원인 확인:
useEffect
로그 찍어보면 두 번 호출됨
- 해결:
loading
플래그로 조건 처리하거나 React Dev 환경에서는 허용
useEffect(() => {
if (!user) return;
fetchData();
}, [user]);
❗️[문제4] 도넛 문구가 안보임
- 로딩 상태 조건부 렌더링에서
textLines
빠짐
- 해결:
ResultMonthly
에서 loading
시 정확한 prop 전달로 복구
✏️ 오늘 작업의 의미
- 모든 화면에서 통일된 경험 제공 (디자인, 구조, 로딩 흐름)
- 달력 및 감정 분석 페이지의 UI, UX 정합성 완성
- 불안정했던 렌더링 순서와 데이터 전달 구조의 근본적인 안정화 완료
🧭 다음 작업 (Day 21, 7월 24일)
- 전체 QA 테스트 (반응형 + 페이지별 이동 + 데이터 흐름)
- console.log 제거 및 경량화
- 최종 Vercel 배포 준비
현재 시연 영상