스토리지 옵션

이 페이지

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

개요

스토리지적합한 용도특징
R2 바인딩Cloudflare Workers설정 불필요, 빠름
S3모든 플랫폼서명된 업로드, CDN 지원
로컬개발간단한 파일 시스템 스토리지

Cloudflare R2 (바인딩)

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 호환 서비스에서 작동합니다.

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 전용입니다.

import emdash, { s3 } from "emdash/astro";

export default defineConfig({
	integrations: [
		emdash({
			// s3() with no args: all fields from S3_* environment variables
			storage: s3(),

			// Or mix: override one field, rest from environment
			// storage: s3({ publicUrl: "https://cdn.example.com" }),
		}),
	],
});

S3 API를 통한 R2

서명된 업로드 URL 등의 기능을 위해 S3 자격 증명으로 R2를 사용합니다:

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

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 바인딩 (대신 R2 자격 증명으로 S3 어댑터를 사용)
  • 로컬

스토리지 인터페이스

모든 스토리지 어댑터는 동일한 인터페이스를 구현합니다:

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;
}

일관된 인터페이스 덕분에 애플리케이션 코드를 변경하지 않고도 스토리지 백엔드를 전환할 수 있습니다.