diff --git a/src/pages/center/MyPage.jsx b/src/pages/center/MyPage.jsx
index 37b725c..4024bbe 100644
--- a/src/pages/center/MyPage.jsx
+++ b/src/pages/center/MyPage.jsx
@@ -16,35 +16,167 @@ import DefaultProfile from '@/assets/images/elder-basic-profile.png';
export default function MyPage() {
const navigate = useNavigate();
const [profileSrc, setProfileSrc] = useState(DefaultProfile);
+ const [performanceMetrics, setPerformanceMetrics] = useState({
+ componentMountTime: null,
+ dataLoadStartTime: null,
+ dataLoadEndTime: null,
+ imageLoadStartTime: null,
+ imageLoadEndTime: null,
+ });
const { data: managerProfile, isLoading, saveManagerProfile } = useManagerProfile();
const { isEditMode, toggleEditMode, setFormData } = useManagerProfileStore();
const setHeaderProps = useHeaderPropsStore((state) => state.setHeaderProps);
const clearHeaderProps = useHeaderPropsStore((state) => state.clearHeaderProps);
+ // 컴포넌트 마운트 시간 측정
useEffect(() => {
+ const mountTime = performance.now();
+ setPerformanceMetrics((prev) => ({ ...prev, componentMountTime: mountTime }));
+ console.log('🚀 MyPage 컴포넌트 마운트 시작');
+
setHeaderProps({ type: 'logo' });
return () => clearHeaderProps();
}, [clearHeaderProps, setHeaderProps]);
- // fallback profile image
+ // React Query 데이터 로딩 상태 추적
useEffect(() => {
+ if (!isLoading && managerProfile) {
+ const dataLoadEndTime = performance.now();
+ setPerformanceMetrics((prev) => ({
+ ...prev,
+ dataLoadEndTime,
+ dataLoadStartTime: prev.dataLoadStartTime || prev.componentMountTime,
+ }));
+
+ const dataLoadTime = (prev) =>
+ prev.dataLoadEndTime && prev.dataLoadStartTime
+ ? (prev.dataLoadEndTime - prev.dataLoadStartTime).toFixed(2)
+ : 'N/A';
+
+ console.log('📊 React Query 데이터 로딩 완료:', {
+ isLoading,
+ hasData: !!managerProfile,
+ dataSource: 'cache', // react-query 캐시에서 가져온 경우
+ loadTime: dataLoadTime(performanceMetrics),
+ });
+ }
+ }, [isLoading, managerProfile, performanceMetrics]);
+
+ // 프로필 이미지 로딩 및 성능 측정
+ useEffect(() => {
+ if (!managerProfile) return;
+
+ const imageLoadStartTime = performance.now();
+ setPerformanceMetrics((prev) => ({ ...prev, imageLoadStartTime }));
+ console.log('🖼️ 프로필 사진 로딩 시작');
+
// if profile image exists, set profileSrc
if (managerProfile?.imgAddress) {
+ console.log('📸 기존 프로필 이미지 사용:', managerProfile.imgAddress);
setProfileSrc(managerProfile.imgAddress);
+ const imageLoadEndTime = performance.now();
+ setPerformanceMetrics((prev) => ({ ...prev, imageLoadEndTime }));
+
+ const imageLoadTime = (imageLoadEndTime - imageLoadStartTime).toFixed(2);
+ console.log(`⚡ 프로필 사진 로딩 완료 (기존 이미지): ${imageLoadTime}ms`);
+
+ // 전체 성능 메트릭 출력
+ logPerformanceMetrics();
} else {
// if profile image doesn't exist, set default profile image
+ console.log('🔄 기본 프로필 이미지 로딩 중...');
fetchDefaultImage()
- .then((url) => setProfileSrc(url))
- .catch(() => setProfileSrc(DefaultProfile));
+ .then((url) => {
+ setProfileSrc(url);
+ const imageLoadEndTime = performance.now();
+ setPerformanceMetrics((prev) => ({ ...prev, imageLoadEndTime }));
+
+ const imageLoadTime = (imageLoadEndTime - imageLoadStartTime).toFixed(2);
+ console.log(`⚡ 프로필 사진 로딩 완료 (기본 이미지): ${imageLoadTime}ms`);
+ console.log('📸 기본 이미지 URL:', url);
+
+ // 전체 성능 메트릭 출력
+ logPerformanceMetrics();
+ })
+ .catch(() => {
+ setProfileSrc(DefaultProfile);
+ const imageLoadEndTime = performance.now();
+ setPerformanceMetrics((prev) => ({ ...prev, imageLoadEndTime }));
+
+ const imageLoadTime = (imageLoadEndTime - imageLoadStartTime).toFixed(2);
+ console.log(`⚡ 프로필 사진 로딩 완료 (fallback): ${imageLoadTime}ms`);
+ console.log('⚠️ 기본 이미지 로딩 실패, fallback 이미지 사용');
+
+ // 전체 성능 메트릭 출력
+ logPerformanceMetrics();
+ });
}
}, [managerProfile]);
+ // 전체 성능 메트릭 로깅 함수
+ const logPerformanceMetrics = () => {
+ const metrics = performanceMetrics;
+ const now = performance.now();
+
+ console.group('📈 전체 성능 메트릭');
+ console.log(
+ '🚀 컴포넌트 마운트 시간:',
+ metrics.componentMountTime ? `${(now - metrics.componentMountTime).toFixed(2)}ms` : 'N/A',
+ );
+ console.log(
+ '📊 데이터 로딩 시간:',
+ metrics.dataLoadEndTime && metrics.dataLoadStartTime
+ ? `${(metrics.dataLoadEndTime - metrics.dataLoadStartTime).toFixed(2)}ms`
+ : 'N/A',
+ );
+ console.log(
+ '🖼️ 이미지 로딩 시간:',
+ metrics.imageLoadEndTime && metrics.imageLoadStartTime
+ ? `${(metrics.imageLoadEndTime - metrics.imageLoadStartTime).toFixed(2)}ms`
+ : 'N/A',
+ );
+ console.log(
+ '⚡ 총 로딩 시간:',
+ metrics.componentMountTime ? `${(now - metrics.componentMountTime).toFixed(2)}ms` : 'N/A',
+ );
+ console.groupEnd();
+ };
+
const handleImgError = useCallback(() => {
+ const startTime = performance.now();
+ console.log('❌ 이미지 로딩 에러 발생, 대체 이미지 로딩 시작');
+
fetchDefaultImage()
- .then((url) => setProfileSrc(url))
- .catch(() => setProfileSrc(DefaultProfile));
- }, []);
+ .then((url) => {
+ setProfileSrc(url);
+ const endTime = performance.now();
+ console.log(`⚡ 대체 이미지 로딩 완료: ${(endTime - startTime).toFixed(2)}ms`);
+ console.log('📸 대체 이미지 URL:', url);
+
+ // 에러 복구 후 성능 메트릭 업데이트
+ setPerformanceMetrics((prev) => ({
+ ...prev,
+ imageLoadEndTime: endTime,
+ imageLoadStartTime: startTime,
+ }));
+ logPerformanceMetrics();
+ })
+ .catch(() => {
+ setProfileSrc(DefaultProfile);
+ const endTime = performance.now();
+ console.log(`⚡ fallback 이미지 로딩 완료: ${(endTime - startTime).toFixed(2)}ms`);
+ console.log('⚠️ 대체 이미지 로딩도 실패, 최종 fallback 이미지 사용');
+
+ // 에러 복구 후 성능 메트릭 업데이트
+ setPerformanceMetrics((prev) => ({
+ ...prev,
+ imageLoadEndTime: endTime,
+ imageLoadStartTime: startTime,
+ }));
+ logPerformanceMetrics();
+ });
+ }, [performanceMetrics]);
// if profile data doesn't exist, redirect to signin page
useEffect(() => {
@@ -123,6 +255,22 @@ export default function MyPage() {
if (isLoading || !managerProfile) return ;
+ console.log('📊 현재 프로필 사진 상태:', {
+ profileSrc,
+ hasManagerProfile: !!managerProfile,
+ hasImgAddress: !!managerProfile?.imgAddress,
+ imgSeq: managerProfile?.imgSeq,
+ reactQueryStatus: {
+ isLoading,
+ isFetching: false, // react-query의 isFetching 상태도 확인 가능
+ dataSource: 'cache', // 캐시에서 가져온 데이터인지 확인
+ },
+ zustandState: {
+ isEditMode,
+ hasFormData: !!useManagerProfileStore.getState().formData,
+ },
+ });
+
return (
{/* profile header */}