Workers API 참조 (Workers API reference)
in-Worker R2 API는 R2 버킷을 Worker에 바인딩해서 접근해요. 작성하는 Worker는 라우트를 통해 버킷에 대한 외부 접근을 노출하거나, R2 객체를 내부에서 조작할 수 있어요.
출처: 문서
본문
R2 API에는 S3 API와 다른 확장 기능과 의미적 차이가 있어요. S3 호환이 필요하다면 S3 호환 API를 고려해 보세요.
개념
R2는 저장하는 데이터를 객체(objects)라고 부르고, 이를 컨테이너인 버킷(buckets)으로 구성해요. 버킷은 R2 내에서 성능, 확장, 접근의 기본 단위예요.
바인딩 만들기
바인딩(Bindings)
바인딩은 Worker가 KV Namespaces, Durable Objects, 또는 R2 Buckets 같은 외부 리소스와 상호작용하는 방식이에요. 바인딩은 Workers 런타임이 코드에 제공하는 런타임 변수예요. Wrangler 파일에 변수 이름을 선언하면 런타임에 이 리소스에 바인딩되고, 그 변수를 통해 상호작용할 수 있어요. 각 바인딩의 변수 이름과 동작은 Worker를 배포할 때 사용자가 결정해요. 자세한 내용은 환경 변수를 참고해 주세요.
바인딩은 Worker 프로젝트 디렉터리의 Wrangler 파일에 정의돼요.
R2 버킷을 Worker에 바인딩하려면 Wrangler 파일에 다음을 추가해요. binding 속성을 유효한 JavaScript 변수 식별자로, bucket_name을 R2 버킷 이름으로 바꿔요:
{
"r2_buckets": [
{
"binding": "MY_BUCKET", // <~ valid JavaScript variable name
"bucket_name": "<YOUR_BUCKET_NAME>"
}
]
}
[[r2_buckets]]
binding = "MY_BUCKET"
bucket_name = "<YOUR_BUCKET_NAME>"
이제 Worker 내에서 버킷 바인딩은 MY_BUCKET 변수로 사용할 수 있고, 아래 설명하는 버킷 메서드로 상호작용을 시작할 수 있어요.
버킷 메서드 정의
다음 메서드들은 코드에 주입되는 버킷 바인딩 객체에서 사용할 수 있어요.
예를 들어, 위의 바인딩으로 PUT 객체 요청을 보내 보면:
export default {
async fetch(request, env) {
const url = new URL(request.url);
const key = url.pathname.slice(1);
switch (request.method) {
case "PUT":
await env.MY_BUCKET.put(key, request.body);
return new Response(`Put ${key} successfully!`);
default:
return new Response(`${request.method} is not allowed.`, {
status: 405,
headers: {
Allow: "PUT",
},
});
}
},
};
from workers import WorkerEntrypoint, Response
from urllib.parse import urlparse
class Default(WorkerEntrypoint):
async def fetch(self, request):
url = urlparse(request.url)
key = url.path[1:]
if request.method == "PUT":
await self.env.MY_BUCKET.put(key, request.body)
return Response(f"Put {key} successfully!")
else:
return Response(
f"{request.method} is not allowed.",
status=405,
headers={"Allow": "PUT"}
)
-
head(key: string): Promise<R2Object | null>- 키가 존재하면 해당 키에 대한 객체 메타데이터만 포함된
R2Object를 검색하고, 키가 없으면null을 반환해요.
- 키가 존재하면 해당 키에 대한 객체 메타데이터만 포함된
-
get(key: string, options?: R2GetOptions): Promise<R2ObjectBody | R2Object | null>- 키가 존재하면 객체 메타데이터와
ReadableStream형태의 객체 본문을 포함한R2ObjectBody를 검색하고, 키가 없으면null을 반환해요. options에 지정된 사전 조건(precondition)이 실패하면get()은body가 undefined인R2Object를 반환해요.
- 키가 존재하면 객체 메타데이터와
-
put(key: string, value: ReadableStream | ArrayBuffer | ArrayBufferView | string | null | Blob, options?: R2PutOptions): Promise<R2Object | null>- 주어진
value와 메타데이터를 관련key아래에 저장해요. 쓰기가 성공하면 저장된 객체에 대한 메타데이터를 포함한R2Object를 반환해요. options에 지정된 사전 조건이 실패하면put()은null을 반환하고 객체는 저장되지 않아요.- R2 쓰기는 강력한 일관성(strongly consistent)을 가져요. Promise가 resolve되면 이후의 모든 읽기 작업은 이 키-값 쌍을 전역에서 볼 수 있어요.
- 주어진
-
delete(key: string | string[]): Promise<void>- 관련
keys아래의 주어진values와 메타데이터를 삭제해요. 삭제가 성공하면void를 반환해요. - R2 삭제는 강력한 일관성을 가져요. Promise가 resolve되면 이후의 모든 읽기 작업은 제공된 키-값 쌍을 전역에서 더 이상 볼 수 없어요.
- 호출당 최대 1000개의 키를 삭제할 수 있어요.
- 관련
-
list(options?: R2ListOptions): Promise<R2Objects>- 버킷에 포함된
R2Object목록을 담은R2Objects를 반환해요. - 반환되는 객체 목록은 사전순으로 정렬돼요.
- 최대 1000개 항목을 반환하지만, Worker 내 메모리 부담을 줄이기 위해 더 적게 반환할 수도 있어요.
- 나열할 객체 수를 명시적으로 설정하려면
limit속성이 설정된 R2ListOptions 객체를 제공해요.
- 버킷에 포함된
-
createMultipartUpload(key: string, options?: R2MultipartOptions): Promise<R2MultipartUpload>- 멀티파트 업로드를 생성해요.
- 새로 생성된 멀티파트 업로드를 나타내는
R2MultipartUpload객체로 resolve되는 Promise를 반환해요. 멀티파트 업로드가 생성되면 Workers API 또는 S3 API를 통해 전역에서 즉시 상호작용할 수 있어요.
-
resumeMultipartUpload(key: string, uploadId: string): R2MultipartUpload- 주어진 key와 uploadId를 가진 멀티파트 업로드를 나타내는 객체를 반환해요.
- resumeMultipartUpload 작업은 uploadId의 유효성을 검사하거나 해당하는 활성 멀티파트 업로드의 존재를 확인하지 않아요. 이는
R2MultipartUpload객체에 대한 후속 작업을 호출하기 전의 지연을 최소화하기 위해서예요.
R2Object 정의
R2Object는 R2 버킷에 객체를 PUT할 때 생성돼요. R2Object는 업로더가 제공한 정보를 기반으로 한 객체의 메타데이터를 나타내요. R2 버킷에 PUT하는 모든 객체에는 R2Object가 생성돼요.
keystring- 객체의 키예요.
versionstring- 특정 키의 특정 업로드와 연결된 무작위 고유 문자열이에요.
sizenumber- 바이트 단위의 객체 크기예요.
etagstring
참고
Cloudflare는 응답 헤더에서 etag를 반환할 때 httpEtag 필드를 사용할 것을 권장해요. 이렇게 하면 etag가 따옴표로 감싸지고 RFC 9110 ↗︎을 준수하게 돼요.
- 객체 업로드와 연결된 etag예요.
httpEtagstring- 헤더로 반환될 수 있도록 따옴표로 감싼 객체의 etag예요.
uploadedDate- 객체가 업로드된 시간을 나타내는 Date 객체예요.
httpMetadataR2HTTPMetadata- 객체와 연결된 다양한 HTTP 헤더예요. HTTP 메타데이터를 참고해 주세요.
customMetadataRecord<string, string>- 객체와 연결된 사용자 정의 메타데이터의 맵이에요.
rangeR2Rangeoptional- 객체의 반환된 범위를 포함하는
R2Range객체예요.
- 객체의 반환된 범위를 포함하는
checksumsR2Checksums- 객체의 저장된 체크섬을 포함하는
R2Checksums객체예요. 체크섬을 참고해 주세요.
- 객체의 저장된 체크섬을 포함하는
writeHttpMetadata(headers: Headers): voidR2Object에서httpMetadata를 검색하고 해당 HTTP 헤더를Headers입력 객체에 적용해요. HTTP 메타데이터를 참고해 주세요.
storageClass'Standard' | 'InfrequentAccess'- 객체와 연결된 스토리지 클래스예요. 스토리지 클래스를 참고해 주세요.
ssecKeyMd5stringoptional- 암호화에 사용된 SSE-C 키의 hex 인코딩 MD5 해시예요(제공된 경우). 이 해시는 객체를 복호화하는 데 필요한 키를 식별하는 데 사용할 수 있어요.
R2ObjectBody 정의
R2ObjectBody는 객체의 메타데이터와 본문을 합친 것을 나타내요. R2 버킷에서 객체를 GET할 때 반환돼요. R2ObjectBody의 전체 키 목록에는 아래 목록과 R2Object에서 상속된 모든 키가 포함돼요.
bodyReadableStream- 객체의 값이에요.
bodyUsedboolean- 객체의 값이 소비되었는지 여부예요.
arrayBuffer(): Promise<ArrayBuffer>- 객체의 값을 포함하는
ArrayBuffer로 resolve되는 Promise를 반환해요.
- 객체의 값을 포함하는
text(): Promise<string>- 객체의 값을 포함하는 문자열로 resolve되는 Promise를 반환해요.
json<T>() : Promise<T>- 객체의 값을 포함하는 주어진 객체로 resolve되는 Promise를 반환해요.
blob(): Promise<Blob>- 객체의 값을 포함하는 이진 Blob으로 resolve되는 Promise를 반환해요.
R2MultipartUpload 정의
R2MultipartUpload 객체는 createMultipartUpload 또는 resumeMultipartUpload를 호출할 때 생성돼요. R2MultipartUpload는 진행 중인 멀티파트 업로드를 나타내요.
완료되지 않은 멀티파트 업로드는 7일 후 자동으로 중단(abort)돼요.
참고
R2MultipartUpload 객체가 그 객체에 해당하는 활성 기본 멀티파트 업로드가 있다는 것을 보장하지는 않아요.
멀티파트 업로드는 S3 API를 통하거나 Worker의 병렬 호출로 언제든지 완료되거나 중단될 수 있어요. 따라서 기본 멀티파트 업로드가 더 이상 존재하지 않을 경우를 대비해 R2MultipartUpload 객체의 각 작업 주변에 필요한 오류 처리 코드를 추가하는 것이 중요해요.
keystring- 멀티파트 업로드의
key예요.
- 멀티파트 업로드의
uploadIdstring- 멀티파트 업로드의
uploadId예요.
- 멀티파트 업로드의
uploadPart(partNumber: number, value: ReadableStream | ArrayBuffer | ArrayBufferView | string | Blob, options?: R2MultipartOptions): Promise<R2UploadedPart>- 지정된 파트 번호로 단일 파트를 이 멀티파트 업로드에 업로드해요. 각 파트의 크기는 동일해야 하며, 예외적으로 마지막 파트는 더 작을 수 있어요.
etag와partNumber를 포함하는R2UploadedPart객체를 반환해요. 이R2UploadedPart객체는 멀티파트 업로드를 완료할 때 필요해요.
abort(): Promise<void>- 멀티파트 업로드를 중단해요. 업로드가 성공적으로 중단되면 resolve되는 Promise를 반환해요.
complete(uploadedParts: R2UploadedPart[]): Promise<R2Object>- 주어진 파트로 멀티파트 업로드를 완료해요.
- 완료 작업이 끝나면 resolve되는 Promise를 반환해요. 이 시점 이후 객체는 이후의 모든 읽기 작업에서 전역에서 즉시 접근할 수 있어요.
메서드별 타입
R2GetOptions
onlyIfR2Conditional | HeadersR2Conditional또는 조건부 헤더의 특정 조건이 충족될 때만 객체를 반환하도록 지정해요. 조건부 작업을 참고해 주세요.
rangeR2Range | HeadersoptionalR2Range또는 범위 헤더의 범위에 따라 객체의 특정 길이(선택적 오프셋에서) 또는 접미사 바이트만 반환하도록 지정해요. 범위 읽기를 참고해 주세요.
ssecKeyArrayBuffer | string- SSE-C에 사용할 키를 지정해요. 키는 hex 인코딩 문자열 또는 ArrayBuffer 형태로 32바이트 길이여야 해요.
범위 읽기 (Ranged reads)
R2GetOptions는 range 파라미터를 받아 body에서 반환되는 데이터를 제한할 수 있어요.
범위에는 세 가지 변형 인자가 있어요:
- 선택적 길이가 있는 오프셋.
- 선택적 오프셋이 있는 길이.
- 접미사(suffix).
offsetnumber- 데이터 반환을 시작할 바이트(포함)예요.
lengthnumber- 반환할 바이트 수예요. 객체에 존재하는 것보다 더 많은 바이트를 요청하면 이 수보다 적은 바이트가 반환될 수 있어요.
suffixnumber- 파일 끝(마지막 바이트부터)에서 반환할 바이트 수예요. 객체에 존재하는 것보다 더 많은 바이트를 요청하면 이 수보다 적은 바이트가 반환될 수 있어요.
R2PutOptions
onlyIfR2Conditional | HeadersR2Conditional의 특정 조건이 충족될 때만 객체를 저장하도록 지정해요. 조건부 작업을 참고해 주세요.
httpMetadataR2HTTPMetadata | Headersoptional- 객체와 연결된 다양한 HTTP 헤더예요. HTTP 메타데이터를 참고해 주세요.
customMetadataRecord<string, string>optional- 객체와 함께 저장될 사용자 정의 메타데이터의 맵이에요.
참고
한 번에 단일 해싱 알고리즘만 지정할 수 있어요.
md5ArrayBuffer | stringoptional- 수신 객체의 무결성을 확인하는 데 사용할 MD5 해시예요.
sha1ArrayBuffer | stringoptional- 수신 객체의 무결성을 확인하는 데 사용할 SHA-1 해시예요.
sha256ArrayBuffer | stringoptional- 수신 객체의 무결성을 확인하는 데 사용할 SHA-256 해시예요.
sha384ArrayBuffer | stringoptional- 수신 객체의 무결성을 확인하는 데 사용할 SHA-384 해시예요.
sha512ArrayBuffer | stringoptional- 수신 객체의 무결성을 확인하는 데 사용할 SHA-512 해시예요.
storageClass'Standard' | 'InfrequentAccess'- 제공되면 객체의 스토리지 클래스를 설정해요. 그렇지 않으면 객체는 버킷과 연결된 기본 스토리지 클래스에 저장돼요. 스토리지 클래스를 참고해 주세요.
ssecKeyArrayBuffer | string- SSE-C에 사용할 키를 지정해요. 키는 hex 인코딩 문자열 또는 ArrayBuffer 형태로 32바이트 길이여야 해요.
R2MultipartOptions
httpMetadataR2HTTPMetadata | Headersoptional- 객체와 연결된 다양한 HTTP 헤더예요. HTTP 메타데이터를 참고해 주세요.
customMetadataRecord<string, string>optional- 객체와 함께 저장될 사용자 정의 메타데이터의 맵이에요.
storageClassstring- 제공되면 객체의 스토리지 클래스를 설정해요. 그렇지 않으면 객체는 버킷과 연결된 기본 스토리지 클래스에 저장돼요. 스토리지 클래스를 참고해 주세요.
ssecKeyArrayBuffer | string- SSE-C에 사용할 키를 지정해요. 키는 hex 인코딩 문자열 또는 ArrayBuffer 형태로 32바이트 길이여야 해요.
R2ListOptions
-
limitnumberoptional- 반환할 결과 수예요. 기본값은
1000이고 최댓값은1000이에요. include를 설정하면 메타데이터를 수용하기 위해 응답에서limit보다 적은 결과를 받을 수 있어요.
- 반환할 결과 수예요. 기본값은
-
prefixstringoptional- 키를 대조할 접두어예요. 주어진 접두어로 시작하는 키만 반환돼요.
-
cursorstringoptional- 객체 나열을 계속할 위치를 나타내는 불투명 토큰이에요. 이전 나열 작업에서 커서를 검색할 수 있어요.
-
delimiterstringoptional- 키를 그룹화할 때 사용할 문자예요.
-
includeArray<string>optionalhttpMetadata및/또는customMetadata를 포함할 수 있어요. 포함하면 나열에서 반환되는 항목에 지정된 메타데이터가 포함돼요.- 단일
list작업이 반환할 수 있는 총 데이터 양에는 제한이 있다는 점을 참고해 주세요. 데이터를 요청하면 메타데이터를 수용하기 위해 응답에서limit보다 적은 결과를 받을 수 있어요. - Wrangler 파일에서 호환성 날짜가
2022-08-04이상으로 설정되어 있어야 해요. 그렇지 않으면r2_list_honor_include호환성 플래그를 설정해야 해요. 그렇게 하지 않으면 실제include옵션 값과 관계없이include: ['httpMetadata', 'customMetadata']로 취급돼요.
즉, 애플리케이션은 반환된 객체 수를
limit와 비교하지 않도록 주의해야 해요. 대신truncated속성을 사용해list요청에 반환할 데이터가 더 있는지 판단해요.
const options = {
limit: 500,
include: ["customMetadata"],
};
const listed = await env.MY_BUCKET.list(options);
let truncated = listed.truncated;
let cursor = truncated ? listed.cursor : undefined;
// ❌ - if your limit can't fit into a single response or your
// bucket has less objects than the limit, it will get stuck here.
while (listed.objects.length < options.limit) {
// ...
}
// ✅ - use the truncated property to check if there are more
// objects to be returned
while (truncated) {
const next = await env.MY_BUCKET.list({
...options,
cursor: cursor,
});
listed.objects.push(...next.objects);
truncated = next.truncated;
cursor = next.cursor;
}
limit = 500
include = ["customMetadata"]
listed = await self.env.MY_BUCKET.list(limit=limit, include=include)
truncated = listed.truncated
cursor = listed.cursor if truncated else None
# ❌ - if your limit can't fit into a single response or your
# bucket has less objects than the limit, it will get stuck here.
while len(listed.objects) < limit:
...
# ✅ - use the truncated property to check if there are more
# objects to be returned
while truncated:
next_page = await self.env.MY_BUCKET.list(limit=limit, include=include, cursor=cursor)
listed.objects.extend(next_page.objects)
truncated = next_page.truncated
cursor = next_page.cursor
R2Objects
BUCKET_BINDING.list()가 반환하는 R2Object 배열을 포함하는 객체예요.
objectsArray<R2Object>list요청과 일치하는 객체 배열이에요.
truncatedboolean- true면 현재
list요청에 대해 검색할 결과가 더 있다는 것을 나타내요.
- true면 현재
cursorstringoptional- 그 지점부터 나열을 재개하기 위해 향후
list호출에 전달할 수 있는 토큰이에요. truncated가 true일 때만 존재해요.
- 그 지점부터 나열을 재개하기 위해 향후
delimitedPrefixesArray<string>- 구분자가 지정된 경우, 지정된 접두어와 구분자의 다음 발생 사이의 모든 접두어를 포함해요.
- 예를 들어 접두어가 없고 구분자가 '/'인 경우
foo/bar/baz는 구분된 접두어로foo를 반환해요. 같은 구조와 구분자로foo/가 접두어로 전달되면foo/bar가 구분된 접두어로 반환돼요.
조건부 작업 (Conditional operations)
R2GetOptions와 R2PutOptions에 R2Conditional 객체를 전달할 수 있어요. get()에 대한 조건 검사가 실패하면 본문은 반환되지 않아요. 이렇게 하면 get()의 지연 시간이 낮아져요.
put()에 대한 조건 검사가 실패하면 R2Object 대신 null이 반환돼요.
etagMatchesstringoptional- 객체의 etag가 주어진 문자열과 일치하면 작업을 수행해요.
etagDoesNotMatchstringoptional- 객체의 etag가 주어진 문자열과 일치하지 않으면 작업을 수행해요.
uploadedBeforeDateoptional- 객체가 주어진 날짜 이전에 업로드되었으면 작업을 수행해요.
uploadedAfterDateoptional- 객체가 주어진 날짜 이후에 업로드되었으면 작업을 수행해요.
또는 조건부 헤더를 포함하는 Headers 객체를 R2GetOptions와 R2PutOptions에 전달할 수 있어요. 이 조건부 헤더에 대한 정보는 조건부 요청에 대한 MDN 문서 ↗︎를 참고해 주세요. If-Range를 제외한 모든 조건부 헤더가 지원돼요.
조건부 요청에 대한 더 구체적인 정보는 RFC 7232 ↗︎를 참고해 주세요.
HTTP 메타데이터
일반적으로 이 필드들은 객체 생성 시 전달된 HTTP 메타데이터와 일치해요. GET 요청을 발행할 때 재정의할 수 있으며, 이 경우 주어진 값이 응답에 그대로 반영돼요.
contentTypestringoptionalcontentLanguagestringoptionalcontentDispositionstringoptionalcontentEncodingstringoptionalcacheControlstringoptionalcacheExpiryDateoptional
체크섬 (Checksums)
put() 바인딩을 사용할 때 체크섬을 제공했다면 반환된 객체의 checksums 속성에서 확인할 수 있어요. non-multipart 객체에는 기본적으로 MD5 체크섬이 포함돼요.
md5ArrayBufferoptional- 객체의 MD5 체크섬이에요.
sha1ArrayBufferoptional- 객체의 SHA-1 체크섬이에요.
sha256ArrayBufferoptional- 객체의 SHA-256 체크섬이에요.
sha384ArrayBufferoptional- 객체의 SHA-384 체크섬이에요.
sha512ArrayBufferoptional- 객체의 SHA-512 체크섬이에요.
R2UploadedPart
R2UploadedPart 객체는 업로드된 파트를 나타내요. R2UploadedPart 객체는 uploadPart 작업에서 반환되며 completeMultipartUpload 작업에 전달되어야 해요.
partNumbernumber- 파트의 번호예요.
etagstring- 파트의
etag예요.
- 파트의
스토리지 클래스 (Storage Class)
R2Object가 저장되는 스토리지 클래스예요. 사용 가능한 스토리지 클래스는 Standard와 InfrequentAccess예요. 자세한 내용은 스토리지 클래스를 참고해 주세요.
더 알아보기 (Learn more)
- Workers에서 R2 사용하기 — Worker에서 R2 바인딩 사용 예시
- Workers에서 멀티파트 업로드 — 대용량 객체 멀티파트 업로드
- R2 S3 호환 API — S3 호환이 필요할 때