컨텐츠로 이동

레이아웃

레이아웃은 페이지 템플릿과 같은 재사용 가능한 UI 구조를 제공하는 데 사용되는 Astro 컴포넌트입니다.

우리는 일반적으로 머리글, 탐색 모음, 바닥글과 같이 페이지 전체에서 공유되는 공통 UI 요소를 제공하는 Astro 컴포넌트에 대해 “레이아웃”이라는 용어를 사용합니다. 일반적인 Astro 레이아웃 컴포넌트는 다음과 같은 Astro, Markdown, MDX 페이지를 제공합니다.

  • 페이지 셸(<html>, <head>, <body> 태그)
  • 개별 페이지 콘텐츠를 삽입해야 하는 위치를 지정하는 <slot />.

하지만 레이아웃 컴포넌트에는 특별한 것이 없습니다! 다른 Astro 컴포넌트처럼 props를 전달받고 다른 컴포넌트를 가져와 사용할 수 있습니다. 여기에는 UI 프레임워크 컴포넌트클라이언트 측 스크립트 (EN)가 포함될 수 있습니다. 전체 페이지 셸을 제공할 필요도 없으며 대신 부분 UI 템플릿으로 사용할 수 있습니다.

레이아웃 컴포넌트는 일반적으로 프로젝트의 src/layouts 디렉터리에 배치되지만 이는 필수 사항은 아닙니다. 프로젝트의 어느 곳에나 배치하도록 선택할 수 있습니다. 심지어 레이아웃 이름 앞에 _를 붙이면 (EN) 레이아웃 컴포넌트와 페이지를 같은 위치에 배치할 수도 있습니다.

src/layouts/MySiteLayout.astro
---
import BaseHead from '../components/BaseHead.astro';
import Footer from '../components/Footer.astro';
const { title } = Astro.props
---
<html lang="ko">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<BaseHead title={title}/>
</head>
<body>
<nav>
<a href="#"></a>
<a href="#">블로그</a>
<a href="#">연락처</a>
</nav>
<h1>{title}</h1>
<article>
<slot /> <!-- 콘텐츠가 여기에 삽입됩니다. -->
</article>
<Footer />
</body>
</html>
src/pages/index.astro
---
import MySiteLayout from '../layouts/MySiteLayout.astro';
---
<MySiteLayout title="Home Page">
<p>레이아웃으로 감싼 페이지입니다!</p>
</MySiteLayout>

📚 슬롯에 대해 자세히 알아보세요.

페이지 레이아웃은 페이지 형식이 없는 Markdown 및 MDX 페이지 (EN)에 특히 유용합니다.

Astro는 페이지 레이아웃으로 사용할 .astro 컴포넌트를 지정하기 위해 특별한 layout 프런트매터 속성을 제공합니다.

src/pages/page.md
---
layout: ../layouts/BaseLayout.astro
title: "안녕하세요!"
author: "Matthew Phillips"
date: "09 Aug 2022"
---
모든 프런트매터 속성은 Astro 레이아웃 컴포넌트에 대한 props로 사용할 수 있습니다.
`layout` 속성은 Astro에서 제공하는 유일한 특수 속성입니다.
`src/pages/` 디렉터리에 있는 Markdown 및 MDX 파일 모두에서 사용할 수 있습니다.

Markdown 또는 MDX 페이지의 일반적인 레이아웃은 다음과 같습니다.

  1. Markdown 또는 MDX 페이지의 프런트매터 및 기타 데이터를 사용하기 위한 frontmatter prop.
  2. 페이지의 Markdown/MDX 콘텐츠가 렌더링되어야 하는 위치를 나타내는 기본 <slot />.
src/layouts/BaseLayout.astro
---
// 1. 프런트매터 prop을 통해 프런트매터 및 기타 데이터를 사용할 수 있습니다.
const { frontmatter } = Astro.props;
---
<html>
<head>
<!-- 여기에 스타일, 메타 태그 등 다른 Head 요소를 추가하세요. -->
<title>{frontmatter.title}</title>
</head>
<body>
<!-- 일반적인 머리글 및 바닥글과 같은 다른 UI 컴포넌트를 여기에 추가합니다. -->
<h1>{frontmatter.title} by {frontmatter.author}</h1>
<!-- 2. 렌더링된 HTML은 기본 슬롯으로 전달됩니다. -->
<slot />
<p>작성: {frontmatter.date}</p>
</body>
</html>

MarkdownLayoutProps 또는 MDXLayoutProps 도우미를 사용하여 레이아웃의 Props 타입을 설정할 수 있습니다.

src/layouts/BaseLayout.astro
---
import type { MarkdownLayoutProps } from 'astro';
type Props = MarkdownLayoutProps<{
// 여기서 프런트매터 props를 정의하세요.
title: string;
author: string;
date: string;
}>;
// 이제 'frontmatter', 'url' 및 기타 Markdown 레이아웃 속성에 타입 안전성을 적용하여 사용할 수 있습니다.
const { frontmatter, url } = Astro.props;
---
<html>
<head>
<link rel="canonical" href={new URL(url, Astro.site).pathname}>
<title>{frontmatter.title}</title>
</head>
<body>
<h1>{frontmatter.title} - {frontmatter.author}</h1>
<slot />
<p>작성: {frontmatter.date}</p>
</body>
</html>

