File name
Commit message
Commit date
File name
Commit message
Commit date
09-04
import type { Metadata } from "next";
import { Geist_Mono } from "next/font/google";
import { FeedbackHost } from "@/app/_components/feedback-host";
import { FeedbackProvider } from "@/app/_components/feedback-provider";
import "./globals.scss";
// 앱 기본 서체는 여기서 선언하지 않는다 — @fox 토큰이 패밀리명을 리터럴 `Pretendard`로 못
// 박고 있어 `next/font`(패밀리명을 해시로 바꾼다)를 쓸 수 없고, globals.scss의 `@font-face`가
// 그 이름 그대로 공급한다. 앱과 @fox가 같은 서체를 쓰므로 앱 몫을 따로 둘 이유도 없다.
// `--app-font-sans` 계약(@fox/README.md "호스트 앱과의 계약")도 그 옆에서 함께 정의한다.
// 코드/숫자 표기용 고정폭 서체 — `--app-font-mono` 계약으로 주입한다.
const geistMono = Geist_Mono({
variable: "--app-font-mono",
subsets: ["latin"],
});
// 관리자 사이트 전체(로그인 포함)의 검색엔진 색인을 차단한다 — 하위 라우트는 별도 설정이
// 없는 한 이 값을 그대로 상속한다. robots.txt(app/robots.ts), next.config.ts의
// X-Robots-Tag 헤더와 함께 SEO 차단 3층 구조를 이룬다.
export const metadata: Metadata = {
title: "에듀페이 관리자",
robots: {
index: false,
follow: false,
nocache: true,
googleBot: {
index: false,
follow: false,
noimageindex: true,
"max-image-preview": "none",
"max-snippet": 0,
"max-video-preview": 0,
},
},
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html
lang="ko"
// 테마를 바꾸는 기획이 아직 없어 라이트로 못박는다. @fox 토큰은 `color-scheme`으로
// 갈리므로(`@fox/styles/_root.scss`) 이 속성 하나가 OS 다크 설정까지 덮는다.
// 전환이 기획되면 이 값을 저장된 선택으로 되돌리고 `_hooks/use-theme-preference`와
// `_components/theme-toggle-button`을 헤더에 다시 붙이면 된다(둘 다 그대로 남아 있다).
data-theme="light"
suppressHydrationWarning
className={geistMono.variable}
>
<head>
{/* @font-face는 CSS를 다 읽은 뒤에야 발견돼 본문이 한 번 폴백 서체로 그려진다.
거의 모든 화면이 쓰는 regular만 미리 받아 그 깜빡임을 없앤다 — 나머지 굵기는
빈도가 낮아 선점 비용이 이득보다 크다. */}
<link
rel="preload"
as="font"
type="font/woff2"
href="/fonts/pretendard-regular.woff2"
crossOrigin="anonymous"
/>
</head>
<body>
<FeedbackProvider>
{children}
<FeedbackHost />
</FeedbackProvider>
</body>
</html>
);
}