EmDash는 글, 페이지, 분류체계, 메뉴, 위젯, 미디어 라이브러리처럼 익숙한 WordPress 개념을 현대적인 Astro 스택으로 가져옵니다. 콘텐츠 관리 지식을 그대로 이어 쓸 수 있습니다.
그대로인 부분
WordPress에서 알고 있는 개념은 EmDash에서도 일급 기능입니다.
- Collections는 Custom Post Types처럼 동작합니다—콘텐츠 구조를 정의하고 템플릿에서 조회합니다
- Taxonomies도 마찬가지—계층형(카테고리처럼)과 평면형(태그처럼)
- Menus는 드래그 앤 드롭 순서와 중첩 항목
- Widget Areas는 사이드바와 동적 콘텐츠 영역용
- Media library는 업로드, 정리, 이미지 관리
- 코드를 건드리지 않고 쓸 수 있는 Admin UI
다른 점
구현은 바뀌지만 머릿속 모델은 같습니다.
PHP 대신 TypeScript
템플릿은 Astro 컴포넌트입니다. 문법은 더 깔끔하지만 개념은 같습니다—HTML을 출력하는 서버 코드입니다.
WP_Query 대신 Content API
getEmDashCollection() 같은 쿼리 함수가 WP_Query를 대체합니다. SQL 없이 함수 호출만 합니다.
파일 기반 라우팅
src/pages/의 파일이 URL이 됩니다. 리라이트 규칙이나 템플릿 계층을 외울 필요가 없습니다.
템플릿 파트 대신 컴포넌트
컴포넌트를 import해 사용합니다. get_template_part()와 같은 아이디어이며 구조가 더 좋습니다.
빠른 참조
| WordPress | EmDash | 비고 |
|---|---|---|
| Custom Post Types | Collections | 관리 UI 또는 API로 정의 |
WP_Query | getEmDashCollection() | 필터, 개수, 분류체계 쿼리 |
get_post() | getEmDashEntry() | 항목 또는 null 반환 |
| Categories/Tags | Taxonomies | 계층 지원 유지 |
register_nav_menus() | getMenu() | 일급 메뉴 지원 |
register_sidebar() | getWidgetArea() | 일급 위젯 영역 |
bloginfo('name') | getSiteSetting("title") | 사이트 설정 API |
the_content() | <PortableText /> | 구조화된 콘텐츠 렌더링 |
| Shortcodes | Portable Text blocks | 사용자 정의 컴포넌트 |
add_action/filter() | Plugin hooks | content:beforeSave 등 |
wp_options | ctx.kv | 키-값 저장 |
| Theme directory | src/ directory | 컴포넌트, 레이아웃, 페이지 |
functions.php | astro.config.mjs + EmDash config | 빌드 및 런타임 설정 |
Content API
컬렉션 조회
WordPress는 WP_Query나 헬퍼로 조회합니다. EmDash는 타입이 있는 쿼리 함수를 씁니다.
WordPress
<?php
$posts = new WP_Query([
'post_type' => 'post',
'posts_per_page' => 10,
'post_status' => 'publish',
'category_name' => 'news',
]);
while ($posts->have_posts()) :
$posts->the_post();
?>
<h2><?php the_title(); ?></h2>
<?php the_excerpt(); ?>
<?php endwhile; ?> EmDash
---
import { getEmDashCollection } from "emdash";
const { entries: posts } = await getEmDashCollection("posts", {
status: "published",
limit: 10,
where: { category: "news" },
});
---
{posts.map((post) => (
<article>
<h2>{post.data.title}</h2>
<p>{post.data.excerpt}</p>
</article>
))} 단일 항목 가져오기
WordPress
<?php
$post = get_post($id);
?>
<article>
<h1><?php echo $post->post_title; ?></h1>
<?php echo apply_filters('the_content', $post->post_content); ?>
</article> EmDash
---
import { getEmDashEntry } from "emdash";
import { PortableText } from "emdash/ui";
const { slug } = Astro.params;
const { entry: post } = await getEmDashEntry("posts", slug);
## if (!post) return Astro.redirect("/404");
<article>
<h1>{post.data.title}</h1>
<PortableText value={post.data.content} />
</article> 템플릿 계층
WordPress는 템플릿 계층으로 어떤 파일이 페이지를 그릴지 고릅니다. Astro는 명시적인 파일 기반 라우팅을 씁니다.
| WordPress Template | EmDash 대응 |
|---|---|
index.php | src/pages/index.astro |
single.php | src/pages/posts/[slug].astro |
single-{type}.php | src/pages/{type}/[slug].astro |
page.php | src/pages/pages/[slug].astro |
archive.php | src/pages/posts/index.astro |
archive-{type}.php | src/pages/{type}/index.astro |
category.php | src/pages/categories/[slug].astro |
tag.php | src/pages/tags/[slug].astro |
search.php | src/pages/search.astro |
404.php | src/pages/404.astro |
header.php / footer.php | src/layouts/Base.astro |
sidebar.php | src/components/Sidebar.astro |
템플릿 파트 → 컴포넌트
WordPress 템플릿 파트는 Astro 컴포넌트가 됩니다.
WordPress
// In template:
get_template_part('template-parts/content', 'post');
// template-parts/content-post.php:
<article class="post">
<h2><?php the_title(); ?></h2>
<?php the_excerpt(); ?>
</article> EmDash
---
const { post } = Astro.props;
---
<article class="post">
<h2>{post.data.title}</h2>
<p>{post.data.excerpt}</p>
</article>---
import PostCard from "../components/PostCard.astro";
import { getEmDashCollection } from "emdash";
const { entries: posts } = await getEmDashCollection("posts");
---
{posts.map((post) => <PostCard {post} />)} 메뉴
EmDash는 URL이 자동으로 풀리는 일급 메뉴 지원이 있습니다.
WordPress
<?php
wp_nav_menu([
'theme_location' => 'primary',
'container' => 'nav',
]);
?> EmDash
---
import { getMenu } from "emdash";
## const menu = await getMenu("primary");
<nav>
<ul>
{menu?.items.map((item) => (
<li>
<a href={item.url}>{item.label}</a>
</li>
))}
</ul>
</nav> 메뉴는 관리 UI, 시드 파일, 또는 WordPress 가져오기로 만듭니다.
위젯 영역
위젯 영역은 WordPress 사이드바와 비슷하게 동작합니다.
WordPress
<?php if (is_active_sidebar('sidebar-1')) : ?>
<aside>
<?php dynamic_sidebar('sidebar-1'); ?>
</aside>
<?php endif; ?> EmDash
---
import { getWidgetArea } from "emdash";
import { PortableText } from "emdash/ui";
## const sidebar = await getWidgetArea("sidebar");
{sidebar && (
<aside>
{sidebar.widgets.map((widget) => {
if (widget.type === "content") {
return <PortableText value={widget.content} />;
}
// Handle other widget types
})}
</aside>
)} 사이트 설정
사이트 옵션과 커스터마이저 설정은 getSiteSetting()에 대응합니다.
| WordPress | EmDash |
|---|---|
bloginfo('name') | getSiteSetting("title") |
bloginfo('description') | getSiteSetting("tagline") |
get_custom_logo() | getSiteSetting("logo") |
get_option('date_format') | getSiteSetting("dateFormat") |
home_url() | Astro.site |
import { getSiteSetting } from "emdash";
const title = await getSiteSetting("title");
const logo = await getSiteSetting("logo"); // Returns { mediaId, alt, url }
분류체계
개념은 같습니다—계층형(카테고리처럼) 또는 평면형(태그처럼).
import { getTaxonomyTerms, getEntryTerms, getTerm } from "emdash";
// Get all categories
const categories = await getTaxonomyTerms("categories");
// Get a specific term
const news = await getTerm("categories", "news");
// Get terms for a post
const postCategories = await getEntryTerms("posts", postId, "categories");
Hooks → 플러그인 시스템
WordPress 훅(add_action, add_filter)은 EmDash 플러그인 훅이 됩니다.
| WordPress Hook | EmDash Hook | 목적 |
|---|---|---|
save_post | content:beforeSave | 저장 전 콘텐츠 수정 |
the_content | PortableText components | 렌더된 콘텐츠 변환 |
pre_get_posts | Query options | 쿼리 필터 |
wp_head | Layout <head> | head에 콘텐츠 추가 |
wp_footer | Layout before </body> | 푸터에 콘텐츠 추가 |
EmDash에서 더 나은 점
타입 안전
전반에 TypeScript. 컬렉션, 쿼리, 컴포넌트가 모두 타입이 있습니다. 필드 이름이나 반환 타입을 더 이상 추측하지 않아도 됩니다.
성능
PHP 오버헤드 없음. 기본은 정적 생성. 필요 시 서버 렌더링. 엣지 배포에도 적합합니다.
모던 DX
Hot module replacement. 컴포넌트 기반 구조. Vite, TypeScript, ESLint 같은 현대 도구.
Git 기반 배포
코드와 템플릿은 git에. 콘텐츠는 DB에. FTP나 파일 권한, 해킹된 사이트 걱정이 줄어듭니다.
미리보기 링크
EmDash는 HMAC 서명 토큰이 있는 안전한 미리보기 URL을 만듭니다. 편집자는 프로덕션에 로그인하지 않고 초안을 볼 수 있습니다—링크만 공유하면 되고 자격 증명은 필요 없습니다.
플러그인 충돌 없음
WordPress식 플러그인 충돌이 사라집니다. EmDash 플러그인은 명시적 API가 있는 격리된 컨텍스트에서 실행됩니다. 전역 상태 오염이 없습니다.
콘텐츠 편집자 경험
편집자는 wp-admin과 비슷한 EmDash 관리 패널을 씁니다.
- 최근 활동이 있는 Dashboard
- 검색, 필터, 일괄 작업이 있는 컬렉션 목록
- 콘텐츠용 리치 에디터(Portable Text, Gutenberg 아님)
- 드래그 앤 드롭 업로드 미디어 라이브러리
- 드래그 앤 드롭 순서 메뉴 빌더
- 사이드바 콘텐츠용 위젯 영역 에디터
편집 경험은 익숙하고, 아래 기술은 현대적입니다.
마이그레이션 경로
EmDash는 WordPress 콘텐츠를 직접 가져옵니다.
- WordPress에서보내기(도구 →보내기)
.xml파일을 EmDash 관리자에 업로드- 글 유형을 컬렉션에 매핑
- 콘텐츠와 미디어 가져오기
글, 페이지, 분류체계, 메뉴, 미디어가 옮겨집니다. Gutenberg 블록은 Portable Text로 변환됩니다. 사용자 정의 필드는 분석되어 매핑됩니다.
전체 절차는 WordPress 마이그레이션 가이드를 참고하세요.
다음 단계
- Getting Started — 첫 EmDash 사이트 설정
- Querying Content — Content API 심화
- Taxonomies — 카테고리, 태그, 사용자 정의 분류체계
- Menus — 내비게이션 메뉴
- Migrate from WordPress — 기존 콘텐츠 가져오기