diff --git a/solution/frontend/src/app/router.tsx b/solution/frontend/src/app/router.tsx
index 4208797..ccd6b79 100644
--- a/solution/frontend/src/app/router.tsx
+++ b/solution/frontend/src/app/router.tsx
@@ -1,20 +1,63 @@
import {createBrowserRouter, Navigate} from 'react-router';
+import {Loader2} from 'lucide-react';
+import {AccountPage} from '@/pages/AccountPage';
import {BuilderPage} from '@/pages/BuilderPage';
import {DevShowcasePage} from '@/pages/DevShowcasePage';
import {LoginPage} from '@/pages/LoginPage';
import {NotFoundPage} from '@/pages/NotFoundPage';
import {SignupPage} from '@/pages/SignupPage';
+import {SitesPage} from '@/pages/SitesPage';
+import {RequireAuth} from '@/components/layout/RequireAuth';
+import {useAuthStore} from '@/stores/auth';
+
+/**
+ * 첫 화면은 로그인 여부로 갈린다 — 이미 사이트를 가진 사장님의 용건은 "새로 만들기"가 아니라
+ * "내 것 고치기"다. 비로그인은 그대로 위저드로 보낸다(관문은 에디터 진입이다).
+ *
+ * ★ 복구가 끝나기 전에 판단하면 새로고침할 때마다 위저드가 한 번 번쩍이고 목록으로 튄다.
+ */
+function Home() {
+ const isRestoring = useAuthStore((s) => s.isRestoring);
+ const user = useAuthStore((s) => s.user);
+
+ if (isRestoring) {
+ return (
+
+
+
+ );
+ }
+ return ;
+}
export const router = createBrowserRouter([
{path: '/login', element: },
// 로그인 화면의 [회원가입] 이 여기로 온다. 이 줄이 없으면 링크는 있고 목적지만 404 다.
{path: '/signup', element: },
- // ★ 첫 화면은 업종 선택(위저드 1단계)이다.
+ // ★ 비로그인의 첫 화면은 업종 선택(위저드 1단계)이다.
// `?new=1` 을 붙이는 이유: 위저드 상태는 새로고침을 넘기려고 저장돼 있어서(stores/builder persist),
// 그냥 /builder 로 보내면 지난번에 만들다 만 **에디터**가 복원돼 뜬다. 처음 들어오는 사람에게는
// 그게 "왜 자꾸 빌더로 튀냐"로 보인다. 그래서 진입 경로에서 한 번 비우고 시작한다.
- {path: '/', element: },
+ {path: '/', element: },
+
+ // 로그인한 사장님의 홈. 만든 사이트를 열고 고치는 자리다.
+ {
+ path: '/sites',
+ element: (
+
+
+
+ ),
+ },
+ {
+ path: '/account',
+ element: (
+
+
+
+ ),
+ },
/**
* 빌더는 로그인 화면을 앞에 세우지 않는다 — 위저드를 열자마자 로그인부터 만나면
diff --git a/solution/frontend/src/components/layout/AppShell.tsx b/solution/frontend/src/components/layout/AppShell.tsx
index 61a1fe7..55f4384 100644
--- a/solution/frontend/src/components/layout/AppShell.tsx
+++ b/solution/frontend/src/components/layout/AppShell.tsx
@@ -1,6 +1,6 @@
import type {ComponentType, ReactNode} from 'react';
import {Link, NavLink, useLocation, useNavigate} from 'react-router';
-import {LayoutGrid, LogIn, LogOut, Search, Wand2} from 'lucide-react';
+import {LayoutGrid, LogIn, LogOut, Search, Store, Wand2} from 'lucide-react';
import {cn} from '@/lib/utils';
import {userLabel, useAuthStore} from '@/stores/auth';
@@ -23,6 +23,7 @@ export type NavItem = {
* 남의 화면이다.
*/
const OWNER_NAV: NavItem[] = [
+ {to: '/sites', match: '/sites', label: '내 사이트', icon: Store},
{to: '/builder?new=1', match: '/builder', label: '새 사이트', icon: Wand2},
];
@@ -63,16 +64,20 @@ export function AppShell({children, nav = OWNER_NAV}: {children: ReactNode; nav?
**비로그인 상태를 반드시 그려야 한다.** 예전엔 이름이 빈 줄로 나오고 [로그아웃]만
남아서, 로그인한 적 없는 사람이 눌러도 아무 일이 안 일어났다(지울 세션이 없다). */}
-
- {user ? (
- <>
- {userLabel(user)}
- {user.companyName ? ` · ${user.companyName}` : ''}
- >
- ) : (
+ {/* 이름 자리가 곧 [내 정보] 입구다 — 메뉴를 한 줄 더 늘리지 않는다(아임웹의 프로필과 같은 자리). */}
+ {user ? (
+
+ {userLabel(user)}
+ {user.companyName ? ` · ${user.companyName}` : ''}
+
+ ) : (
+
로그인하지 않았습니다
- )}
-
+
+ )}
{user ? (
+ }
+ >
+ {isLoading && (
+
+
+
+ )}
+
+ {isError && (
+
refetch()}>
+ 다시 시도
+
+ }
+ />
+ )}
+
+ {!isLoading && !isError && rows.length === 0 && (
+ navigate('/builder?new=1')}>
+ 첫 사이트 만들기
+
+ }
+ />
+ )}
+
+ {rows.length > 0 && (
+
+ )}
+
+
+ );
+}