import { getSessionAdmin } from '@/lib/auth/dal'; import { fetchNotifications } from '@/lib/data/repositories/notification-repository'; import { fetchSidebarMenu } from '@/lib/data/repositories/sidebar-menu-repository'; import type { SidebarMenu } from '@/lib/domain/sidebar-menu'; import { AdminShell } from './_components/admin-shell'; const EMPTY_MENU: SidebarMenu = { sections: [] }; // Basic 레이아웃 — 헤더·사이드바·풋터가 있는 일반 관리자 화면 진입점. 보안 강제는 상위 // `(protected)/layout.tsx`가 담당하므로 여기서는 크롬 조립(AdminShell)만 책임진다. page // 콘텐츠는 Server Component로 렌더된 그대로 AdminShell의 children으로 통과한다. // // **사이드바 메뉴는 여기서 조회한다.** 계정 권한마다 항목이 달라 화면이 들고 있을 수 없는 // 값이라, 세션의 권한으로 서버에서 구성해 내려보낸다 — 클라이언트가 나중에 불러오면 첫 // 페인트에 메뉴가 비었다가 채워지고, 조회에 쓰는 토큰도 브라우저로 내려가야 한다. // // 세션이 없으면 빈 메뉴다. **인증 판단은 하지 않는다** — 레이아웃은 Partial Rendering 때문에 // 인증 체크 지점으로 부적합하다는 상위 레이아웃의 판단을 그대로 따른다. export default async function Layout({ children, }: Readonly<{ children: React.ReactNode; }>) { const admin = await getSessionAdmin(); // 메뉴와 알림은 서로를 기다릴 이유가 없다. const [menu, notifications] = await Promise.all([ admin ? fetchSidebarMenu(admin.roleCode) : EMPTY_MENU, admin ? fetchNotifications() : [], ]); return ( {children} ); }