EmDash 플러그인은 sandboxed 또는 native 두 형식 중 하나를 사용합니다. 작성 형태, 설치 경로, 신뢰 경계가 다르므로 플러그인을 쓰기 전에 형식을 선택하세요.
플러그인이 native 전용 통합이 필요하지 않다면 sandboxed 플러그인을 선택하세요. sandboxed 플러그인은 레지스트리에 게시하고 관리 UI에서 설치할 수 있습니다. native 플러그인은 사이트 운영자가 프로젝트에 설치하고 재배포 전에 astro.config.mjs에 추가하는 npm 패키지입니다.
한눈에 보기
| Sandboxed | Native | |
|---|---|---|
| Authoring shape | emdash-plugin.jsonc + src/plugin.ts | definePlugin() descriptor |
| Install method | One-click from the admin registry | npm install + edit astro.config |
| Runs in | An isolated runtime provided by a sandbox runner | Same process as your Astro site |
Capability-gated ctx APIs | Enforced by the sandbox bridge | Gated by PluginContext, but not a security boundary |
| Resource limits | Runner limits for CPU, subrequests, and wall time; platform memory ceiling | No per-plugin limits |
| Network access | ctx.http, restricted to declared access | ctx.http follows declarations; native code can also call fetch() |
Direct fetch() / process.env | Blocked by the runner | Possible (plugin code shares the runtime) |
| Distribution | Signed release in the plugin registry | npm package |
| Admin UI | Block Kit (JSON-described) routes | React components, or Block Kit |
| Settings UI | Block Kit page + ctx.settings | admin.settingsSchema (auto-form) or Block Kit |
| Portable Text rendering components | Not available | componentsEntry provides Astro components |
| Page metadata contributions | page:metadata hook — meta/property tags, allowlisted <link> rels, JSON-LD | page:metadata hook (same surface) |
| Page fragment injection | Not available — meta/JSON-LD only via page:metadata | page:fragments hook — inline scripts, external scripts, raw HTML |
| Constructor options | None — read settings from KV at runtime | options on the descriptor |
native 플러그인의 비용
native 플러그인은 설치와 신뢰 모델이 다릅니다.
- 프로젝트 수준 설치. 모든 사이트가 npm 패키지를 설치하고
astro.config.mjs를 편집한 뒤 재배포해야 합니다. - 격리 없음. 플러그인의 버그가 호스트 프로세스를 크래시시키거나 CPU 예산을 소모할 수 있습니다. 훅의 처리되지 않은 rejection이 주변 요청까지 함께 무너뜨릴 수 있습니다.
- 사용자 측 신뢰 부담. native 플러그인은 호스트 사이트와 동일한 접근 권한을 가집니다. 기능 선언만으로는 코드가 할 수 있는 모든 것을 보여줄 수 없습니다.
플러그인이 샌드박스에서 일을 할 수 있다면 그렇게 해야 합니다.
native로 갈 때
호스트 사이트와의 빌드 타임 통합이 필요한 기능에는 native를 선택하세요.
-
사용자 정의 React 관리 페이지 또는 위젯. sandboxed 플러그인은 관리 UI를 Block Kit — 관리 화면이 플러그인 대신 렌더링하는 JSON 스키마 — 로 설명합니다. 전체 React(사용자 정의 훅, 서드파티 컴포넌트, 복잡한 상태)가 필요하면 native가 필요합니다.
-
사용자 정의 Portable Text 블록 타입. 편집 구성과 Astro 렌더링 컴포넌트는 설치된 npm 패키지에서 로드됩니다. 그 빌드 타임 표면을 제공할 수 있는 것은 native 플러그인뿐입니다.
-
공개 페이지에 원시 HTML, 스크립트, 스타일시트 주입.
page:fragments훅은 방문자의 브라우저에 퍼스트파티 코드를 보냅니다 — 어떤 샌드박스 경계 밖에서도. native 플러그인으로 제한됩니다. sandboxed 플러그인은 많은 실제 사용 사례를 다루는page:metadata훅을 통해 공개 페이지에 계속 기여할 수 있습니다.meta태그(name+content) — SEO 설명, robots 지시문, Twitter 카드property태그 — OpenGraph 및 기타 property 기반 메타- 보안으로 잠긴 rel 허용 목록이 있는
link태그(canonical,alternate,author,license,nlweb,site.standard.document) —stylesheet,prefetch및 유사한 리소스 로딩 rel은 의도적으로 허용되지 않습니다 - JSON-LD 그래프
「페이지 주입」 필요가 구조화된 데이터나 SEO 메타데이터라면 sandboxed를 유지하고
page:metadata를 사용하세요. 실제로 방문자의 브라우저에 JavaScript나 HTML을 보내야 한다면 그것이 native로 가는 경우입니다.
이러한 기능이 하나도 해당되지 않으면 sandboxed 형식을 사용하세요.
샌드박스 러너와 플랫폼 지원
샌드박스 자체는 교체 가능합니다. EmDash는 sandboxRunner 구성 옵션을 노출하고, 러너가 플러그인 코드를 어떻게 격리할지 결정합니다 — 플러그인 형식 자체에는 Cloudflare 고유의 것이 없습니다.
EmDash와 함께 두 러너가 제공됩니다. @emdash-cms/cloudflare의 sandbox()는 Cloudflare Worker Loader를 통해 각 플러그인을 Dynamic Worker로 실행하고, @emdash-cms/sandbox-workerd/sandbox는 Node.js의 workerd 자식 프로세스에서 플러그인을 실행합니다. Plugin Sandbox에서 각 러너 설정, 적용하는 리소스 한도, 둘의 차이를 다룹니다.
러너가 구성되지 않으면 sandboxed: []에 나열된 플러그인은 로드되지 않습니다. 구성된 러너가 현재 플랫폼에서 사용할 수 없어도 로드되지 않으며, EmDash는 시작 시 경고를 기록합니다.
샌드박스 러너가 없는 플랫폼에서 sandboxed 플러그인을 실행하려면 sandboxed: []에서 plugins: [] 배열로 옮기세요 — 인프로세스로 실행됩니다. 기능 선언은 계속 존중됩니다(같은 PluginContext 팩토리가 ctx.content, ctx.http 등을 게이트합니다)만, 격리 경계도 리소스 한도도 없고, 버그 있거나 악의적인 플러그인이 fetch()를 직접 호출하고, 환경 변수를 읽고, 이벤트 루프를 차단할 수 있습니다. 샌드박스 러너가 활성이지 않으면 신뢰 목적상 모든 플러그인을 native 플러그인으로 취급하세요.