refactor: 레이아웃 3종 라우트 그룹 구조 재편
Co-Authored-By: Claude Opus 5
@58026b1918653b49630bd52e3cd488d4b306847a
--- app/(protected)/_components/admin-header.tsx
+++ app/(protected)/(basic)/_components/admin-header.tsx
... | ... | @@ -1,4 +1,4 @@ |
| 1 |
-import { logout } from '../_actions';
|
|
| 1 |
+import { logout } from '@/app/(protected)/_actions';
|
|
| 2 | 2 |
|
| 3 | 3 |
export function AdminHeader() {
|
| 4 | 4 |
return ( |
+++ app/(protected)/(basic)/layout.tsx
... | ... | @@ -0,0 +1,16 @@ |
| 1 | +import { AdminHeader } from './_components/admin-header'; | |
| 2 | + | |
| 3 | +// Basic 레이아웃 — 헤더가 있는 일반 관리자 화면 진입점. 보안 강제는 상위 `(protected)/layout.tsx`가 | |
| 4 | +// 담당하므로 여기서는 크롬 조립만 책임진다. | |
| 5 | +export default function Layout({ | |
| 6 | + children, | |
| 7 | +}: Readonly<{ | |
| 8 | + children: React.ReactNode; | |
| 9 | +}>) { | |
| 10 | + return ( | |
| 11 | + <div className="flex min-h-screen flex-col"> | |
| 12 | + <AdminHeader /> | |
| 13 | + <main className="flex flex-1 flex-col">{children}</main> | |
| 14 | + </div> | |
| 15 | + ); | |
| 16 | +} |
--- app/(protected)/page.tsx
+++ app/(protected)/(basic)/page.tsx
| No changes |
+++ app/(protected)/(empty)/layout.tsx
... | ... | @@ -0,0 +1,10 @@ |
| 1 | +// Empty 레이아웃 — 헤더·사이드바 없이 전체 화면을 쓰는 보호 화면 진입점. 보안 강제는 상위 | |
| 2 | +// `(protected)/layout.tsx`가 담당하므로(세션 재검증·bfcache 방어 상속) 여기서는 크롬을 두지 않는다. | |
| 3 | +// 이 그룹에는 아직 화면(page.tsx)이 없다 — 최초 Empty 화면 작업 시 이 레이아웃 아래에 추가한다. | |
| 4 | +export default function Layout({ | |
| 5 | + children, | |
| 6 | +}: Readonly<{ | |
| 7 | + children: React.ReactNode; | |
| 8 | +}>) { | |
| 9 | + return <div className="flex min-h-screen flex-col">{children}</div>; | |
| 10 | +} |
--- app/(protected)/layout.tsx
+++ app/(protected)/layout.tsx
... | ... | @@ -1,8 +1,10 @@ |
| 1 |
-import { AdminHeader } from './_components/admin-header';
|
|
| 2 | 1 |
import { BfcacheGuard } from './_components/bfcache-guard';
|
| 3 | 2 |
|
| 4 | 3 |
// 인증 최종 판단은 하지 않는다(Partial Rendering 때문에 레이아웃은 인증 체크 지점으로 부적합 — |
| 5 | 4 |
// Next.js 공식 authentication 가이드 지침). 대신 캐시 차단만 명시적으로 강제한다. |
| 5 |
+// |
|
| 6 |
+// 이 레이어는 보호 영역 전체의 공통 보안층으로 축소되어 있다 — 크롬(헤더·사이드바 등)은 |
|
| 7 |
+// 하위 레이아웃((basic)/(empty))의 책임이며, 여기서는 세션 재검증 강제와 bfcache 방어만 담당한다. |
|
| 6 | 8 |
export const dynamic = 'force-dynamic'; |
| 7 | 9 |
|
| 8 | 10 |
export default function Layout({
|
... | ... | @@ -11,10 +13,9 @@ |
| 11 | 13 |
children: React.ReactNode; |
| 12 | 14 |
}>) {
|
| 13 | 15 |
return ( |
| 14 |
- <div className="flex min-h-screen flex-col"> |
|
| 16 |
+ <> |
|
| 15 | 17 |
<BfcacheGuard /> |
| 16 |
- <AdminHeader /> |
|
| 17 |
- <main className="flex flex-1 flex-col">{children}</main>
|
|
| 18 |
- </div> |
|
| 18 |
+ {children}
|
|
| 19 |
+ </> |
|
| 19 | 20 |
); |
| 20 | 21 |
} |
+++ app/(public)/layout.tsx
... | ... | @@ -0,0 +1,13 @@ |
| 1 | +// Auth 레이아웃 — 배경 위 카드를 화면 중앙에 배치하는 공용 래퍼. `(public)` 하위 화면(로그인 등)이 | |
| 2 | +// 공유한다. | |
| 3 | +export default function Layout({ | |
| 4 | + children, | |
| 5 | +}: Readonly<{ | |
| 6 | + children: React.ReactNode; | |
| 7 | +}>) { | |
| 8 | + return ( | |
| 9 | + <main className="flex min-h-screen flex-1 items-center justify-center bg-background p-6"> | |
| 10 | + {children} | |
| 11 | + </main> | |
| 12 | + ); | |
| 13 | +} |
--- app/(public)/login/page.tsx
+++ app/(public)/login/page.tsx
... | ... | @@ -12,9 +12,5 @@ |
| 12 | 12 |
redirect('/');
|
| 13 | 13 |
} |
| 14 | 14 |
|
| 15 |
- return ( |
|
| 16 |
- <main className="flex min-h-screen flex-1 items-center justify-center bg-background p-6"> |
|
| 17 |
- <LoginForm /> |
|
| 18 |
- </main> |
|
| 19 |
- ); |
|
| 15 |
+ return <LoginForm />; |
|
| 20 | 16 |
} |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?