Markdown/MDX 레이아웃은 Astro.props를 통해 다음 정보를 사용할 수 있습니다.

  • file - 이 파일의 절대 경로(예: /home/user/projects/.../file.md).
  • url - 페이지인 경우 해당 페이지의 URL(예: /en/guides/markdown-content).
  • frontmatter - Markdown 또는 MDX 문서의 모든 프런트매터.
    • frontmatter.file - 최상위 file 속성과 동일합니다.
    • frontmatter.url - 최상위 url 속성과 동일합니다.
  • headings - 관련 메타데이터가 있는 Markdown 또는 MDX 문서의 제목(h1 -> h6)들의 목록입니다. 이 목록은 다음 타입을 따릅니다: { depth: number; slug: string; text: string }[]
  • (Markdown만 해당) rawContent() - 원시 Markdown 문서를 문자열로 반환하는 함수입니다.
  • (Markdown만 해당) compiledContent() - HTML 문자열로 컴파일된 Markdown 문서를 반환하는 함수입니다.

Markdown 블로그 게시물의 예는 다음과 같은 Astro.props 객체를 레이아웃에 전달할 수 있습니다.

Astro.props = {
file: "/home/user/projects/.../file.md",
url: "/en/guides/markdown-content/",
frontmatter: {
/** 블로그 게시물의 프런트매터 */
title: "Astro 0.18 릴리스",
date: "Tuesday, July 27 2021",
author: "Matthew Phillips",
description: "Astro 0.18은 Astro 출시 이후 가장 큰 릴리스입니다.",
/** 생성된 값 */
file: "/home/user/projects/.../file.md",
url: "/en/guides/markdown-content/"
},
headings: [
{
"depth": 1,
"text": "Astro 0.18 릴리스",
"slug": "astro-018-릴리스"
},
{
"depth": 2,
"text": "반응성 부분 수화",
"slug": "반응성-부분-수화"
}
/* ... */
],
/** Markdown에서만 사용 가능 */
rawContent: () => "# Astro 0.18 릴리스\n한 달 남짓 전에 첫 번째 공개 베타가 시작되었습니다. [...]",
compiledContent: () => "<h1>Astro 0.18 릴리스</h1>\n<p>한 달 남짓 전에 첫 번째 공개 베타가 시작되었습니다. [...]</p>",
}

수동으로 레이아웃 가져오기 (MDX)

섹션 제목: 수동으로 레이아웃 가져오기 (MDX)

프런트매터에 존재하지 않거나 존재할 수 없는 정보를 MDX 레이아웃에 전달해야 할 수도 있습니다. 이 경우 대신 <Layout /> 컴포넌트를 가져와 사용하고 다른 컴포넌트처럼 props를 전달할 수 있습니다.

src/pages/posts/first-post.mdx
---
layout: ../../layouts/BaseLayout.astro
title: '나의 첫 MDX 게시물'
publishDate: '21 September 2022'
---
import BaseLayout from '../../layouts/BaseLayout.astro';
function fancyJsHelper() {
return "YAML로 시도해 보세요!";
}
<BaseLayout title={frontmatter.title} fancyJsHelper={fancyJsHelper}>
MDX를 사용하는 새 Astro 블로그에 오신 것을 환영합니다!
</BaseLayout>

그러면 레이아웃의 Astro.props를 통해 값을 사용할 수 있으며 MDX 콘텐츠는 <slot /> 컴포넌트가 작성된 페이지에 삽입됩니다.

src/layouts/BaseLayout.astro
---
const { title, fancyJsHelper } = Astro.props;
---
<!-- -->
<h1>{title}</h1>
<slot /> <!-- 콘텐츠가 여기에 삽입됩니다 -->
<p>{fancyJsHelper()}</p>
<!-- -->

📚 Markdown/MDX 안내서 (EN)에서 Astro의 Markdown 및 MDX 지원에 대해 자세히 알아보세요.

.md, .mdx, .astro에 하나의 레이아웃 사용

섹션 제목: .md, .mdx, .astro에 하나의 레이아웃 사용

단일 Astro 레이아웃을 작성하여 .md.mdx 파일의 frontmatter 객체는 물론, .astro 파일에서 전달된 모든 명명된 props를 수신할 수 있습니다.

아래 예에서 레이아웃은 프런트매터 YAML title 속성 또는 title 속성을 전달하는 Astro 컴포넌트에서 페이지 제목을 표시합니다.

src/components/MyLayout.astro
---
const { title } = Astro.props.frontmatter || Astro.props;
---
<html>
<head></head>
<body>
<h1>{title}</h1>
<slot />
</body>
</html>

레이아웃 컴포넌트는 HTML의 전체 페이지를 포함할 필요가 없습니다. 레이아웃을 더 작은 컴포넌트로 나누고 레이아웃 컴포넌트를 결합하여 더욱 유연한 페이지 템플릿을 만들 수 있습니다. 이 패턴은 여러 레이아웃에서 일부 코드를 공유하려는 경우에 유용합니다.

예를 들어, BlogPostLayout.astro 레이아웃 컴포넌트는 게시물의 제목, 날짜, 작성자의 스타일을 지정할 수 있습니다. 그리고 사이트 전체 BaseLayout.astro가 탐색, 바닥글, SEO 메타 태그, 전역 스타일, 글꼴과 같은 페이지 템플릿의 나머지 부분을 처리할 수 있습니다. 또한, 다른 중첩 컴포넌트와 마찬가지로 게시물에서 받은 props를 다른 레이아웃으로 전달할 수도 있습니다.

src/layouts/BlogPostLayout.astro
---
import BaseLayout from './BaseLayout.astro'
const {frontmatter} = Astro.props;
---
<BaseLayout url={frontmatter.url}>
<h1>{frontmatter.title}</h1>
<h2>게시물 작성자: {frontmatter.author}</h2>
<slot />
</BaseLayout>