From c3a21fbc4ff52ddf662c069a8d7135feb673873f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A4=80=EC=98=81?= Date: Thu, 19 Mar 2026 19:23:43 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20=EB=9D=BC=EC=9A=B0=ED=8A=B8?= =?UTF-8?q?=EB=B3=84=20lazy=20import=20=EB=8F=84=EC=9E=85=20=EB=B0=8F=20sp?= =?UTF-8?q?litting=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.tsx | 205 +++++++++--------- .../common/RouteLoadingFallback.tsx | 20 ++ src/components/layout/index.tsx | 5 +- 3 files changed, 128 insertions(+), 102 deletions(-) create mode 100644 src/components/common/RouteLoadingFallback.tsx diff --git a/src/App.tsx b/src/App.tsx index a701b87..4641721 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,49 +1,52 @@ +import { lazy, Suspense } from 'react'; import * as Sentry from '@sentry/react'; -import { BrowserRouter, Routes, Route } from 'react-router-dom'; +import { BrowserRouter, Route, Routes } from 'react-router-dom'; +import RouteLoadingFallback from '@/components/common/RouteLoadingFallback'; import AuthGuard from './components/auth/AuthGuard'; import ProtectedRoute from './components/auth/ProtectedRoute'; import PublicRoute from './components/auth/PublicRoute'; import Layout from './components/layout'; import Login from './pages/Auth/Login'; -import ConfirmStep from './pages/Auth/SignUp/ConfirmStep'; -import FinishStep from './pages/Auth/SignUp/FinishStep'; -import NameStep from './pages/Auth/SignUp/NameStep'; -import StudentIdStep from './pages/Auth/SignUp/StudentIdStep'; -import TermStep from './pages/Auth/SignUp/TermStep'; -import UniversityStep from './pages/Auth/SignUp/UniversityStep'; -import ChatListPage from './pages/Chat'; -import ChatRoom from './pages/Chat/ChatRoom'; -import ApplicationPage from './pages/Club/Application'; -import ApplyCompletePage from './pages/Club/Application/applyCompletePage'; -import ClubFeePage from './pages/Club/Application/clubFeePage'; -import ClubDetail from './pages/Club/ClubDetail'; -import ClubList from './pages/Club/ClubList'; -import ClubSearch from './pages/Club/ClubSearch'; -import CouncilDetail from './pages/Council/CouncilDetail'; -import CouncilNotice from './pages/Council/CouncilNotice'; -import GuidePage from './pages/Guide'; import Home from './pages/Home'; -import LicensePage from './pages/legal/LicensePage'; -import MarketingPolicyPage from './pages/legal/MarketingPolicyPage'; -import PrivacyPolicyPage from './pages/legal/PrivacyPolicyPage'; -import TermsPage from './pages/legal/TermsPage'; -import ManagedAccount from './pages/Manager/ManagedAccount'; -import ManagedApplicationDetail from './pages/Manager/ManagedApplicationDetail'; -import ManagedApplicationList from './pages/Manager/ManagedApplicationList'; -import ManagedClubDetail from './pages/Manager/ManagedClubDetail'; -import ManagedClubList from './pages/Manager/ManagedClubList'; -import ManagedClubInfo from './pages/Manager/ManagedClubProfile'; -import ManagedMemberApplicationDetail from './pages/Manager/ManagedMemberApplicationDetail'; -import ManagedMemberList from './pages/Manager/ManagedMemberList'; -import ManagedRecruitment from './pages/Manager/ManagedRecruitment'; -import ManagedRecruitmentForm from './pages/Manager/ManagedRecruitmentForm'; -import ManagedRecruitmentWrite from './pages/Manager/ManagedRecruitmentWrite'; import NotFoundPage from './pages/NotFound'; -import Schedule from './pages/Schedule'; import ServerErrorPage from './pages/ServerError'; -import Timer from './pages/Timer'; -import MyPage from './pages/User/MyPage'; -import Profile from './pages/User/Profile'; + +const ConfirmStep = lazy(() => import('./pages/Auth/SignUp/ConfirmStep')); +const FinishStep = lazy(() => import('./pages/Auth/SignUp/FinishStep')); +const NameStep = lazy(() => import('./pages/Auth/SignUp/NameStep')); +const StudentIdStep = lazy(() => import('./pages/Auth/SignUp/StudentIdStep')); +const TermStep = lazy(() => import('./pages/Auth/SignUp/TermStep')); +const UniversityStep = lazy(() => import('./pages/Auth/SignUp/UniversityStep')); +const ChatListPage = lazy(() => import('./pages/Chat')); +const ChatRoom = lazy(() => import('./pages/Chat/ChatRoom')); +const ApplicationPage = lazy(() => import('./pages/Club/Application')); +const ApplyCompletePage = lazy(() => import('./pages/Club/Application/applyCompletePage')); +const ClubFeePage = lazy(() => import('./pages/Club/Application/clubFeePage')); +const ClubDetail = lazy(() => import('./pages/Club/ClubDetail')); +const ClubList = lazy(() => import('./pages/Club/ClubList')); +const ClubSearch = lazy(() => import('./pages/Club/ClubSearch')); +const CouncilDetail = lazy(() => import('./pages/Council/CouncilDetail')); +const CouncilNotice = lazy(() => import('./pages/Council/CouncilNotice')); +const GuidePage = lazy(() => import('./pages/Guide')); +const LicensePage = lazy(() => import('./pages/legal/LicensePage')); +const MarketingPolicyPage = lazy(() => import('./pages/legal/MarketingPolicyPage')); +const PrivacyPolicyPage = lazy(() => import('./pages/legal/PrivacyPolicyPage')); +const TermsPage = lazy(() => import('./pages/legal/TermsPage')); +const ManagedAccount = lazy(() => import('./pages/Manager/ManagedAccount')); +const ManagedApplicationDetail = lazy(() => import('./pages/Manager/ManagedApplicationDetail')); +const ManagedApplicationList = lazy(() => import('./pages/Manager/ManagedApplicationList')); +const ManagedClubDetail = lazy(() => import('./pages/Manager/ManagedClubDetail')); +const ManagedClubInfo = lazy(() => import('./pages/Manager/ManagedClubProfile')); +const ManagedClubList = lazy(() => import('./pages/Manager/ManagedClubList')); +const ManagedMemberApplicationDetail = lazy(() => import('./pages/Manager/ManagedMemberApplicationDetail')); +const ManagedMemberList = lazy(() => import('./pages/Manager/ManagedMemberList')); +const ManagedRecruitment = lazy(() => import('./pages/Manager/ManagedRecruitment')); +const ManagedRecruitmentForm = lazy(() => import('./pages/Manager/ManagedRecruitmentForm')); +const ManagedRecruitmentWrite = lazy(() => import('./pages/Manager/ManagedRecruitmentWrite')); +const Schedule = lazy(() => import('./pages/Schedule')); +const Timer = lazy(() => import('./pages/Timer')); +const MyPage = lazy(() => import('./pages/User/MyPage')); +const Profile = lazy(() => import('./pages/User/Profile')); const SentryRoutes = Sentry.withSentryReactRouterV7Routing(Routes); @@ -51,80 +54,82 @@ function App() { return ( - - }> - }> - } /> - - } /> - } /> - } /> - } /> - } /> + }> + + }> + }> + } /> + + } /> + } /> + } /> + } /> + } /> + - - - }> - } /> - - } /> - }> - - } /> - } /> - } /> - } /> + }> + } /> - + } /> - }> - }> - } /> - - } /> - - } /> - } /> - } /> - } /> - } /> - } /> - } /> - - - } /> - - } /> - } /> + }> + + } /> + } /> + } /> + } /> - }> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - - } /> - } /> + + }> + }> + } /> + + } /> + + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + + } /> + + } /> + } /> + - - } /> - } /> + }> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + } /> + } /> + + + } /> + } /> + - - } /> - } /> - + } /> + } /> + + ); diff --git a/src/components/common/RouteLoadingFallback.tsx b/src/components/common/RouteLoadingFallback.tsx new file mode 100644 index 0000000..352f605 --- /dev/null +++ b/src/components/common/RouteLoadingFallback.tsx @@ -0,0 +1,20 @@ +import { cn } from '@/utils/ts/cn'; + +interface RouteLoadingFallbackProps { + fullScreen?: boolean; +} + +export default function RouteLoadingFallback({ fullScreen = false }: RouteLoadingFallbackProps) { + return ( +
+
+
+ ); +} diff --git a/src/components/layout/index.tsx b/src/components/layout/index.tsx index 6243275..9c6c22e 100644 --- a/src/components/layout/index.tsx +++ b/src/components/layout/index.tsx @@ -1,5 +1,6 @@ import { Suspense, type CSSProperties } from 'react'; import { Outlet, useLocation } from 'react-router-dom'; +import RouteLoadingFallback from '@/components/common/RouteLoadingFallback'; import { cn } from '@/utils/ts/cn'; import BottomNav from './BottomNav'; import Header from './Header'; @@ -27,11 +28,11 @@ export default function Layout({ showBottomNav = false, contentClassName }: Layo return (
{hasHeader &&
} - + }>
Date: Fri, 20 Mar 2026 09:37:01 +0900 Subject: [PATCH 2/3] Perf/02 auth init (#197) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: 인증 불필요 페이지 검증 제거 * refactor: 인증 필요 페이지 로직 수정 * Perf/03 home data request shaping (#198) * refactor: 채팅 hook 분리 및 호출 시점 정리 * refactor: 총동 공지사항 조회 수 수정 * Perf/04 home lighthouse (#199) * chore: svg -> png 변환 및 리사이징 * chore: 번들 분석 라이브러리 추가 * refactor: 캐러셀 이미지 지연 로드 적요 --- package.json | 2 + pnpm-lock.yaml | 216 ++++++++++++++++++ src/assets/image/chat-cat-header.png | Bin 0 -> 7444 bytes src/assets/image/chat-cat-login.png | Bin 0 -> 66459 bytes src/assets/svg/chat-cat.svg | 9 - src/components/auth/AuthGuard.tsx | 19 +- .../layout/Header/components/InfoHeader.tsx | 21 +- .../Header/components/NotificationBell.tsx | 15 +- src/pages/Auth/Login/index.tsx | 13 +- src/pages/Chat/hooks/useUnreadChatCount.ts | 52 +++++ .../CouncilDetail/hooks/useGetCouncilInfo.ts | 1 + .../Home/components/CouncilNoticeSection.tsx | 6 +- .../Home/components/InfiniteClubCarousel.tsx | 12 + .../Home/components/RecommendedClubCard.tsx | 16 +- .../Home/hooks/useGetHomeCouncilNotices.ts | 14 ++ src/stores/authStore.ts | 78 +++++-- vite.config.ts | 18 ++ 17 files changed, 451 insertions(+), 41 deletions(-) create mode 100644 src/assets/image/chat-cat-header.png create mode 100644 src/assets/image/chat-cat-login.png delete mode 100644 src/assets/svg/chat-cat.svg create mode 100644 src/pages/Chat/hooks/useUnreadChatCount.ts create mode 100644 src/pages/Home/hooks/useGetHomeCouncilNotices.ts diff --git a/package.json b/package.json index 8eded31..8df492b 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "scripts": { "start": "vite", "build": "tsc -b && vite build", + "build:analyze:staging": "ANALYZE=true tsc -b && ANALYZE=true vite build --mode staging", "lint": "eslint .", "preview": "vite preview" }, @@ -42,6 +43,7 @@ "globals": "^16.5.0", "prettier": "^3.6.2", "prettier-plugin-tailwindcss": "^0.7.1", + "rollup-plugin-visualizer": "^7.0.1", "typescript": "~5.9.3", "typescript-eslint": "^8.46.4", "vite": "^7.2.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d37a984..7705b62 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -96,6 +96,9 @@ importers: prettier-plugin-tailwindcss: specifier: ^0.7.1 version: 0.7.1(prettier@3.6.2) + rollup-plugin-visualizer: + specifier: ^7.0.1 + version: 7.0.1(rollup@4.53.3) typescript: specifier: ~5.9.3 version: 5.9.3 @@ -1077,10 +1080,18 @@ packages: ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + ansi-regex@6.2.2: + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + engines: {node: '>=12'} + ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} + engines: {node: '>=12'} + argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -1160,6 +1171,10 @@ packages: buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + bundle-name@4.1.0: + resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} + engines: {node: '>=18'} + call-bind-apply-helpers@1.0.2: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} @@ -1187,6 +1202,10 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} + cliui@9.0.1: + resolution: {integrity: sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==} + engines: {node: '>=20'} + clsx@2.1.1: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} @@ -1259,10 +1278,22 @@ packages: deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + default-browser-id@5.0.1: + resolution: {integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==} + engines: {node: '>=18'} + + default-browser@5.5.0: + resolution: {integrity: sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==} + engines: {node: '>=18'} + define-data-property@1.1.4: resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} engines: {node: '>= 0.4'} + define-lazy-prop@3.0.0: + resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} + engines: {node: '>=12'} + define-properties@1.2.1: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} @@ -1289,6 +1320,9 @@ packages: electron-to-chromium@1.5.259: resolution: {integrity: sha512-I+oLXgpEJzD6Cwuwt1gYjxsDmu/S/Kd41mmLA3O+/uH2pFRO/DvOjUyGozL8j3KeLV6WyZ7ssPwELMsXCcsJAQ==} + emoji-regex@10.6.0: + resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} + enhanced-resolve@5.18.3: resolution: {integrity: sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==} engines: {node: '>=10.13.0'} @@ -1557,6 +1591,14 @@ packages: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-east-asian-width@1.5.0: + resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==} + engines: {node: '>=18'} + get-intrinsic@1.3.0: resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} @@ -1701,6 +1743,11 @@ packages: resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} engines: {node: '>= 0.4'} + is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -1717,6 +1764,15 @@ packages: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} + is-in-ssh@1.0.0: + resolution: {integrity: sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw==} + engines: {node: '>=20'} + + is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + is-map@2.0.3: resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} engines: {node: '>= 0.4'} @@ -1769,6 +1825,10 @@ packages: resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} engines: {node: '>= 0.4'} + is-wsl@3.1.1: + resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==} + engines: {node: '>=16'} + isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} @@ -2021,6 +2081,10 @@ packages: resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} engines: {node: '>= 0.4'} + open@11.0.0: + resolution: {integrity: sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw==} + engines: {node: '>=20'} + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -2083,6 +2147,10 @@ packages: resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} + powershell-utils@0.1.0: + resolution: {integrity: sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==} + engines: {node: '>=20'} + prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -2229,11 +2297,28 @@ packages: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + rollup-plugin-visualizer@7.0.1: + resolution: {integrity: sha512-UJUT4+1Ho4OcWmPYU3sYXgUqI8B8Ayfe06MX7y0qCJ1K8aGoKtR/NDd/2nZqM7ADkrzny+I99Ul7GgyoiVNAgg==} + engines: {node: '>=22'} + hasBin: true + peerDependencies: + rolldown: 1.x || ^1.0.0-beta || ^1.0.0-rc + rollup: 2.x || 3.x || 4.x + peerDependenciesMeta: + rolldown: + optional: true + rollup: + optional: true + rollup@4.53.3: resolution: {integrity: sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + run-applescript@7.1.0: + resolution: {integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==} + engines: {node: '>=18'} + run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -2314,6 +2399,10 @@ packages: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} + source-map@0.7.6: + resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} + engines: {node: '>= 12'} + stable-hash-x@0.2.0: resolution: {integrity: sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==} engines: {node: '>=12.0.0'} @@ -2322,6 +2411,10 @@ packages: resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} engines: {node: '>= 0.4'} + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + string.prototype.matchall@4.0.12: resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} engines: {node: '>= 0.4'} @@ -2341,6 +2434,10 @@ packages: resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} engines: {node: '>= 0.4'} + strip-ansi@7.2.0: + resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} + engines: {node: '>=12'} + strip-bom@3.0.0: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} @@ -2529,9 +2626,29 @@ packages: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} + wrap-ansi@9.0.2: + resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} + engines: {node: '>=18'} + + wsl-utils@0.3.1: + resolution: {integrity: sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg==} + engines: {node: '>=20'} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + yargs-parser@22.0.0: + resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==} + engines: {node: ^20.19.0 || ^22.12.0 || >=23} + + yargs@18.0.0: + resolution: {integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=23} + yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -3435,10 +3552,14 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 + ansi-regex@6.2.2: {} + ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 + ansi-styles@6.2.3: {} + argparse@2.0.1: {} array-buffer-byte-length@1.0.2: @@ -3552,6 +3673,10 @@ snapshots: buffer-from@1.1.2: optional: true + bundle-name@4.1.0: + dependencies: + run-applescript: 7.1.0 + call-bind-apply-helpers@1.0.2: dependencies: es-errors: 1.3.0 @@ -3580,6 +3705,12 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 + cliui@9.0.1: + dependencies: + string-width: 7.2.0 + strip-ansi: 7.2.0 + wrap-ansi: 9.0.2 + clsx@2.1.1: {} color-convert@2.0.1: @@ -3642,12 +3773,21 @@ snapshots: deep-is@0.1.4: {} + default-browser-id@5.0.1: {} + + default-browser@5.5.0: + dependencies: + bundle-name: 4.1.0 + default-browser-id: 5.0.1 + define-data-property@1.1.4: dependencies: es-define-property: 1.0.1 es-errors: 1.3.0 gopd: 1.2.0 + define-lazy-prop@3.0.0: {} + define-properties@1.2.1: dependencies: define-data-property: 1.1.4 @@ -3675,6 +3815,8 @@ snapshots: electron-to-chromium@1.5.259: {} + emoji-regex@10.6.0: {} + enhanced-resolve@5.18.3: dependencies: graceful-fs: 4.2.11 @@ -4078,6 +4220,10 @@ snapshots: gensync@1.0.0-beta.2: {} + get-caller-file@2.0.5: {} + + get-east-asian-width@1.5.0: {} + get-intrinsic@1.3.0: dependencies: call-bind-apply-helpers: 1.0.2 @@ -4233,6 +4379,8 @@ snapshots: call-bound: 1.0.4 has-tostringtag: 1.0.2 + is-docker@3.0.0: {} + is-extglob@2.1.1: {} is-finalizationregistry@1.1.1: @@ -4251,6 +4399,12 @@ snapshots: dependencies: is-extglob: 2.1.1 + is-in-ssh@1.0.0: {} + + is-inside-container@1.0.0: + dependencies: + is-docker: 3.0.0 + is-map@2.0.3: {} is-negative-zero@2.0.3: {} @@ -4301,6 +4455,10 @@ snapshots: call-bound: 1.0.4 get-intrinsic: 1.3.0 + is-wsl@3.1.1: + dependencies: + is-inside-container: 1.0.0 + isarray@2.0.5: {} isexe@2.0.0: {} @@ -4515,6 +4673,15 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.1.1 + open@11.0.0: + dependencies: + default-browser: 5.5.0 + define-lazy-prop: 3.0.0 + is-in-ssh: 1.0.0 + is-inside-container: 1.0.0 + powershell-utils: 0.1.0 + wsl-utils: 0.3.1 + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -4576,6 +4743,8 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 + powershell-utils@0.1.0: {} + prelude-ls@1.2.1: {} prettier-linter-helpers@1.0.0: @@ -4665,6 +4834,15 @@ snapshots: reusify@1.1.0: {} + rollup-plugin-visualizer@7.0.1(rollup@4.53.3): + dependencies: + open: 11.0.0 + picomatch: 4.0.3 + source-map: 0.7.6 + yargs: 18.0.0 + optionalDependencies: + rollup: 4.53.3 + rollup@4.53.3: dependencies: '@types/estree': 1.0.8 @@ -4693,6 +4871,8 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.53.3 fsevents: 2.3.3 + run-applescript@7.1.0: {} + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 @@ -4796,6 +4976,8 @@ snapshots: source-map@0.6.1: optional: true + source-map@0.7.6: {} + stable-hash-x@0.2.0: {} stop-iteration-iterator@1.1.0: @@ -4803,6 +4985,12 @@ snapshots: es-errors: 1.3.0 internal-slot: 1.1.0 + string-width@7.2.0: + dependencies: + emoji-regex: 10.6.0 + get-east-asian-width: 1.5.0 + strip-ansi: 7.2.0 + string.prototype.matchall@4.0.12: dependencies: call-bind: 1.0.8 @@ -4847,6 +5035,10 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.1.1 + strip-ansi@7.2.0: + dependencies: + ansi-regex: 6.2.2 + strip-bom@3.0.0: {} strip-json-comments@3.1.1: {} @@ -5074,8 +5266,32 @@ snapshots: word-wrap@1.2.5: {} + wrap-ansi@9.0.2: + dependencies: + ansi-styles: 6.2.3 + string-width: 7.2.0 + strip-ansi: 7.2.0 + + wsl-utils@0.3.1: + dependencies: + is-wsl: 3.1.1 + powershell-utils: 0.1.0 + + y18n@5.0.8: {} + yallist@3.1.1: {} + yargs-parser@22.0.0: {} + + yargs@18.0.0: + dependencies: + cliui: 9.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + string-width: 7.2.0 + y18n: 5.0.8 + yargs-parser: 22.0.0 + yocto-queue@0.1.0: {} zod-validation-error@4.0.2(zod@4.1.12): diff --git a/src/assets/image/chat-cat-header.png b/src/assets/image/chat-cat-header.png new file mode 100644 index 0000000000000000000000000000000000000000..550a566696b8942f6b822d7c0d0e105b3e8d487a GIT binary patch literal 7444 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 - - - - - - - - diff --git a/src/components/auth/AuthGuard.tsx b/src/components/auth/AuthGuard.tsx index 2456b8c..1ee1008 100644 --- a/src/components/auth/AuthGuard.tsx +++ b/src/components/auth/AuthGuard.tsx @@ -7,10 +7,26 @@ interface AuthGuardProps { children: ReactNode; } +const PROTECTED_ROUTE_PREFIXES = [ + '/home', + '/mypage', + '/timer', + '/clubs', + '/schedule', + '/profile', + '/council', + '/chats', +]; + +function isProtectedPath(pathname: string) { + return PROTECTED_ROUTE_PREFIXES.some((prefix) => pathname === prefix || pathname.startsWith(`${prefix}/`)); +} + function AuthGuard({ children }: AuthGuardProps) { const { pathname } = useLocation(); const { isLoading, initialize } = useAuthStore(); const shouldSkipInitialize = pathname === SERVER_ERROR_PATH; + const shouldBlockWhileInitializing = !shouldSkipInitialize && isProtectedPath(pathname); useEffect(() => { if (shouldSkipInitialize) return; @@ -18,7 +34,8 @@ function AuthGuard({ children }: AuthGuardProps) { initialize(); }, [initialize, shouldSkipInitialize]); - if (isLoading && !shouldSkipInitialize) { + // Public routes can paint immediately while auth restore runs in the background. + if (isLoading && shouldBlockWhileInitializing) { return (
로딩 중… diff --git a/src/components/layout/Header/components/InfoHeader.tsx b/src/components/layout/Header/components/InfoHeader.tsx index b3937b0..a8b8668 100644 --- a/src/components/layout/Header/components/InfoHeader.tsx +++ b/src/components/layout/Header/components/InfoHeader.tsx @@ -1,19 +1,28 @@ import { useLocation } from 'react-router-dom'; -import { useMyInfo } from '@/pages/User/Profile/hooks/useMyInfo'; +import { useAuthStore } from '@/stores/authStore'; import NotificationBell from './NotificationBell'; function InfoHeader() { const { pathname } = useLocation(); - const { myInfo } = useMyInfo(); + const user = useAuthStore((state) => state.user); const showChatTooltip = pathname === '/home'; return (
-
{myInfo.universityName}
-
- {myInfo.name} {myInfo.studentNumber} -
+ {user ? ( + <> +
{user.universityName}
+
+ {user.name} {user.studentNumber} +
+ + ) : ( + <> +
+
+ + )}
diff --git a/src/components/layout/Header/components/NotificationBell.tsx b/src/components/layout/Header/components/NotificationBell.tsx index 8e3c1ef..e352d02 100644 --- a/src/components/layout/Header/components/NotificationBell.tsx +++ b/src/components/layout/Header/components/NotificationBell.tsx @@ -1,8 +1,8 @@ import { useState } from 'react'; import { Link } from 'react-router-dom'; -import ChatCatIcon from '@/assets/svg/chat-cat.svg'; +import chatCatHeaderImage from '@/assets/image/chat-cat-header.png'; import MegaphoneSmIcon from '@/assets/svg/megaphone-sm.svg'; -import useChat from '@/pages/Chat/hooks/useChat'; +import useUnreadChatCount from '@/pages/Chat/hooks/useUnreadChatCount'; import { cn } from '@/utils/ts/cn'; const CHAT_TOOLTIP_DISMISSED_STORAGE_KEY = 'chat-tooltip-dismissed:v1'; @@ -24,7 +24,7 @@ interface NotificationBellProps { } function NotificationBell({ showTooltip = false }: NotificationBellProps) { - const { totalUnreadCount } = useChat(); + const { totalUnreadCount } = useUnreadChatCount(); const [isTooltipDismissed, setIsTooltipDismissed] = useState(readChatTooltipDismissed); const shouldShowTooltip = showTooltip && !isTooltipDismissed; @@ -51,7 +51,14 @@ function NotificationBell({ showTooltip = false }: NotificationBellProps) { onClick={handleChatButtonClick} className={cn('relative inline-flex', shouldShowTooltip && 'chat-tooltip-anchor')} > - + {totalUnreadCount > 0 ? ( {totalUnreadCount > 99 ? '99+' : totalUnreadCount} diff --git a/src/pages/Auth/Login/index.tsx b/src/pages/Auth/Login/index.tsx index 6de7fd1..b42f7f8 100644 --- a/src/pages/Auth/Login/index.tsx +++ b/src/pages/Auth/Login/index.tsx @@ -1,5 +1,5 @@ +import chatCatLoginImage from '@/assets/image/chat-cat-login.png'; import AppleFigmaIcon from '@/assets/svg/apple-figma.svg'; -import ChatCatIcon from '@/assets/svg/chat-cat.svg'; import GoogleIcon from '@/assets/svg/google.svg'; import KakaoIcon from '@/assets/svg/kakao.svg'; import NaverIcon from '@/assets/svg/naver.svg'; @@ -66,7 +66,16 @@ function Login() {
- +
diff --git a/src/pages/Chat/hooks/useUnreadChatCount.ts b/src/pages/Chat/hooks/useUnreadChatCount.ts new file mode 100644 index 0000000..d35e8c8 --- /dev/null +++ b/src/pages/Chat/hooks/useUnreadChatCount.ts @@ -0,0 +1,52 @@ +import { useEffect, useState } from 'react'; +import { useQuery } from '@tanstack/react-query'; +import { getChatRooms } from '@/apis/chat'; +import { chatQueryKeys } from '@/pages/Chat/hooks/useChat'; + +const UNREAD_CHAT_COUNT_REFETCH_INTERVAL = 5_000; + +function useUnreadChatCount() { + const [isEnabled, setIsEnabled] = useState(false); + + useEffect(() => { + if (typeof window === 'undefined') { + return; + } + + const requestIdleCallback = window.requestIdleCallback; + + if (typeof requestIdleCallback === 'function') { + const idleCallbackId = requestIdleCallback(() => { + setIsEnabled(true); + }); + + return () => { + window.cancelIdleCallback(idleCallbackId); + }; + } + + const timeoutId = window.setTimeout(() => { + setIsEnabled(true); + }, 0); + + return () => { + window.clearTimeout(timeoutId); + }; + }, []); + + const { data } = useQuery({ + queryKey: chatQueryKeys.rooms(), + queryFn: getChatRooms, + enabled: isEnabled, + staleTime: UNREAD_CHAT_COUNT_REFETCH_INTERVAL, + refetchInterval: isEnabled ? UNREAD_CHAT_COUNT_REFETCH_INTERVAL : false, + }); + + const totalUnreadCount = data?.rooms.reduce((sum, room) => sum + room.unreadCount, 0) ?? 0; + + return { + totalUnreadCount, + }; +} + +export default useUnreadChatCount; diff --git a/src/pages/Council/CouncilDetail/hooks/useGetCouncilInfo.ts b/src/pages/Council/CouncilDetail/hooks/useGetCouncilInfo.ts index b7140fb..8b644b4 100644 --- a/src/pages/Council/CouncilDetail/hooks/useGetCouncilInfo.ts +++ b/src/pages/Council/CouncilDetail/hooks/useGetCouncilInfo.ts @@ -5,6 +5,7 @@ export const councilQueryKeys = { all: ['council'], info: () => [...councilQueryKeys.all, 'info'], notices: (limit: number) => [...councilQueryKeys.all, 'notices', limit], + noticesPreview: (limit: number) => [...councilQueryKeys.all, 'noticesPreview', limit], noticeDetail: (noticeId: number) => [...councilQueryKeys.all, 'noticeDetail', noticeId], }; diff --git a/src/pages/Home/components/CouncilNoticeSection.tsx b/src/pages/Home/components/CouncilNoticeSection.tsx index f3f38f8..d7f5757 100644 --- a/src/pages/Home/components/CouncilNoticeSection.tsx +++ b/src/pages/Home/components/CouncilNoticeSection.tsx @@ -1,8 +1,8 @@ import Card from '@/components/common/Card'; -import { useCouncilNotice } from '@/pages/Club/ClubDetail/hooks/useCouncilNotices'; import CouncilNoticeCard from '@/pages/Home/components/CouncilNoticeCard'; import SectionErrorFallback from '@/pages/Home/components/SectionErrorFallback'; import SectionTitle from '@/pages/Home/components/SectionTitle'; +import { useGetHomeCouncilNotices } from '@/pages/Home/hooks/useGetHomeCouncilNotices'; const COUNCIL_NOTICE_PARAMS = { limit: 3 } as const; @@ -38,8 +38,8 @@ export function CouncilNoticeSectionErrorFallback() { } function CouncilNoticeSection() { - const { data: councilNoticeData } = useCouncilNotice(COUNCIL_NOTICE_PARAMS); - const allNotices = councilNoticeData.pages.flatMap((page) => page.councilNotices); + const { data: councilNoticeData } = useGetHomeCouncilNotices(COUNCIL_NOTICE_PARAMS); + const allNotices = councilNoticeData.councilNotices; return (
diff --git a/src/pages/Home/components/InfiniteClubCarousel.tsx b/src/pages/Home/components/InfiniteClubCarousel.tsx index 9af0672..899d763 100644 --- a/src/pages/Home/components/InfiniteClubCarousel.tsx +++ b/src/pages/Home/components/InfiniteClubCarousel.tsx @@ -9,6 +9,16 @@ interface InfiniteClubCarouselProps { clubs: HomeClubCardItem[]; } +function isPriorityImage(index: number, clubsLength: number, shouldLoop: boolean) { + if (!shouldLoop) { + return index < 2; + } + + const middleSegmentStartIndex = clubsLength; + + return index >= middleSegmentStartIndex - 1 && index <= middleSegmentStartIndex + 1; +} + function InfiniteClubCarousel({ clubs }: InfiniteClubCarouselProps) { const { displayClubs, @@ -45,6 +55,8 @@ function InfiniteClubCarousel({ clubs }: InfiniteClubCarouselProps) { club={club} className="w-full" ariaHidden={isDuplicate} + imageFetchPriority={isPriorityImage(index, clubs.length, shouldLoop) ? 'auto' : 'low'} + imageLoading={isPriorityImage(index, clubs.length, shouldLoop) ? 'eager' : 'lazy'} tabIndex={isDuplicate ? -1 : 0} />
diff --git a/src/pages/Home/components/RecommendedClubCard.tsx b/src/pages/Home/components/RecommendedClubCard.tsx index f855175..e774a05 100644 --- a/src/pages/Home/components/RecommendedClubCard.tsx +++ b/src/pages/Home/components/RecommendedClubCard.tsx @@ -7,9 +7,18 @@ interface RecommendedClubCardProps { className?: string; tabIndex?: number; ariaHidden?: boolean; + imageLoading?: 'eager' | 'lazy'; + imageFetchPriority?: 'auto' | 'high' | 'low'; } -function RecommendedClubCard({ club, className, tabIndex, ariaHidden = false }: RecommendedClubCardProps) { +function RecommendedClubCard({ + club, + className, + tabIndex, + ariaHidden = false, + imageLoading = 'lazy', + imageFetchPriority = 'low', +}: RecommendedClubCardProps) { return (
diff --git a/src/pages/Home/hooks/useGetHomeCouncilNotices.ts b/src/pages/Home/hooks/useGetHomeCouncilNotices.ts new file mode 100644 index 0000000..95ce540 --- /dev/null +++ b/src/pages/Home/hooks/useGetHomeCouncilNotices.ts @@ -0,0 +1,14 @@ +import { useSuspenseQuery } from '@tanstack/react-query'; +import { getCouncilNotice } from '@/apis/council'; +import { councilQueryKeys } from '@/pages/Council/CouncilDetail/hooks/useGetCouncilInfo'; + +interface UseGetHomeCouncilNoticesParams { + limit?: number; +} + +export const useGetHomeCouncilNotices = ({ limit = 3 }: UseGetHomeCouncilNoticesParams = {}) => { + return useSuspenseQuery({ + queryKey: councilQueryKeys.noticesPreview(limit), + queryFn: () => getCouncilNotice({ page: 1, limit }), + }); +}; diff --git a/src/stores/authStore.ts b/src/stores/authStore.ts index fb8b7e3..7637e8a 100644 --- a/src/stores/authStore.ts +++ b/src/stores/authStore.ts @@ -2,6 +2,9 @@ import { create } from 'zustand'; import { getMyInfo, refreshAccessToken } from '@/apis/auth'; import type { MyInfoResponse } from '@/apis/auth/entity'; +let initializePromise: Promise | null = null; +let hydrateUserPromise: Promise | null = null; + interface AuthState { user: MyInfoResponse | null; accessToken: string | null; @@ -21,29 +24,70 @@ export const useAuthStore = create((set, get) => ({ isLoading: true, initialize: async () => { - if (get().user) { - set({ isLoading: false }); + const { accessToken, isAuthenticated, user } = get(); + + if (user) { + set({ isAuthenticated: true, isLoading: false }); return; } - try { - const accessToken = await refreshAccessToken(); - set({ accessToken }); + const hydrateUser = async (nextAccessToken: string) => { + if (hydrateUserPromise) return hydrateUserPromise; - const user = await getMyInfo(); + hydrateUserPromise = (async () => { + try { + const nextUser = await getMyInfo(); - set({ user, isAuthenticated: true, isLoading: false }); + if (get().accessToken !== nextAccessToken) return; - try { - if (window.ReactNativeWebView) { - window.ReactNativeWebView.postMessage(JSON.stringify({ type: 'LOGIN_COMPLETE', accessToken })); + set({ user: nextUser }); + + try { + if (window.ReactNativeWebView) { + window.ReactNativeWebView.postMessage( + JSON.stringify({ type: 'LOGIN_COMPLETE', accessToken: nextAccessToken }) + ); + } + } catch { + // 브릿지 전달 실패가 인증 성공 상태를 롤백시키지 않도록 무시 + } + } catch { + if (get().accessToken !== nextAccessToken) return; + + set({ user: null, accessToken: null, isAuthenticated: false }); + } finally { + hydrateUserPromise = null; } + })(); + + return hydrateUserPromise; + }; + + if (isAuthenticated && accessToken) { + set({ isLoading: false }); + void hydrateUser(accessToken); + return; + } + + if (initializePromise) { + return initializePromise; + } + + initializePromise = (async () => { + try { + const nextAccessToken = await refreshAccessToken(); + + // Open protected routes as soon as the access token is restored. + set({ accessToken: nextAccessToken, isAuthenticated: true, isLoading: false }); + void hydrateUser(nextAccessToken); } catch { - // 브릿지 전달 실패가 인증 성공 상태를 롤백시키지 않도록 무시 + set({ user: null, accessToken: null, isAuthenticated: false, isLoading: false }); + } finally { + initializePromise = null; } - } catch { - set({ user: null, accessToken: null, isAuthenticated: false, isLoading: false }); - } + })(); + + return initializePromise; }, setUser: (user) => set({ user, isAuthenticated: !!user, isLoading: false }), @@ -52,5 +96,9 @@ export const useAuthStore = create((set, get) => ({ getAccessToken: () => get().accessToken, - clearAuth: () => set({ user: null, accessToken: null, isAuthenticated: false, isLoading: false }), + clearAuth: () => { + initializePromise = null; + hydrateUserPromise = null; + set({ user: null, accessToken: null, isAuthenticated: false, isLoading: false }); + }, })); diff --git a/vite.config.ts b/vite.config.ts index 12ef5ec..9d46bc0 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,6 +1,7 @@ import { sentryVitePlugin } from '@sentry/vite-plugin'; import tailwindcss from '@tailwindcss/vite'; import react from '@vitejs/plugin-react'; +import { visualizer } from 'rollup-plugin-visualizer'; import { defineConfig } from 'vite'; import svgr from 'vite-plugin-svgr'; @@ -9,11 +10,25 @@ const sentryProject = process.env.SENTRY_PROJECT; const sentryAuthToken = process.env.SENTRY_AUTH_TOKEN; const sentryRelease = process.env.SENTRY_RELEASE; +const shouldAnalyzeBundle = process.env.ANALYZE === 'true'; const shouldUploadSourcemaps = Boolean(sentryOrg && sentryProject && sentryAuthToken); // https://vite.dev/config/ export default defineConfig({ build: { + rollupOptions: { + plugins: shouldAnalyzeBundle + ? [ + visualizer({ + brotliSize: true, + filename: 'docs/perf/assets/bundle-stats.html', + gzipSize: true, + open: false, + template: 'treemap', + }), + ] + : [], + }, sourcemap: shouldUploadSourcemaps ? 'hidden' : false, }, plugins: [ @@ -47,4 +62,7 @@ export default defineConfig({ server: { port: 3000, }, + preview: { + port: 3000, + }, }); From 2ba2c102078ec7de9f515296914949bd3121cda6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A4=80=EC=98=81?= Date: Fri, 20 Mar 2026 10:14:07 +0900 Subject: [PATCH 3/3] =?UTF-8?q?refactor:=20=EC=BD=94=EB=93=9C=20=EB=A6=AC?= =?UTF-8?q?=EB=B7=B0=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../layout/Header/components/InfoHeader.tsx | 2 +- src/components/layout/index.tsx | 22 ++--- .../Home/components/InfiniteClubCarousel.tsx | 16 +++- src/stores/authStore.ts | 90 +++++++++++-------- 4 files changed, 79 insertions(+), 51 deletions(-) diff --git a/src/components/layout/Header/components/InfoHeader.tsx b/src/components/layout/Header/components/InfoHeader.tsx index a8b8668..b64b4b7 100644 --- a/src/components/layout/Header/components/InfoHeader.tsx +++ b/src/components/layout/Header/components/InfoHeader.tsx @@ -20,7 +20,7 @@ function InfoHeader() { ) : ( <>
-
+
)}
diff --git a/src/components/layout/index.tsx b/src/components/layout/index.tsx index 9c6c22e..2927ffd 100644 --- a/src/components/layout/index.tsx +++ b/src/components/layout/index.tsx @@ -28,18 +28,18 @@ export default function Layout({ showBottomNav = false, contentClassName }: Layo return (
{hasHeader &&
} - }> -
+
+ }> -
- + +
{showBottomNav && }
); diff --git a/src/pages/Home/components/InfiniteClubCarousel.tsx b/src/pages/Home/components/InfiniteClubCarousel.tsx index 899d763..fde6bba 100644 --- a/src/pages/Home/components/InfiniteClubCarousel.tsx +++ b/src/pages/Home/components/InfiniteClubCarousel.tsx @@ -10,13 +10,20 @@ interface InfiniteClubCarouselProps { } function isPriorityImage(index: number, clubsLength: number, shouldLoop: boolean) { + const visibleCount = 2; + if (!shouldLoop) { - return index < 2; + return index < visibleCount; } const middleSegmentStartIndex = clubsLength; + const middleSegmentVisibleRadius = 1; + const isInInitialVisibleRange = index < visibleCount; + const isInMiddleVisibleRange = + index >= middleSegmentStartIndex - middleSegmentVisibleRadius && + index <= middleSegmentStartIndex + middleSegmentVisibleRadius; - return index >= middleSegmentStartIndex - 1 && index <= middleSegmentStartIndex + 1; + return isInInitialVisibleRange || isInMiddleVisibleRange; } function InfiniteClubCarousel({ clubs }: InfiniteClubCarouselProps) { @@ -44,6 +51,7 @@ function InfiniteClubCarousel({ clubs }: InfiniteClubCarouselProps) {
{displayClubs.map(({ club, key }, index) => { const isDuplicate = shouldLoop && (index < clubs.length || index >= clubs.length * 2); + const isPriority = isPriorityImage(index, clubs.length, shouldLoop); return (
diff --git a/src/stores/authStore.ts b/src/stores/authStore.ts index 7637e8a..a21577c 100644 --- a/src/stores/authStore.ts +++ b/src/stores/authStore.ts @@ -5,6 +5,55 @@ import type { MyInfoResponse } from '@/apis/auth/entity'; let initializePromise: Promise | null = null; let hydrateUserPromise: Promise | null = null; +const isAccessTokenExpired = (accessToken: string | null) => { + if (!accessToken) return true; + + const [, payload] = accessToken.split('.'); + if (!payload) return true; + + try { + const normalizedPayload = payload.replace(/-/g, '+').replace(/_/g, '/'); + const padding = '='.repeat((4 - (normalizedPayload.length % 4)) % 4); + const parsedPayload = JSON.parse(atob(`${normalizedPayload}${padding}`)) as { exp?: number }; + + return typeof parsedPayload.exp !== 'number' || parsedPayload.exp * 1000 <= Date.now(); + } catch { + return true; + } +}; + +const hydrateUser = async (nextAccessToken: string) => { + if (hydrateUserPromise) return hydrateUserPromise; + + hydrateUserPromise = (async () => { + try { + const nextUser = await getMyInfo(); + + if (useAuthStore.getState().accessToken !== nextAccessToken) return; + + useAuthStore.setState({ user: nextUser }); + + try { + if (window.ReactNativeWebView) { + window.ReactNativeWebView.postMessage( + JSON.stringify({ type: 'LOGIN_COMPLETE', accessToken: nextAccessToken }) + ); + } + } catch { + // 브릿지 전달 실패가 인증 성공 상태를 롤백시키지 않도록 무시 + } + } catch { + if (useAuthStore.getState().accessToken !== nextAccessToken) return; + + useAuthStore.setState({ user: null, accessToken: null, isAuthenticated: false }); + } finally { + hydrateUserPromise = null; + } + })(); + + return hydrateUserPromise; +}; + interface AuthState { user: MyInfoResponse | null; accessToken: string | null; @@ -25,45 +74,16 @@ export const useAuthStore = create((set, get) => ({ initialize: async () => { const { accessToken, isAuthenticated, user } = get(); + const hasValidAccessToken = !isAccessTokenExpired(accessToken); if (user) { - set({ isAuthenticated: true, isLoading: false }); - return; + if (hasValidAccessToken) { + set({ isAuthenticated: true, isLoading: false }); + return; + } } - const hydrateUser = async (nextAccessToken: string) => { - if (hydrateUserPromise) return hydrateUserPromise; - - hydrateUserPromise = (async () => { - try { - const nextUser = await getMyInfo(); - - if (get().accessToken !== nextAccessToken) return; - - set({ user: nextUser }); - - try { - if (window.ReactNativeWebView) { - window.ReactNativeWebView.postMessage( - JSON.stringify({ type: 'LOGIN_COMPLETE', accessToken: nextAccessToken }) - ); - } - } catch { - // 브릿지 전달 실패가 인증 성공 상태를 롤백시키지 않도록 무시 - } - } catch { - if (get().accessToken !== nextAccessToken) return; - - set({ user: null, accessToken: null, isAuthenticated: false }); - } finally { - hydrateUserPromise = null; - } - })(); - - return hydrateUserPromise; - }; - - if (isAuthenticated && accessToken) { + if (isAuthenticated && accessToken && hasValidAccessToken) { set({ isLoading: false }); void hydrateUser(accessToken); return;