기본적으로 서버 렌더링
PHP와 마찬가지로, Astro 코드는 서버에서 실행됩니다. PHP와 달리, 기본적으로 JavaScript 없이 정적 HTML을 출력합니다.
Astro는 콘텐츠 중심 웹사이트를 구축하기 위한 웹 프레임워크입니다. EmDash를 사용할 때, Astro는 WordPress 테마를 대체합니다—템플릿, 라우팅, 렌더링을 처리합니다.
이 가이드는 여러분이 이미 이해하고 있는 WordPress 개념에 매핑하여 Astro의 기본 사항을 가르칩니다.
기본적으로 서버 렌더링
PHP와 마찬가지로, Astro 코드는 서버에서 실행됩니다. PHP와 달리, 기본적으로 JavaScript 없이 정적 HTML을 출력합니다.
명시적으로 추가하지 않는 한 JavaScript 없음
WordPress는 jQuery와 테마 스크립트를 자동으로 로드합니다. Astro는 명시적으로 추가하지 않는 한 브라우저에 아무것도 전송하지 않습니다.
컴포넌트 기반 아키텍처
분산된 템플릿 태그와 인클루드 대신, 구성 가능하고 독립적인 컴포넌트로 구축하세요.
파일 기반 라우팅
리라이트 규칙이나 query_vars가 필요 없습니다. src/pages/의 파일 구조가 직접 URL을 정의합니다.
WordPress 테마는 마법 같은 파일명을 가진 평면 구조를 사용합니다. Astro는 명시적인 디렉토리를 사용합니다:
| WordPress | Astro | 목적 |
|---|---|---|
index.php, single.php | src/pages/ | 라우트 (URL) |
template-parts/ | src/components/ | 재사용 가능한 UI 조각 |
header.php + footer.php | src/layouts/ | 페이지 래퍼 |
style.css | src/styles/ | 전역 CSS |
functions.php | astro.config.mjs | 사이트 설정 |
일반적인 Astro 프로젝트:
src/├── components/ # Reusable UI (Header, PostCard, etc.)├── layouts/ # Page shells (Base.astro)├── pages/ # Routes - files become URLs│ ├── index.astro # → /│ ├── posts/│ │ ├── index.astro # → /posts│ │ └── [slug].astro # → /posts/hello-world│ └── [slug].astro # → /about, /contact, etc.└── styles/ └── global.css.astro 파일은 PHP 템플릿에 해당하는 Astro의 파일입니다. 각 파일은 두 부분으로 구성됩니다:
--- 펜스 사이) — 서버 측 코드, 템플릿 상단의 PHP와 유사astro title="src/components/PostCard.astro"---// Frontmatter: runs on server, never sent to browserinterface Props { title: string; excerpt: string; url: string;}
const { title, excerpt, url } = Astro.props;---<!-- Template: outputs HTML --><article class="post-card"> <h2><a href={url}>{title}</a></h2> <p>{excerpt}</p></article>PHP와의 주요 차이점:
interface Props로 프로퍼티 타입을 정의하여 에디터 자동 완성과 검증을 사용하세요.Astro 템플릿은 <?php ?> 태그 대신 {curly braces}를 사용합니다. 구문은 JSX와 유사하지만 순수 HTML을 출력합니다.
astro title="src/components/PostList.astro"---import { getEmDashCollection } from "emdash";
const { entries: posts } = await getEmDashCollection("posts");const showTitle = true;---{showTitle && <h1>최신 게시물</h1>}
{posts.length > 0 ? ( <ul> {posts.map(post => ( <li> <a href={`/posts/${post.id}`}>{post.data.title}</a> </li> ))} </ul>) : ( <p>게시물이 없습니다.</p>)}php title="template-parts/post-list.php"<?php$posts = new WP_Query(['post_type' => 'post']);$show_title = true;?>
<?php if ($show_title): ?> <h1>최신 게시물</h1><?php endif; ?>
<?php if ($posts->have_posts()): ?> <ul> <?php while ($posts->have_posts()): $posts->the_post(); ?> <li> <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a> </li> <?php endwhile; wp_reset_postdata(); ?> </ul><?php else: ?> <p>게시물이 없습니다.</p><?php endif; ?>| 패턴 | 목적 |
|---|---|
{variable} | 값 출력 |
{condition && <Element />} | 조건부 렌더링 |
{condition ? <A /> : <B />} | If/else |
{items.map(item => <Li>{item}</Li>)} | 반복문 |
컴포넌트는 프로퍼티(함수 인수와 유사)와 슬롯(do_action 삽입 지점과 유사)을 통해 데이터를 받습니다.
astro title="src/components/Card.astro"---interface Props { title: string; featured?: boolean;}
const { title, featured = false } = Astro.props;---
<article class:list={["card", { featured }]}> <h2>{title}</h2> <slot /> <slot name="footer" /></article>사용법:
<Card title="Hello" featured> <p>This goes in the default slot.</p> <footer slot="footer">Footer content</footer></Card>php title="template-parts/card.php"<?php// Usage: get_template_part('template-parts/card', null, [// 'title' => 'Hello',// 'featured' => true// ]);
$title = $args['title'] ?? '';$featured = $args['featured'] ?? false;$class = $featured ? 'card featured' : 'card';?><article class="<?php echo esc_attr($class); ?>"> <h2><?php echo esc_html($title); ?></h2> <?php // 슬롯에 직접 대응하는 것은 없습니다. // WordPress는 유사한 패턴에 do_action()을 사용합니다: do_action('card_content'); do_action('card_footer'); ?></article>$argsWordPress에서 get_template_part()는 $args 배열을 통해 데이터를 전달합니다. Astro 프로퍼티는 타입이 지정되고 구조 분해됩니다:
---// Type-safe with defaultsinterface Props { title: string; count?: number;}const { title, count = 10 } = Astro.props;---WordPress는 do_action()을 사용하여 삽입 지점을 만듭니다. Astro는 슬롯을 사용합니다:
| WordPress | Astro |
|---|---|
do_action('before_content') | <slot name="before" /> |
| 기본 콘텐츠 영역 | <slot /> |
do_action('after_content') | <slot name="after" /> |
차이점: 슬롯은 호출 지점에서 자식 요소를 받는 반면, WordPress 훅은 별도의 add_action() 호출이 다른 곳에 필요합니다.
레이아웃은 공통 HTML 구조—<head>, 헤더, 푸터, 그리고 페이지 간 공유되는 모든 것—로 페이지를 감쌉니다. 이는 header.php + footer.php를 대체합니다.
astro title="src/layouts/Base.astro"---import "../styles/global.css";
interface Props { title: string; description?: string;}
const { title, description = "My EmDash Site" } = Astro.props;---<!doctype html><html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="description" content={description} /> <title>{title}</title> </head> <body> <header> <nav><!-- Navigation --></nav> </header>
<main> <slot /> </main>
<footer> <p>© {new Date().getFullYear()}</p> </footer> </body></html>레이아웃을 페이지에서 사용하기:
astro title="src/pages/index.astro"---import Base from "../../layouts/Base.astro";---<Base title="홈"> <h1>환영합니다</h1> <p>페이지 콘텐츠는 slot 안에 들어갑니다.</p></Base>Astro는 여러 가지 스타일링 접근 방식을 제공합니다. 가장 독특한 것은 스코프 스타일입니다.
<style> 태그 내의 스타일은 자동으로 해당 컴포넌트에만 적용됩니다:
astro title="src/components/Card.astro"<article class="card"> <h2>Title</h2></article>
<style> /* 이 컴포넌트의 .card에만 영향을 줍니다 */ .card { padding: 1rem; border: 1px solid #ddd; }
h2 { color: navy; }</style>생성된 HTML에는 스타일 누출을 방지하기 위해 고유한 클래스 이름이 포함됩니다. 더 이상 특이성 전쟁은 없습니다.
사이트 전체 스타일의 경우 CSS 파일을 생성하고 레이아웃에서 가져옵니다:
astro title="src/layouts/Base.astro"---import "../styles/global.css";---class:list 지시문은 수동 클래스 문자열 구성을 대체합니다:
---const { featured, size = "medium" } = Astro.props;---<article class:list={[ "card", size, { featured, "has-border": true }]}>출력: <article class="card medium featured has-border">
php<?php$classes = ['card', $size];if ($featured) $classes[] = 'featured';if (true) $classes[] = 'has-border';?><article class="<?php echo esc_attr(implode(' ', $classes)); ?>">Astro는 기본적으로 JavaScript를 전혀 제공하지 않습니다. 이것이 WordPress와의 가장 큰 사고 방식 전환입니다.
간단한 상호작용의 경우 <script> 태그를 추가하세요:
astro title="src/components/MobileMenu.astro"<button id="menu-toggle">Menu</button><nav id="mobile-menu" hidden> <slot /></nav>
<script> const toggle = document.getElementById("menu-toggle"); const menu = document.getElementById("mobile-menu");
toggle?.addEventListener("click", () => { menu?.toggleAttribute("hidden"); });</script>스크립트는 자동으로 번들링되고 중복 제거됩니다. 이 컴포넌트가 페이지에 두 번 나타나면 스크립트는 한 번만 실행됩니다.
더 복잡한 상호작용을 위해 Astro는 필요 시 JavaScript 컴포넌트(React, Vue, Svelte)를 로드할 수 있습니다. 이는 선택 사항입니다—대부분의 사이트는 <script> 태그만으로도 잘 작동합니다.
astro title="src/pages/index.astro"---import SearchWidget from "../../components/SearchWidget.jsx";---<!-- Only load JavaScript when the search box scrolls into view --><SearchWidget client:visible />| 지시문 | JavaScript 로드 시점 |
|---|---|
client:load | 페이지 로드 시 즉시 |
client:visible | 컴포넌트가 뷰포트에 들어올 때 |
client:idle | 브라우저가 유휴 상태일 때 |
Astro는 파일 기반 라우팅을 사용합니다. src/pages/의 파일이 URL이 됩니다:
| 파일 | URL |
|---|---|
src/pages/index.astro | / |
src/pages/about.astro | /about |
src/pages/posts/index.astro | /posts |
src/pages/posts/[slug].astro | /posts/hello-world |
src/pages/[...slug].astro | 모든 경로 (캐치올) |
CMS 콘텐츠의 경우, 동적 세그먼트에 대해 대괄호 구문을 사용하세요:
astro title="src/pages/posts/[slug].astro"---import { getEmDashCollection, getEmDashEntry } from "emdash";import Base from "../../../layouts/Base.astro";import { PortableText } from "emdash/ui";
// For static builds, define which pages to generateexport async function getStaticPaths() { const { entries: posts } = await getEmDashCollection("posts"); return posts.map(post => ({ params: { slug: post.id }, props: { post }, }));}
const { post } = Astro.props;---<Base title={post.data.title}> <article> <h1>{post.data.title}</h1> <PortableText value={post.data.content} /> </article></Base>| WordPress | Astro |
|---|---|
템플릿 계층 구조 (single-post.php) | 명시적 파일: posts/[slug].astro |
리라이트 규칙 + query_vars | 파일 구조 |
$wp_query가 템플릿 결정 | URL이 파일에 직접 매핑 |
add_rewrite_rule() | 파일 또는 폴더 생성 |
WordPress 기능에 해당하는 Astro/EmDash 기능을 찾기 위한 참조 자료:
| WordPress | Astro/EmDash |
|---|---|
| 템플릿 계층 구조 | src/pages/의 파일 기반 라우팅 |
get_template_part() | 컴포넌트 가져오기 및 사용 |
the_content() | <PortableText value={content} /> |
the_title(), the_*() | post.data.title를 통해 접근 |
| 템플릿 태그 | 템플릿 표현식 {value} |
body_class() | class:list 지시문 |
| WordPress | Astro/EmDash |
|---|---|
WP_Query | getEmDashCollection(type, filters) |
get_post() | getEmDashEntry(type, id) |
get_posts() | getEmDashCollection(type) |
get_the_terms() | entry.data.categories를 통해 접근 |
get_post_meta() | entry.data.fieldName을 통해 접근 |
get_option() | getSiteSettings() |
wp_nav_menu() | getMenu(location) |
| WordPress | Astro/EmDash |
|---|---|
add_action() | EmDash 훅, Astro 미들웨어 |
add_filter() | EmDash 훅 |
add_shortcode() | Portable Text 사용자 정의 블록 |
register_block_type() | Portable Text 사용자 정의 블록 |
register_sidebar() | EmDash 위젯 영역 |
| 플러그인 | Astro 통합 + EmDash 플러그인 |
| WordPress | Astro/EmDash |
|---|---|
register_post_type() | 관리자 UI에서 컬렉션 생성 |
register_taxonomy() | 관리자 UI에서 분류 생성 |
register_meta() | 컬렉션 스키마에 필드 추가 |
| 게시물 상태 | 항목 상태 (초안, 게시됨 등) |
| 대표 이미지 | 미디어 참조 필드 |
| Gutenberg 블록 | Portable Text 블록 |
WordPress에서 Astro로의 전환은 상당하지만 논리적입니다:
시작하기 가이드로 첫 EmDash 사이트를 구축하거나, 콘텐츠 작업하기를 탐색하여 CMS 데이터를 쿼리하고 렌더링하는 방법을 배워보세요.