스토리지 옵션

이 페이지

EmDash는 업로드된 미디어(이미지, 문서, 비디오)를 구성 가능한 스토리지 백엔드에 저장합니다. 배포 플랫폼과 요구 사항에 따라 선택하세요.

개요

스토리지최적 용도기능
R2 BindingCloudflare 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" }),
		}),
	],
});

구성

옵션타입설명
bindingstringwrangler.jsonc의 R2 바인딩 이름
publicUrlstring버킷의 선택적 공개 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 버킷에서 공개 액세스를 활성화하세요:

  1. Cloudflare 대시보드 > R2 > 버킷으로 이동
  2. 설정에서 공개 액세스 활성화
  3. 구성에 공개 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
			}),
		}),
	],
});

구성

옵션타입필수설명
endpointstringS3 엔드포인트 URL
bucketstring버킷 이름
accessKeyIdstring아니오*액세스 키
secretAccessKeystring아니오*시크릿 키
regionstring아니오리전(기본값: "auto")
publicUrlstring아니오선택적 CDN 또는 공개 URL

* accessKeyIdsecretAccessKey는 함께 제공되거나 둘 다 생략되어야 합니다.

환경 변수에서 S3 구성 해결

s3({...})에서 생략된 필드는 프로세스가 시작될 때 일치하는 S3_* 환경 변수에서 읽습니다. 이를 통해 컨테이너 이미지를 한 번 빌드하고 재빌드 없이 부팅 시 자격 증명을 주입할 수 있습니다. s3({...})의 명시적 값은 항상 환경 변수보다 우선합니다.

환경 변수필드참고
S3_ENDPOINTendpoint유효한 http/https URL이어야 합니다
S3_BUCKETbucket
S3_ACCESS_KEY_IDaccessKeyId
S3_SECRET_ACCESS_KEYsecretAccessKey
S3_REGIONregion기본값: "auto"
S3_PUBLIC_URLpublicUrl선택적 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",
			}),
		}),
	],
});

구성

옵션타입설명
directorystring파일 스토리지용 디렉토리 경로
baseUrlstring파일 제공을 위한 기본 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;
}

이러한 일관성으로 애플리케이션 코드를 변경하지 않고 스토리지 백엔드를 전환할 수 있습니다.