diff --git a/app/my/page.tsx b/app/my/page.tsx
deleted file mode 100644
index d1b0b16..0000000
--- a/app/my/page.tsx
+++ /dev/null
@@ -1,52 +0,0 @@
-import { QuizCard } from '@/components/quiz/quiz-card';
-import quizOptions from '@/services/quiz/options';
-import { createClient } from '@/utils/supabase/server';
-import {
- HydrationBoundary,
- QueryClient,
- dehydrate,
-} from '@tanstack/react-query';
-import { cookies } from 'next/headers';
-
-export default async function Page() {
- const cookieStore = cookies();
- const supabase = createClient(cookieStore);
- const {
- data: { user },
- } = await supabase.auth.getUser();
-
- const queryClient = new QueryClient();
-
- const submittedQuiz = await queryClient.fetchQuery(
- quizOptions.submitted(user?.id ?? '')
- );
-
- return (
- <>
-
- {user?.user_metadata.user_name}
-
- 풀었던 퀴즈
-
- {submittedQuiz && submittedQuiz.length ? (
-
- {submittedQuiz.map(
- ({ quiz_id, success, quizzes }) =>
- quizzes && (
-
- )
- )}
-
- ) : (
- 제출한 퀴즈가 없습니다.
- )}
-
- >
- );
-}
diff --git a/app/quizzes/[id]/page.tsx b/app/quizzes/[id]/page.tsx
index efd33e6..9522746 100644
--- a/app/quizzes/[id]/page.tsx
+++ b/app/quizzes/[id]/page.tsx
@@ -37,8 +37,7 @@ export default async function Page({ params }: { params: { id: string } }) {
By{' '}
-
- {/* TODO: 추후 상세 유저 페이지 라우팅 경로로 변경하기 */}
+
{quiz?.users?.name}
diff --git a/app/user/[id]/_components/quiz-table.tsx b/app/user/[id]/_components/quiz-table.tsx
new file mode 100644
index 0000000..2d89af7
--- /dev/null
+++ b/app/user/[id]/_components/quiz-table.tsx
@@ -0,0 +1,15 @@
+import { columns } from '@/components/quiz/table/columns';
+import DataTable from '@/components/quiz/table/data-table';
+import { QuizTable } from '../../../../libs/models';
+
+type QuizTableProps = {
+ quiz: QuizTable[];
+};
+
+export default function QuizTable({ quiz }: QuizTableProps) {
+ return (
+
+
+
+ );
+}
diff --git a/app/user/[id]/_components/user-info.tsx b/app/user/[id]/_components/user-info.tsx
new file mode 100644
index 0000000..11f6d80
--- /dev/null
+++ b/app/user/[id]/_components/user-info.tsx
@@ -0,0 +1,9 @@
+type UserInfoProps = {
+ userInfo: {
+ name: string;
+ };
+};
+
+export default function UserInfo({ userInfo }: UserInfoProps) {
+ return {userInfo.name}
;
+}
diff --git a/app/user/[id]/layout.tsx b/app/user/[id]/layout.tsx
new file mode 100644
index 0000000..ce3b4fd
--- /dev/null
+++ b/app/user/[id]/layout.tsx
@@ -0,0 +1,16 @@
+import BackHeader from '@/components/common/headers/back-header';
+import React from 'react';
+
+type LayoutProps = {
+ children: React.ReactNode;
+};
+
+export default function Layout({ children }: LayoutProps) {
+ return (
+ <>
+
+
+
+ >
+ );
+}
diff --git a/app/user/[id]/not-found.tsx b/app/user/[id]/not-found.tsx
new file mode 100644
index 0000000..ae28c4d
--- /dev/null
+++ b/app/user/[id]/not-found.tsx
@@ -0,0 +1,20 @@
+import Image from 'next/image';
+import Link from 'next/link';
+import TypeTime from '@/assets/images/type-time.png';
+
+export default function NotFound() {
+ return (
+ <>
+
+
+
페이지를 찾을 수 없습니다.
+
+ 홈으로 이동하기
+
+
+ >
+ );
+}
diff --git a/app/user/[id]/page.tsx b/app/user/[id]/page.tsx
new file mode 100644
index 0000000..feab581
--- /dev/null
+++ b/app/user/[id]/page.tsx
@@ -0,0 +1,36 @@
+import {
+ HydrationBoundary,
+ QueryClient,
+ dehydrate,
+} from '@tanstack/react-query';
+import quizOptions from '@/services/quiz/options';
+import userOptions from '@/services/user/options';
+import { Separator } from '@/components/ui/separator';
+import UserInfo from './_components/user-info';
+import QuizTable from './_components/quiz-table';
+import NotFound from './not-found';
+
+export default async function Page({ params }: { params: { id: string } }) {
+ const { id } = params;
+
+ const queryClient = new QueryClient();
+
+ const [userInfo, submittedQuiz] = await Promise.all([
+ queryClient.fetchQuery(userOptions.info(id)),
+ queryClient.fetchQuery(quizOptions.submitted(id)),
+ ]);
+
+ if (userInfo) {
+ return (
+
+ {userInfo && }
+
+
+ 제출한 퀴즈
+
+
+ );
+ }
+
+ return ;
+}
diff --git a/components/common/headers/menu.tsx b/components/common/headers/menu.tsx
index f2d5154..0c9015a 100644
--- a/components/common/headers/menu.tsx
+++ b/components/common/headers/menu.tsx
@@ -48,7 +48,7 @@ export default async function Menu() {
diff --git a/components/common/headers/profile.tsx b/components/common/headers/profile.tsx
index 079070b..3dc6c05 100644
--- a/components/common/headers/profile.tsx
+++ b/components/common/headers/profile.tsx
@@ -13,7 +13,7 @@ export default async function Profile() {
} = await supabase.auth.getUser();
return (
-
+
{
diff --git a/services/user/api.ts b/services/user/api.ts
new file mode 100644
index 0000000..f8d76d8
--- /dev/null
+++ b/services/user/api.ts
@@ -0,0 +1,19 @@
+import { createClient } from '@/utils/supabase/client';
+import { SupabaseClient } from '@supabase/supabase-js';
+
+const userAPI = {
+ getUserInfo: async (id: string) => {
+ const supabase: SupabaseClient = createClient();
+
+ const { data } = await supabase
+ .from('users')
+ .select('name')
+ .eq('id', id)
+ .limit(1)
+ .single();
+
+ return data;
+ },
+};
+
+export default userAPI;
diff --git a/services/user/hook.ts b/services/user/hook.ts
new file mode 100644
index 0000000..58b7d52
--- /dev/null
+++ b/services/user/hook.ts
@@ -0,0 +1,6 @@
+import { useSuspenseQuery } from '@tanstack/react-query';
+import userOptions from './options';
+
+export function useGetUserInfo(id: string) {
+ return useSuspenseQuery(userOptions.info(id));
+}
diff --git a/services/user/options.ts b/services/user/options.ts
new file mode 100644
index 0000000..46a122c
--- /dev/null
+++ b/services/user/options.ts
@@ -0,0 +1,14 @@
+import { queryOptions } from '@tanstack/react-query';
+import userAPI from './api';
+
+const userOptions = {
+ default: ['users'] as const,
+
+ info: (id: string) =>
+ queryOptions({
+ queryKey: [...userOptions.default, 'info', id],
+ queryFn: () => userAPI.getUserInfo(id),
+ }),
+};
+
+export default userOptions;