Date: Sun, 20 Apr 2025 01:05:33 +0900
Subject: [PATCH 07/12] =?UTF-8?q?refactor:=20=EB=A9=94=EC=8B=9C=EC=A7=80?=
=?UTF-8?q?=20=EC=A0=95=EB=B3=B4=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20?=
=?UTF-8?q?=EC=A0=81=EC=9A=A9=20=EB=B0=8F=20=ED=95=A8=EC=88=98=20=EC=9E=AC?=
=?UTF-8?q?=EC=84=B1=EC=84=B1=20=EA=B4=80=EB=A0=A8=20=EC=B5=9C=EC=A0=81?=
=?UTF-8?q?=ED=99=94=20=EC=A0=81=EC=9A=A9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/pages/Main/components/MessageCounter.tsx | 22 ++++++++++++++
src/pages/Main/index.tsx | 30 +++++++++-----------
2 files changed, 35 insertions(+), 17 deletions(-)
create mode 100644 src/pages/Main/components/MessageCounter.tsx
diff --git a/src/pages/Main/components/MessageCounter.tsx b/src/pages/Main/components/MessageCounter.tsx
new file mode 100644
index 0000000..f073632
--- /dev/null
+++ b/src/pages/Main/components/MessageCounter.tsx
@@ -0,0 +1,22 @@
+interface MessageCounterProps {
+ messageCount: number
+}
+
+const MessageCounter = ({ messageCount }: MessageCounterProps) => {
+ return (
+
+
+ 지금까지 {messageCount}개의
+
+ 메시지가 모였어요 💌
+
+
+ 전체 메시지가 쌓일수록
+
+ 도시에 불이 켜져요
+
+
+ )
+}
+
+export default MessageCounter
diff --git a/src/pages/Main/index.tsx b/src/pages/Main/index.tsx
index e066600..58f80b3 100644
--- a/src/pages/Main/index.tsx
+++ b/src/pages/Main/index.tsx
@@ -5,7 +5,7 @@ import useBodyBackgroundColor from '@/hooks/useBodyBackgroundColor'
import { useMainData } from '@/hooks/useMainData'
import { useGetMessages } from '@/hooks/useMessage'
import Sidebar from '@/layouts/Sidebar'
-import { useEffect, useMemo, useState } from 'react'
+import { useCallback, useEffect, useMemo, useState } from 'react'
import { useInView } from 'react-intersection-observer'
import { useLocation } from 'react-router-dom'
import { twMerge } from 'tailwind-merge'
@@ -14,6 +14,7 @@ import MessageList from './components/MessageList'
import WriteMessageButton from './components/WriteMessageButton'
import { useScrollFade } from '@/hooks/useScrollFade'
import CityBackground from './components/CityBackground'
+import MessageCounter from './components/MessageCounter'
export default function MainPage() {
const [showSidebar, setShowSidebar] = useState(false)
@@ -46,6 +47,14 @@ export default function MainPage() {
[mainData?.writtenLetterNumber, messages.length]
)
+ const handleSidebarToggle = useCallback(() => {
+ setShowSidebar(true)
+ }, [])
+
+ const handleCloseModal = useCallback(() => {
+ setActiveMessage(undefined)
+ }, [])
+
useEffect(() => {
if (inView && hasNextPage && !isFetchingNextPage) {
fetchNextPage()
@@ -61,27 +70,14 @@ export default function MainPage() {
return (
<>
- {activeMessage && (
-
setActiveMessage(undefined)} />
- )}
+ {activeMessage && }
- setShowSidebar(true)} />
+
-
-
- 지금까지 {Math.max(mainData?.writtenLetterNumber || 0, messages.length)}개의
-
- 메시지가 모였어요 💌
-
-
- 전체 메시지가 쌓일수록
-
- 도시에 불이 켜져요
-
-
+
From 6352250b01964aea481f5282d2e73208508eb9f9 Mon Sep 17 00:00:00 2001
From: AAminha
Date: Sun, 20 Apr 2025 01:11:05 +0900
Subject: [PATCH 08/12] =?UTF-8?q?refactor:=20=EC=BA=90=EC=8B=B1=20?=
=?UTF-8?q?=EA=B4=80=EB=A0=A8=20=EC=83=81=EC=88=98=20=EC=83=9D=EC=84=B1=20?=
=?UTF-8?q?=EB=B0=8F=20=EC=A0=81=EC=9A=A9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/constants/cache.ts | 2 ++
src/hooks/useMainData.ts | 5 +++--
src/hooks/useMessage.ts | 13 +++++++------
src/hooks/useNews.tsx | 5 +++--
src/hooks/useNotices.ts | 9 +++++----
src/hooks/useShare..ts | 5 +++--
6 files changed, 23 insertions(+), 16 deletions(-)
create mode 100644 src/constants/cache.ts
diff --git a/src/constants/cache.ts b/src/constants/cache.ts
new file mode 100644
index 0000000..91f949f
--- /dev/null
+++ b/src/constants/cache.ts
@@ -0,0 +1,2 @@
+export const CACHE_TIME = 1000 * 60 * 60 // 1시간
+export const STALE_TIME = 1000 * 60 * 5 // 5분
diff --git a/src/hooks/useMainData.ts b/src/hooks/useMainData.ts
index 496af01..4093f29 100644
--- a/src/hooks/useMainData.ts
+++ b/src/hooks/useMainData.ts
@@ -1,11 +1,12 @@
import { getMainData } from '@/apis/message'
+import { CACHE_TIME, STALE_TIME } from '@/constants/cache'
import { useQuery } from '@tanstack/react-query'
export const useMainData = () => {
return useQuery({
queryKey: ['main-data'],
queryFn: () => getMainData(),
- staleTime: 1000 * 60 * 5, // 5분
- gcTime: 1000 * 60 * 60, // 1시간
+ staleTime: STALE_TIME,
+ gcTime: CACHE_TIME,
})
}
diff --git a/src/hooks/useMessage.ts b/src/hooks/useMessage.ts
index ea73366..00af8a7 100644
--- a/src/hooks/useMessage.ts
+++ b/src/hooks/useMessage.ts
@@ -1,4 +1,5 @@
import { getMessages, getMyMessageDetail, getMyMessages } from '@/apis/message'
+import { CACHE_TIME, STALE_TIME } from '@/constants/cache'
import { useInfiniteQuery, useQuery } from '@tanstack/react-query'
const MESSAGE_SIZE = 10
@@ -14,8 +15,8 @@ export const useGetMessages = () => {
return allPages.length
},
initialPageParam: 0,
- staleTime: 1000 * 60 * 5, // 5분
- gcTime: 1000 * 60 * 60, // 1시간
+ staleTime: STALE_TIME,
+ gcTime: CACHE_TIME,
})
}
@@ -23,8 +24,8 @@ export const useGetMyMessages = () => {
return useQuery({
queryKey: ['my-messages'],
queryFn: () => getMyMessages(),
- staleTime: 1000 * 60 * 5, // 5분
- gcTime: 1000 * 60 * 60, // 1시간
+ staleTime: STALE_TIME,
+ gcTime: CACHE_TIME,
})
}
@@ -32,8 +33,8 @@ export const useGetMyMessageDetail = (id: string) => {
return useQuery({
queryKey: ['my-message-detail', id],
queryFn: () => getMyMessageDetail(id),
- staleTime: 1000 * 60 * 5, // 5분
- gcTime: 1000 * 60 * 60, // 1시간
+ staleTime: STALE_TIME,
+ gcTime: CACHE_TIME,
retry: 0,
})
}
diff --git a/src/hooks/useNews.tsx b/src/hooks/useNews.tsx
index 8b7579a..7ec78d9 100644
--- a/src/hooks/useNews.tsx
+++ b/src/hooks/useNews.tsx
@@ -1,4 +1,5 @@
import { getNews } from '@/apis/news'
+import { CACHE_TIME, STALE_TIME } from '@/constants/cache'
import { useInfiniteQuery } from '@tanstack/react-query'
const NEWS_SIZE = 10
@@ -14,7 +15,7 @@ export const useGetNews = () => {
return allPages.length
},
initialPageParam: 0,
- staleTime: 1000 * 60 * 5, // 5분
- gcTime: 1000 * 60 * 60, // 1시간
+ staleTime: STALE_TIME,
+ gcTime: CACHE_TIME,
})
}
diff --git a/src/hooks/useNotices.ts b/src/hooks/useNotices.ts
index 7b3f7e1..fa7cf93 100644
--- a/src/hooks/useNotices.ts
+++ b/src/hooks/useNotices.ts
@@ -1,4 +1,5 @@
import { getNoticeById, getNotices } from '@/apis/notice'
+import { CACHE_TIME, STALE_TIME } from '@/constants/cache'
import { useInfiniteQuery, useQuery } from '@tanstack/react-query'
export const useGetNotices = (size: number) => {
@@ -12,8 +13,8 @@ export const useGetNotices = (size: number) => {
return allPages.length // 다음 페이지 번호
},
initialPageParam: 0,
- staleTime: 1000 * 60 * 5, // 5분
- gcTime: 1000 * 60 * 60, // 1시간
+ staleTime: STALE_TIME,
+ gcTime: CACHE_TIME,
})
}
@@ -21,7 +22,7 @@ export const useGetNoticeById = (id: string) => {
return useQuery({
queryKey: ['notice', id],
queryFn: () => getNoticeById(id),
- staleTime: 1000 * 60 * 60, // 1시간
- gcTime: 1000 * 60 * 60 * 2, // 2시간
+ staleTime: CACHE_TIME,
+ gcTime: CACHE_TIME * 2,
})
}
diff --git a/src/hooks/useShare..ts b/src/hooks/useShare..ts
index 26e0079..1f5f964 100644
--- a/src/hooks/useShare..ts
+++ b/src/hooks/useShare..ts
@@ -1,11 +1,12 @@
import { getSharing } from '@/apis/share'
+import { CACHE_TIME, STALE_TIME } from '@/constants/cache'
import { useQuery } from '@tanstack/react-query'
export const useGetSharing = () => {
return useQuery({
queryKey: ['sharing'],
queryFn: () => getSharing(),
- staleTime: 1000 * 60 * 5, // 5분
- gcTime: 1000 * 60 * 60, // 1시간
+ staleTime: STALE_TIME,
+ gcTime: CACHE_TIME,
})
}
From 072e889ffa147fe76e16c3f23230a6ab124a5453 Mon Sep 17 00:00:00 2001
From: AAminha
Date: Sun, 20 Apr 2025 21:53:35 +0900
Subject: [PATCH 09/12] =?UTF-8?q?refactor:=20api=20=ED=95=A8=EC=88=98=20?=
=?UTF-8?q?=EA=B4=80=EB=A0=A8=20=EC=97=90=EB=9F=AC=20=EC=B2=98=EB=A6=AC=20?=
=?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EB=B3=B4=EC=99=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/apis/message.ts | 50 ++++++++++++++++++----------------------
src/pages/Main/index.tsx | 27 ++++++++++++++++++++--
2 files changed, 47 insertions(+), 30 deletions(-)
diff --git a/src/apis/message.ts b/src/apis/message.ts
index 7298ba0..656f237 100644
--- a/src/apis/message.ts
+++ b/src/apis/message.ts
@@ -1,39 +1,33 @@
import { client } from './client'
export const getMessages = async (page: number, size: number) => {
- try {
- const {
- data: { data },
- } = await client.get('/mainPage/letter', {
- params: {
- page,
- size,
- },
- })
- return data
- } catch (error) {
- if (error instanceof Error) {
- console.error(error.message)
- }
+ const {
+ data: { data },
+ } = await client.get('/mainPage/letter', {
+ params: {
+ page,
+ size,
+ },
+ })
+ if (!data) {
+ throw new Error('No messages received from server')
}
+ return data
}
export const getMainData = async () => {
- try {
- const {
- data: { data },
- } = await client.get('/mainPage', {
- params: {
- page: 0,
- size: 1,
- },
- })
- return data
- } catch (error) {
- if (error instanceof Error) {
- console.error(error.message)
- }
+ const {
+ data: { data },
+ } = await client.get('/mainPage', {
+ params: {
+ page: 0,
+ size: 1,
+ },
+ })
+ if (!data) {
+ throw new Error('No main data received from server')
}
+ return data
}
export const getSearchResult = async (keyword: string, target: string) => {
diff --git a/src/pages/Main/index.tsx b/src/pages/Main/index.tsx
index 58f80b3..984e360 100644
--- a/src/pages/Main/index.tsx
+++ b/src/pages/Main/index.tsx
@@ -15,6 +15,7 @@ import WriteMessageButton from './components/WriteMessageButton'
import { useScrollFade } from '@/hooks/useScrollFade'
import CityBackground from './components/CityBackground'
import MessageCounter from './components/MessageCounter'
+import SolidButton from '@/components/SolidButton'
export default function MainPage() {
const [showSidebar, setShowSidebar] = useState(false)
@@ -28,13 +29,14 @@ export default function MainPage() {
const showFade = useScrollFade()
useBodyBackgroundColor('#14192F')
- const { data: mainData, refetch: mainDataRefetch } = useMainData()
+ const { data: mainData, refetch: mainDataRefetch, isError: isMainDataError } = useMainData()
const {
data,
fetchNextPage,
hasNextPage,
isFetchingNextPage,
refetch: messagesRefetch,
+ isError: isMessagesError,
} = useGetMessages()
const messages = useMemo(
@@ -68,6 +70,27 @@ export default function MainPage() {
}
}, [state?.from])
+ if (isMainDataError || isMessagesError) {
+ return (
+
+
+
데이터를 불러오는데 실패했습니다.
+
{
+ mainDataRefetch()
+ messagesRefetch()
+ }}
+ >
+ 다시 시도하기
+
+
+
+ )
+ }
+
return (
<>
{activeMessage && }
@@ -75,7 +98,7 @@ export default function MainPage() {
-
+
From e2982c5d2b93bc67a53ecfe2fa55d2c8792b009e Mon Sep 17 00:00:00 2001
From: AAminha
Date: Sun, 20 Apr 2025 22:28:04 +0900
Subject: [PATCH 10/12] =?UTF-8?q?feat:=20query=20=EB=B0=8F=20mutation=20?=
=?UTF-8?q?=EC=97=90=EB=9F=AC=20=EC=8B=9C,=20Sentry=EC=97=90=20=EA=B8=B0?=
=?UTF-8?q?=EB=A1=9D=EB=90=98=EB=8F=84=EB=A1=9D=20=EC=B2=98=EB=A6=AC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/main.tsx | 27 +++++++++++++++++++++++++--
1 file changed, 25 insertions(+), 2 deletions(-)
diff --git a/src/main.tsx b/src/main.tsx
index 49374d4..4448caa 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -1,7 +1,7 @@
import { createRoot } from 'react-dom/client'
import App from '@/App'
import '@/styles/index.css'
-import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
+import { MutationCache, QueryCache, QueryClient, QueryClientProvider } from '@tanstack/react-query'
import * as Sentry from '@sentry/react'
import { browserTracingIntegration, replayIntegration } from '@sentry/react'
@@ -16,7 +16,30 @@ Sentry.init({
tracePropagationTargets: ['localhost', import.meta.env.VITE_API_URL],
})
-const queryClient = new QueryClient()
+const queryClient = new QueryClient({
+ queryCache: new QueryCache({
+ onError: (error) => {
+ if (error instanceof Error) {
+ Sentry.captureException(error)
+ } else {
+ Sentry.captureMessage('Unknown Query Error', {
+ extra: { error },
+ })
+ }
+ },
+ }),
+ mutationCache: new MutationCache({
+ onError: (error) => {
+ if (error instanceof Error) {
+ Sentry.captureException(error)
+ } else {
+ Sentry.captureMessage('Unknown Mutation Error', {
+ extra: { error },
+ })
+ }
+ },
+ }),
+})
createRoot(document.getElementById('root')!).render(
From 39e9319a0c1f157255dc3ed161739f0cb73dc3b1 Mon Sep 17 00:00:00 2001
From: AAminha
Date: Sun, 20 Apr 2025 23:08:13 +0900
Subject: [PATCH 11/12] =?UTF-8?q?chore:=20=EC=9E=AC=EC=8B=9C=EB=8F=84=20?=
=?UTF-8?q?=EB=B0=8F=20refetch=20=EA=B4=80=EB=A0=A8=20=EC=84=A4=EC=A0=95?=
=?UTF-8?q?=20=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/main.tsx | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/main.tsx b/src/main.tsx
index 4448caa..5980a89 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -17,6 +17,12 @@ Sentry.init({
})
const queryClient = new QueryClient({
+ defaultOptions: {
+ queries: {
+ retry: false,
+ refetchOnWindowFocus: false,
+ },
+ },
queryCache: new QueryCache({
onError: (error) => {
if (error instanceof Error) {
From f22763e98f99669a05decf39251e769be26338c5 Mon Sep 17 00:00:00 2001
From: AAminha
Date: Sun, 20 Apr 2025 23:29:36 +0900
Subject: [PATCH 12/12] =?UTF-8?q?design:=20=EA=B3=B5=ED=86=B5=20=EB=94=94?=
=?UTF-8?q?=EC=9E=90=EC=9D=B8=20=EC=8A=A4=ED=83=80=EC=9D=BC=20=EC=88=98?=
=?UTF-8?q?=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/pages/AuthCallback/index.tsx | 2 +-
src/pages/Login/index.tsx | 6 +++---
src/styles/utilities.css | 1 -
3 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/src/pages/AuthCallback/index.tsx b/src/pages/AuthCallback/index.tsx
index 1bbc7e2..6d98cd7 100644
--- a/src/pages/AuthCallback/index.tsx
+++ b/src/pages/AuthCallback/index.tsx
@@ -17,7 +17,7 @@ export default function AuthCallback() {
if (error) {
return (
-
+
{error}
diff --git a/src/pages/Login/index.tsx b/src/pages/Login/index.tsx
index 3fbea1e..925fe67 100644
--- a/src/pages/Login/index.tsx
+++ b/src/pages/Login/index.tsx
@@ -22,9 +22,9 @@ export default function LoginPage() {
return (
<>
setIsOpen(false)} />
-
-
-
+
+
+
{
diff --git a/src/styles/utilities.css b/src/styles/utilities.css
index f977bb9..7cb2b14 100644
--- a/src/styles/utilities.css
+++ b/src/styles/utilities.css
@@ -15,7 +15,6 @@
display: flex;
flex-direction: column;
align-items: center;
- justify-content: space-between;
width: 100%;
flex-grow: 1;
}