diff --git a/500.html b/500.html
new file mode 100644
index 0000000..56939b6
--- /dev/null
+++ b/500.html
@@ -0,0 +1,180 @@
+
+
+
+
+
+ Velog Dashboard - 500
+
+
+
+
+
+
+ VD
+
+
Velog Dashboard
+
+
알 수 없는 오류가 발생했습니다.
+
+
+
+
+
diff --git a/package.json b/package.json
index 186bf20..5409b0f 100644
--- a/package.json
+++ b/package.json
@@ -15,6 +15,7 @@
"dependencies": {
"@channel.io/channel-web-sdk-loader": "^2.0.0",
"@next/third-parties": "^15.1.7",
+ "@sentry/core": "^9.4.0",
"@sentry/nextjs": "^8.47.0",
"@tanstack/react-query": "^5.61.3",
"@tanstack/react-query-devtools": "^5.62.11",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 29ce0d1..85f3689 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -14,6 +14,9 @@ importers:
'@next/third-parties':
specifier: ^15.1.7
version: 15.1.7(next@14.2.18(@babel/core@7.26.0)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
+ '@sentry/core':
+ specifier: ^9.4.0
+ version: 9.4.0
'@sentry/nextjs':
specifier: ^8.47.0
version: 8.47.0(@opentelemetry/core@1.30.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.56.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.0(@opentelemetry/api@1.9.0))(next@14.2.18(@babel/core@7.26.0)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(webpack@5.97.1)
@@ -1499,6 +1502,10 @@ packages:
resolution: {integrity: sha512-iSEJZMe3DOcqBFZQAqgA3NB2lCWBc4Gv5x/SCri/TVg96wAlss4VrUunSI2Mp0J4jJ5nJcJ2ChqHSBAU48k3FA==}
engines: {node: '>=14.18'}
+ '@sentry/core@9.4.0':
+ resolution: {integrity: sha512-Edd/uWDGZ+1CMuVVWdxIOm1rBhzgpqiqz984TZu20wryoIoRsA8ZllUar6N+cWK17VusNY0OS2DozKO69y7fVQ==}
+ engines: {node: '>=18'}
+
'@sentry/nextjs@8.47.0':
resolution: {integrity: sha512-qr++MBYhyAwF25hGq7LAxe3Xehs+w2V4b8mVxilRYFXNkWFazY1ukZcVzq9pKrrt5uTiURTf68e8eVMraHnHEQ==}
engines: {node: '>=14.18'}
@@ -6373,6 +6380,8 @@ snapshots:
'@sentry/core@8.47.0': {}
+ '@sentry/core@9.4.0': {}
+
'@sentry/nextjs@8.47.0(@opentelemetry/core@1.30.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.56.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.0(@opentelemetry/api@1.9.0))(next@14.2.18(@babel/core@7.26.0)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(webpack@5.97.1)':
dependencies:
'@opentelemetry/api': 1.9.0
diff --git a/src/apis/instance.request.ts b/src/apis/instance.request.ts
index 05ba80b..613fd03 100644
--- a/src/apis/instance.request.ts
+++ b/src/apis/instance.request.ts
@@ -75,10 +75,9 @@ export const instance = async (
return (data.body as unknown as SuccessType).data;
} catch (err: unknown) {
const context = err as Response;
- if (location && !context.ok && context.status === 403) {
+ if (location && !context.ok && context.status === 401) {
window.location.replace('/');
}
- //context.status === 401 ||
setContext('Request', {
path: context.url,
status: context.status,
diff --git a/src/app/(with-tracker)/(login)/Content.tsx b/src/app/(with-tracker)/(login)/Content.tsx
index 8c63710..bad17fb 100644
--- a/src/app/(with-tracker)/(login)/Content.tsx
+++ b/src/app/(with-tracker)/(login)/Content.tsx
@@ -3,7 +3,7 @@
import { useRouter } from 'next/navigation';
import { useForm } from 'react-hook-form';
import Image from 'next/image';
-import { useMutation, useQueryClient } from '@tanstack/react-query';
+import { useMutation } from '@tanstack/react-query';
import { Input, Button } from '@/components';
import { LoginVo } from '@/types';
import { login, sampleLogin } from '@/apis';
@@ -14,7 +14,6 @@ const responsiveStyle =
export const Content = () => {
const { replace } = useRouter();
- const client = useQueryClient();
const {
register,
@@ -23,7 +22,6 @@ export const Content = () => {
} = useForm({ mode: 'all' });
const onSuccess = () => {
- client.clear();
trackUserEvent(MessageEnum.LOGIN);
replace('/main?asc=false&sort=');
};
diff --git a/src/components/auth-required/header/index.tsx b/src/components/auth-required/header/index.tsx
index 6984f7b..530a488 100644
--- a/src/components/auth-required/header/index.tsx
+++ b/src/components/auth-required/header/index.tsx
@@ -9,6 +9,8 @@ import { NameType } from '@/components';
import { useResponsive } from '@/hooks';
import { logout, me } from '@/apis';
import { trackUserEvent, MessageEnum } from '@/utils/trackUtil';
+import { revalidate } from '@/utils/revalidateUtil';
+
import { defaultStyle, Section, textStyle } from './Section';
const PARAMS = {
@@ -37,13 +39,19 @@ export const Header = () => {
const { mutate: out } = useMutation({
mutationFn: logout,
- onMutate: () => router.replace('/'),
- onSuccess: () => client.removeQueries(),
+ onSuccess: async () => {
+ await revalidate();
+ client.clear();
+ router.replace('/');
+ },
});
const { data: profiles } = useQuery({
queryKey: [PATHS.ME],
queryFn: me,
+ enabled: !!client.getQueryData([PATHS.ME]),
+ // 로그아웃 후 리렌더링되어 다시 fetch되는 경우 해결
+ // 어차피 prefetch를 통해 데이터를 불러온 상태에서 렌더하기 때문에, 캐시 여부만 판단하면 됨
});
useEffect(() => {
diff --git a/src/components/auth-required/main/Section/index.tsx b/src/components/auth-required/main/Section/index.tsx
index 91ce6dc..bdb1c45 100644
--- a/src/components/auth-required/main/Section/index.tsx
+++ b/src/components/auth-required/main/Section/index.tsx
@@ -1,27 +1,22 @@
'use client';
-import { useQueryClient } from '@tanstack/react-query';
import { useState } from 'react';
-import { UserNameNotFoundError } from '@/errors';
import { trackUserEvent, MessageEnum } from '@/utils/trackUtil';
import { parseNumber } from '@/utils/numberUtil';
import { COLORS, env, PATHS } from '@/constants';
import { PostType, UserDto } from '@/types';
import { Icon } from '@/components';
+import { getQueryClient } from '@/utils/queryUtil';
import { Graph } from './Graph';
export const Section = (p: PostType) => {
const [open, setOpen] = useState(false);
- const client = useQueryClient();
- const { username } = client.getQueryData([PATHS.ME]) as UserDto;
- const URL = env.VELOG_URL;
+ const username = (
+ getQueryClient().getQueryData([PATHS.ME]) as Partial
+ )?.username;
- if (!username) {
- throw new UserNameNotFoundError();
- }
-
- const url = `${URL}/@${username}/${p.slug}`;
+ const url = `${env.VELOG_URL}/@${username}/${p.slug}`;
return (
diff --git a/src/utils/queryUtil.ts b/src/utils/queryUtil.ts
index 9e40e0a..ad54707 100644
--- a/src/utils/queryUtil.ts
+++ b/src/utils/queryUtil.ts
@@ -3,7 +3,7 @@ import { toast } from 'react-toastify';
let localQueryClient: QueryClient | undefined;
const STALE_TIME = 1000 * 60 * 3;
-const GC_TIME = 1000;
+const GC_TIME = 1000 * 60 * 20;
const createQueryClient = () =>
new QueryClient({
diff --git a/src/utils/revalidateUtil.ts b/src/utils/revalidateUtil.ts
new file mode 100644
index 0000000..375a030
--- /dev/null
+++ b/src/utils/revalidateUtil.ts
@@ -0,0 +1,9 @@
+'use server';
+
+import { revalidatePath } from 'next/cache';
+import { redirect } from 'next/navigation';
+
+export async function revalidate() {
+ revalidatePath('/', 'layout');
+ redirect('/');
+}