diff --git a/admin/backend/app.py b/admin/backend/app.py
index be45cca..8b94ae7 100644
--- a/admin/backend/app.py
+++ b/admin/backend/app.py
@@ -1,10 +1,4 @@
-"""어드민 API. 솔루션 API(:9800)와 프로세스·포트가 갈린다.
-
-도메인 코드는 solution/backend 것을 PYTHONPATH 로 쓴다 — admin 전용 라우터가 0개라
-(전부 place·fact) 새로 쓰면 같은 테이블을 두 벌 구현하는 것뿐이다.
-경로 접두어가 아니라 포트를 가른 이유: 접두어는 같은 프로세스라 사장님이 닿는 서버에
-내부 엔드포인트가 존재한다. 포트를 가르면 아예 없다.
-"""
+"""어드민 API."""
import time
@@ -32,7 +26,7 @@ API_SERVER_START_TIME = GTime.UTCStr()
@asynccontextmanager
async def lifespan(app: FastAPI):
- # 크론은 :9800 담당. 여기서도 돌리면 같은 시각에 중복 실행된다.
+ # 크론은 :9800 담당.
yield
await DB_SESSION_MNG.dispose_all()
diff --git a/admin/backend/main.py b/admin/backend/main.py
index 62c6810..f8c4318 100644
--- a/admin/backend/main.py
+++ b/admin/backend/main.py
@@ -1,5 +1,4 @@
-# 어드민 API 서버 (:9801). 근거는 app.py 주석.
-# PYTHONPATH=../../solution/backend python main.py
+# 어드민 API 서버 (:9801).
import os
diff --git a/admin/frontend/eslint.config.js b/admin/frontend/eslint.config.js
index b669fb4..aeaed98 100644
--- a/admin/frontend/eslint.config.js
+++ b/admin/frontend/eslint.config.js
@@ -1,6 +1,4 @@
// 최소 게이트 — 전체 스타일 린트가 아니라, tsc 가 못 잡는 런타임 크래시 버그만 막는다.
-// (negodata 보일러플레이트에서 이식. 도입 계기는 로컬 const 가 동명 import 를 가려
-// zustand 셀렉터가 TDZ 참조 → 프로덕션 크래시. 그 케이스는 tsc --noEmit 도 통과했다.)
import tseslint from 'typescript-eslint';
import reactHooks from 'eslint-plugin-react-hooks';
@@ -18,7 +16,7 @@ export default tseslint.config({
// 훅 호출 순서 위반은 런타임 크래시라 error, deps 누락은 기존 코드가 많아 warn.
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
- // 선언보다 위에서 변수를 쓰는 것(TDZ) 차단. 함수/타입 호이스팅은 안전하므로 허용.
+ // 선언보다 위에서 변수를 쓰는 것(TDZ) 차단.
'no-use-before-define': 'off',
'@typescript-eslint/no-use-before-define': [
'error',
diff --git a/admin/frontend/src/app/provider.tsx b/admin/frontend/src/app/provider.tsx
index 416c3b0..734582c 100644
--- a/admin/frontend/src/app/provider.tsx
+++ b/admin/frontend/src/app/provider.tsx
@@ -5,14 +5,7 @@ import {getAccessToken, me} from '@/api';
import {queryClient} from '@/lib/query-client';
import {toAuthUser, useAuthStore} from '@/stores/auth';
-/**
- * 저장된 액세스 토큰으로 세션을 복구한다.
- *
- * ★ 사장님 앱과 결정적으로 다른 점: **여기서는 실패가 곧 차단이다.**
- * 빌더는 로그인 없이도 돌아야 해서 인증 실패를 삼키지만(solution/frontend/app/provider.tsx),
- * 내부 운영 화면은 전부 RequireAuth 뒤에 있다. 두 정책을 한 앱에 두면 실수가 늘
- * 느슨한 쪽으로 나기 때문에 앱을 갈랐다.
- */
+/** 저장된 액세스 토큰으로 세션을 복구한다. */
function useRestoreSession() {
const setUser = useAuthStore((s) => s.setUser);
const finishRestore = useAuthStore((s) => s.finishRestore);
@@ -31,7 +24,7 @@ function useRestoreSession() {
setUser(toAuthUser(res));
})
.catch(() => {
- /* 토큰이 죽었으면 비로그인 상태로 떨어뜨린다. RequireAuth 가 로그인으로 보낸다. */
+ /* 토큰이 죽었으면 비로그인 상태로 떨어뜨린다. */
})
.finally(() => {
if (alive) finishRestore();
diff --git a/admin/frontend/src/app/router.tsx b/admin/frontend/src/app/router.tsx
index 6a7e5b5..09a8af3 100644
--- a/admin/frontend/src/app/router.tsx
+++ b/admin/frontend/src/app/router.tsx
@@ -10,20 +10,14 @@ 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},
{to: '/reviews', match: '/reviews', label: '이용 후기', icon: MessageSquareQuote},
];
-/**
- * 내부 운영 화면. **전부 RequireAuth 뒤에 둔다** — 예외를 하나 두는 순간
- * 그 예외가 기본값이 된다. 사장님 앱과 앱을 가른 이유가 이 규칙을 지키기 위해서다.
- */
+/** 내부 운영 화면. */
export const router = createBrowserRouter([
// selfServe=false: 내부 운영 계정은 우리가 만들어 준다 — 가입 링크도 구글 로그인도 두지 않는다.
{path: '/login', element: