EmDash는 업로드된 미디어(이미지, 문서, 비디오)를 구성 가능한 스토리지 백엔드에 저장합니다. 배포 플랫폼과 요구 사항에 따라 선택하세요.
개요
| 스토리지 | 최적 용도 | 기능 |
|---|---|---|
| R2 Binding | Cloudflare Workers | 제로 설정, 빠름 |
| S3 | 모든 플랫폼 | 서명된 업로드, CDN 지원 |
| Local | 개발 | 간단한 파일 시스템 스토리지 |
Cloudflare R2 (Binding)
가장 빠른 통합을 위해 Cloudflare Workers에 배포할 때 R2 바인딩을 사용하세요.
import emdash from "emdash/astro";
import { r2 } from "@emdash-cms/cloudflare";
export default defineConfig({
integrations: [
emdash({
storage: r2({ binding: "MEDIA" }),
}),
],
});
구성
| 옵션 | 타입 | 설명 |
|---|---|---|
binding | string | wrangler.jsonc의 R2 바인딩 이름 |
publicUrl | string | 버킷의 선택적 공개 URL |
설정
Wrangler 구성에 R2 바인딩을 추가하세요:
wrangler.jsonc
{
"r2_buckets": [
{
"binding": "MEDIA",
"bucket_name": "emdash-media"
}
]
} wrangler.toml
[[r2_buckets]]
binding = "MEDIA"
bucket_name = "emdash-media" 공개 액세스
공개 미디어 URL을 위해 R2 버킷에서 공개 액세스를 활성화하세요:
- Cloudflare 대시보드 > R2 > 버킷으로 이동
- 설정에서 공개 액세스 활성화
- 구성에 공개 URL 추가:
storage: r2({
binding: "MEDIA",
publicUrl: "https://pub-xxxx.r2.dev",
});
S3 호환 스토리지
S3 어댑터는 Cloudflare R2(S3 API 경유), MinIO 및 기타 S3 호환 서비스와 함께 작동합니다.
다음 구성은 EmDash를 S3 호환 버킷으로 지정합니다:
import emdash, { s3 } from "emdash/astro";
export default defineConfig({
integrations: [
emdash({
storage: s3({
endpoint: process.env.S3_ENDPOINT,
bucket: process.env.S3_BUCKET,
accessKeyId: process.env.S3_ACCESS_KEY_ID,
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY,
region: "auto", // Optional, defaults to "auto"
publicUrl: process.env.S3_PUBLIC_URL, // Optional CDN URL
}),
}),
],
});
구성
| 옵션 | 타입 | 필수 | 설명 |
|---|---|---|---|
endpoint | string | 예 | S3 엔드포인트 URL |
bucket | string | 예 | 버킷 이름 |
accessKeyId | string | 아니오* | 액세스 키 |
secretAccessKey | string | 아니오* | 시크릿 키 |
region | string | 아니오 | 리전(기본값: "auto") |
publicUrl | string | 아니오 | 선택적 CDN 또는 공개 URL |
* accessKeyId와 secretAccessKey는 함께 제공되거나 둘 다 생략되어야 합니다.
환경 변수에서 S3 구성 해결
s3({...})에서 생략된 필드는 프로세스가 시작될 때 일치하는 S3_* 환경 변수에서 읽습니다. 이를 통해 컨테이너 이미지를 한 번 빌드하고 재빌드 없이 부팅 시 자격 증명을 주입할 수 있습니다. s3({...})의 명시적 값은 항상 환경 변수보다 우선합니다.
| 환경 변수 | 필드 | 참고 |
|---|---|---|
S3_ENDPOINT | endpoint | 유효한 http/https URL이어야 합니다 |
S3_BUCKET | bucket | |
S3_ACCESS_KEY_ID | accessKeyId | |
S3_SECRET_ACCESS_KEY | secretAccessKey | |
S3_REGION | region | 기본값: "auto" |
S3_PUBLIC_URL | publicUrl | 선택적 CDN 접두사 |
환경 변수는 프로세스가 시작될 때 process.env에서 읽습니다. 이것은 Node 전용 기능입니다.
인수 없이 s3()를 호출하면 S3_* 환경 변수에서 모든 필드를 읽습니다:
import emdash, { s3 } from "emdash/astro";
export default defineConfig({
integrations: [
emdash({
// 인수 없는 s3(): S3_* 환경 변수의 모든 필드
storage: s3(),
// 또는 혼합: 하나의 필드 재정의, 나머지는 환경에서
// storage: s3({ publicUrl: "https://cdn.example.com" }),
}),
],
});
S3 API를 통한 R2
서명된 업로드 URL과 같은 기능을 위해 R2와 함께 S3 자격 증명을 사용하세요:
storage: s3({
endpoint: "https://<account-id>.r2.cloudflarestorage.com",
bucket: "emdash-media",
accessKeyId: process.env.R2_ACCESS_KEY_ID,
secretAccessKey: process.env.R2_SECRET_ACCESS_KEY,
publicUrl: "https://pub-xxxx.r2.dev",
});
Cloudflare 대시보드의 R2 > Manage R2 API Tokens에서 R2 API 자격 증명을 생성하세요.
MinIO
액세스 자격 증명으로 S3 어댑터를 MinIO 엔드포인트로 지정하세요:
storage: s3({
endpoint: "https://minio.example.com",
bucket: "emdash-media",
accessKeyId: process.env.MINIO_ACCESS_KEY,
secretAccessKey: process.env.MINIO_SECRET_KEY,
publicUrl: "https://minio.example.com/emdash-media",
});
로컬 파일 시스템
개발을 위해 로컬 스토리지를 사용하세요. 파일은 디스크의 디렉토리에 저장됩니다.
import emdash, { local } from "emdash/astro";
export default defineConfig({
integrations: [
emdash({
storage: local({
directory: "./uploads",
baseUrl: "/_emdash/api/media/file",
}),
}),
],
});
구성
| 옵션 | 타입 | 설명 |
|---|---|---|
directory | string | 파일 스토리지용 디렉토리 경로 |
baseUrl | string | 파일 제공을 위한 기본 URL |
사용자 정의 정적 파일 서버를 구성하지 않는 한 baseUrl은 EmDash의 미디어 파일 엔드포인트(/_emdash/api/media/file)와 일치해야 합니다.
환경 기반 구성
환경에 따라 스토리지 백엔드를 전환하세요:
import emdash, { s3, local } from "emdash/astro";
import { r2 } from "@emdash-cms/cloudflare";
const storage = import.meta.env.PROD
? r2({ binding: "MEDIA" })
: local({
directory: "./uploads",
baseUrl: "/_emdash/api/media/file",
});
export default defineConfig({
integrations: [emdash({ storage })],
});
서명된 업로드
S3 어댑터는 서명된 업로드 URL을 지원하여 클라이언트가 서버를 거치지 않고 스토리지에 직접 업로드할 수 있습니다. 이는 큰 파일의 성능을 향상시킵니다.
서명된 업로드는 S3 어댑터를 사용할 때 자동으로 수행됩니다. 관리 인터페이스는 사용 가능할 때 이를 사용합니다.
서명된 업로드를 지원하는 어댑터:
- S3(S3 API를 통한 R2 포함)
서명된 업로드를 지원하지 않는 어댑터:
- R2 binding(대신 R2 자격 증명으로 S3 어댑터 사용)
- Local
Storage 인터페이스
모든 스토리지 어댑터는 동일한 인터페이스를 구현합니다:
interface Storage {
upload(options: {
key: string;
body: Buffer | Uint8Array | ReadableStream;
contentType: string;
}): Promise<UploadResult>;
download(key: string): Promise<DownloadResult>;
delete(key: string): Promise<void>;
exists(key: string): Promise<boolean>;
list(options?: ListOptions): Promise<ListResult>;
getSignedUploadUrl(options: SignedUploadOptions): Promise<SignedUploadUrl>;
getPublicUrl(key: string): string;
}
이러한 일관성으로 애플리케이션 코드를 변경하지 않고 스토리지 백엔드를 전환할 수 있습니다.