o2o-site-AEO/admin/frontend/src/app/router.tsx
Mina Choi 374a3a4a6e 구조: admin 을 backend/frontend 로 가른다
admin/ 이 프론트 파일만 널려 있는 폴더였다. :9801 을 띄우는 코드도 solution/backend 안에
얹혀 있어서, 폴더만 봐서는 admin 에 백엔드가 있다는 걸 몰랐다.

  admin/backend/   main.py · app.py   (:9801 진입점. 도메인 코드는 PYTHONPATH 로 solution/backend)
  admin/frontend/  운영 화면

패키지 이름도 폴더에 맞췄다: @o2o/front → @o2o/frontend.
이미지 빌드 컨텍스트를 레포 루트로 올렸다 — 진입점(admin/)과 도메인 코드(solution/)가
한 이미지에 들어와야 한다. 루트 .dockerignore 로 프론트·문서·시크릿을 잘라냈다.

★ 실측으로 잡은 것: 패키지명을 바꾸면서 compose 의 `-w @o2o/front` 를 안 고쳐
  web 컨테이너가 `No workspaces found` 로 재기동 루프에 빠져 있었다.

주석은 짧게 줄였다.

검증: lint·build 6개 전부 0. 컨테이너 5개 엔드포인트(9800·9801·3000·3002·80) 전부 200.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019uYhHQdssRubirPirrdJJC
2026-08-31 16:22:29 +09:00

48 lines
1.8 KiB
TypeScript

import {Building2, CalendarDays} from 'lucide-react';
import {createBrowserRouter, Navigate, Outlet} from 'react-router';
import {AppShell, type NavItem} from '@/components/layout/AppShell';
import {RequireAuth} from '@/components/layout/RequireAuth';
import {LocalContentPage} from '@admin/pages/LocalContentPage';
import {LoginPage} from '@/pages/LoginPage';
import {NotFoundPage} from '@/pages/NotFoundPage';
import {PlaceDetailPage} from '@admin/pages/PlaceDetailPage';
import {PlaceListPage} from '@admin/pages/PlaceListPage';
import {SeoAuditPage} from '@admin/pages/SeoAuditPage';
/**
* ★ 내부 메뉴는 여기 있다. AppShell(사장님 앱 소유)에 두면 이 경로 이름들이
* 사장님 번들에 문자열로 남는다 — 앱을 가른 이유가 사라진다.
*/
const ADMIN_NAV: NavItem[] = [
{to: '/places', match: '/places', label: '사업장', icon: Building2},
{to: '/local-content', match: '/local-content', label: '지역 콘텐츠', icon: CalendarDays},
];
/**
* 내부 운영 화면. **전부 RequireAuth 뒤에 둔다** — 예외를 하나 두는 순간
* 그 예외가 기본값이 된다. 사장님 앱과 앱을 가른 이유가 이 규칙을 지키기 위해서다.
*/
export const router = createBrowserRouter([
{path: '/login', element: <LoginPage />},
{path: '/', element: <Navigate to="/places" replace />},
{
element: (
<RequireAuth>
<AppShell nav={ADMIN_NAV}>
<Outlet />
</AppShell>
</RequireAuth>
),
children: [
{path: '/places', element: <PlaceListPage />},
{path: '/places/:placeId', element: <PlaceDetailPage />},
{path: '/places/:placeId/seo', element: <SeoAuditPage />},
{path: '/local-content', element: <LocalContentPage />},
],
},
{path: '*', element: <NotFoundPage />},
]);