S3 호환성

S3 호환성 (S3 Compatibility)

Storage Buckets는 S3 호환 API로 접근할 수 있어요. 이를 통해 기존 S3 도구(AWS CLI, boto3, s5cmd, 대부분의 다른 S3 SDK)를 코드 변경 없이 버킷에 사용할 수 있어요. 요청은 https://s3.hf.co의 게이트웨이 서비스를 거쳐요.

출처: 문서

본문

S3 API는 버킷 데이터에 접근하는 여러 방법 중 하나예요. 별도의 S3 자격 증명 없이 Hugging Face 네이티브 접근(hf CLI, hf:// 경로, 파일시스템 마운트)을 원한다면 Access Patterns를 참고하세요.

[!NOTE] S3 API는 Storage Buckets에서만 동작해요. 다른 Hugging Face 저장소 유형(모델, 데이터셋, Spaces)은 노출하지 않아요.

S3 자격 증명 생성 (Generating S3 Credentials)

게이트웨이는 Hugging Face User Access Token에서 파생된 AWS 스타일 액세스 키로 인증해요.

  1. Access Tokens 설정으로 이동하세요. 토큰이 없다면 Create new token 버튼으로 생성하세요. 토큰의 권한이 S3 자격 증명의 권한이 됩니다 — 버킷에 대한 읽기 전용 접근은 Read, 읽기·쓰기 접근은 Write를 선택하세요.
  2. 목록에서 토큰을 찾아 드롭다운 메뉴를 열고 Generate S3 credentials를 선택하세요.
  3. 생성된 access key ID(HFAK… 접두사)와 secret access key를 안전한 곳에 복사하세요 — 시크릿은 한 번만 표시돼요.

S3 자격 증명은 기본이 되는 액세스 토큰의 권한을 상속해요. 세밀한 토큰의 경우 사용하려는 네임스페이스와 버킷에만 스코프를 제한하세요.

클라이언트 구성하기 (Configuring a Client)

S3 클라이언트를 게이트웨이 엔드포인트로 지정하고 몇 가지 필수 옵션을 설정하세요. 엔드포인트 URL에 Hugging Face namespace(사용자 이름 또는 조직 이름)를 사용하세요 — 아래 Addressing buckets 참고.

설정 이유
endpoint_url https://s3.hf.co/<namespace> 내 네임스페이스로 스코프된 게이트웨이
region us-east-1 필수; 게이트웨이는 현재 단일 리전
s3.addressing_style path 버킷을 서브도메인이 아닌 경로 세그먼트로 주소 지정
request_checksum_calculation when_required 최신 클라이언트가 트레일링 체크섬을 보내는 것을 방지
response_checksum_validation when_required 최신 클라이언트가 응답에 체크섬을 기대하는 것을 방지

두 체크섬 설정은 최신 클라이언트에 중요해요: AWS CLI ≥ 2.23과 최신 boto3 버전은 기본적으로 aws-chunked 프레이밍으로 트레일링 CRC32 체크섬을 보내는데, 게이트웨이가 파싱하지 못해요. 이 설정들은 클라이언트가 연산이 엄격히 요구할 때만 체크섬을 보내도록 지시해요.

다음은 선택 사항이지만 대용량 업로드가 가능한 한 적은 multipart 파트를 사용하도록 하므로 권장돼요:

설정
s3.multipart_threshold 2GB
s3.multipart_chunksize 2GB

예시: AWS CLI 프로필

~/.aws/config에 프로필을 추가하세요:

[profile hf]
region = us-east-1
endpoint_url = https://s3.hf.co/<namespace>
s3 =
    addressing_style = path
    multipart_threshold = 2GB
    multipart_chunksize = 2GB
request_checksum_calculation = when_required
response_checksum_validation = when_required

참고: 위의 <namespace>를 내 버킷이 저장된 사용자 이름 또는 조직으로 바꾸세요.

프로필에 맞는 자격 증명을 ~/.aws/credentials에 추가하세요:

[hf]
aws_access_key_id = HFAK...
aws_secret_access_key = ...

그런 다음 프로필로 아무 S3 명령을 사용하세요:

aws --profile hf s3 ls
aws --profile hf s3 mb s3://my-bucket
aws --profile hf s3 cp ./model.safetensors s3://my-bucket/models/model.safetensors

버킷 주소 지정 (Addressing Buckets)

AWS S3는 단일 평평한 전역 고유 버킷 이름 공간을 사용하며, SDK는 버킷 이름이 /가 없는 일반 문자열이길 기대해요. 반면 Hugging Face 버킷은 namespace/bucket으로 식별되는데, 여기서 namespace는 사용자 이름이나 조직이에요. 이 추가 레벨이 S3 클라이언트와 불일치를 만들고, 많은 클라이언트가 버킷 이름의 /를 허용하지 않거나 잘못 URL 이스케이프해요. 이를 우회하는 두 가지 방법이 있어요:

1. 네임스페이스를 엔드포인트 URL에 넣기(대부분의 경우 권장). 이렇게 하면 모든 연산이 그 네임스페이스로 스코프되므로 클라이언트에 전달하는 버킷 이름은 HF 버킷 이름뿐이에요. 내 버킷이나 단일 조직의 버킷에는 잘 동작하지만, 네임스페이스 간에는 문제가 생겨요 — 예를 들어 개인 버킷에서 조직 버킷으로의 서버 측 복사 같은 경우요.

aws --endpoint-url https://s3.hf.co/my-org s3api get-object \
  --bucket my-bucket --key some/object.txt ./object.txt

2. 네임스페이스를 버킷으로 취급하고 HF 버킷 이름을 오브젝트 키 앞에 붙이기. 이는 오브젝트 레벨 연산(업로드, 다운로드)에는 동작하지만 버킷 생성·삭제 같은 버킷 레벨 연산에는 문제가 있어요.

aws --endpoint-url https://s3.hf.co s3api get-object \
  --bucket my-org --key my-bucket/some/object.txt ./object.txt

AWS S3와의 제한·차이점 (Limitations and Differences from AWS S3)

Storage Buckets가 모든 S3 개념을 모델링하지 않기 때문에 일부 동작이 다르거나 지원되지 않아요.

오브젝트 다운로드

게이트웨이는 현재 단일 리전이에요. 다운로드 성능을 개선하기 위해 GetObject는 보통 바이트를 직접 서빙하지 않고 가장 가까운 Hugging Face CDN 엣지로의 HTTP 302 리디렉션으로 응답해요.

일부 SDK는 S3 엔드포인트의 리디렉션을 따르지 않으므로, 게이트웨이는 aws-cli, botocore(boto3 포함), aws-sdk-rust로 식별되는 클라이언트를 감지해 그들을 위해 데이터를 자체적으로 프록시해요. 다른 모든 클라이언트(rclone, s5cmd, curl, AWS Go SDK 등)는 302를 받아 네이티브로 따라가므로, 더 빠른 다운로드를 위해 게이트웨이가 데이터 경로에서 벗어나 있어요.

오브젝트 키 이름

버킷 오브젝트 키는 S3보다 더 제한적이에요. 키는 다음을 하면 안 됩니다:

  • /로 시작하거나 끝나기
  • 연속 슬래시(//) 포함
  • ../ 시퀀스 포함
  • ./로 시작
  • ..로 끝
  • 백슬래시(\)나 널 바이트(\0) 포함

ListObjects

  • ListObjectsV1은 지원되지 않아요 — ListObjectsV2를 사용하세요. 일부 클라이언트(rclone 같은)는 전용으로 ListObjectsV2를 사용하도록 구성해야 할 수 있어요.
  • 구분자는 /만 허용돼요.

기타 API 차이점

  • 오브젝트 메타데이터: 임의의 사용자 메타데이터(x-amz-meta-*)는 저장되거나 반환되지 않아요. Content-Type은 지원됩니다.
  • 지원되지 않는 기능: ACL, 버킷 정책, 오브젝트 태깅, 오브젝트 버전 관리, 수명 주기 규칙, 서버 측 암호화(SSE), 버킷 알림은 지원되지 않아요. 오브젝트는 항상 STANDARD 스토리지 클래스로 보고돼요. 관련 요청 헤더와 파라미터는 수용되지만 무시돼요.
  • CopyObject: 서버 측 복사는 단일 네임스페이스 내에서만 동작해요. 크로스 네임스페이스 복사와 UploadPartCopy(기존 오브젝트의 파트를 multipart 업로드로 복사)는 지원되지 않아요.
  • 조건부 요청: If-Match / If-None-Match 선행 조건은 PutObjectCopyObject의 copy-source에서 존중되지만 GetObject에서는 아뇨.
  • Multipart 업로드 만료: 완료되거나 중단되지 않은 진행 중인 multipart 업로드는 7일 후 자동으로 만료·정리돼요.

예시 (Examples)

일반적인 작업을 위한 실전 레시피예요. 각각 위의 클라이언트 구성을 기반으로 해요.

boto3로 읽기·쓰기

boto3는 위의 클라이언트 설정으로 게이트웨이와 동작해요. <namespace>를 내 사용자 이름이나 조직으로 바꾸세요:

import boto3
from botocore.config import Config

s3 = boto3.client(
    "s3",
    endpoint_url="https://s3.hf.co/<namespace>",
    aws_access_key_id="HFAK...",
    aws_secret_access_key="...",
    config=Config(
        region_name="us-east-1",
        s3={"addressing_style": "path"},
        request_checksum_calculation="when_required",
        response_checksum_validation="when_required",
    ),
)

s3.upload_file("model.safetensors", "my-bucket", "models/model.safetensors")
s3.download_file("my-bucket", "models/model.safetensors", "model.safetensors")

DuckDB로 버킷 쿼리하기

httpfs 확장으로 DuckDB는 버킷에서 Parquet(및 다른 형식)을 직접 읽을 수 있어요:

INSTALL httpfs;
LOAD httpfs;

CREATE SECRET hf (
    TYPE s3,
    KEY_ID 'HFAK...',
    SECRET '...',
    ENDPOINT 's3.hf.co/<namespace>',
    URL_STYLE 'path',
    REGION 'us-east-1'
);

SELECT * FROM read_parquet('s3://my-bucket/data.parquet');

[!NOTE] URL_STYLE 'path'가 필요해요. 없으면 DuckDB는 virtual-hosted-style 주소 지정(my-bucket.s3.hf.co)을 사용하는데, 게이트웨이가 서빙하지 않아서 "Could not resolve hostname" 오류가 나요.

rclone으로 데이터 가져오기

rclone은 두 S3 호환 스토어 사이에서 데이터를 복사하는 편리한 방법이라, 기존 AWS S3 버킷(또는 어떤 S3 호환 소스든)을 Storage Bucket으로 옮기는 데 잘 맞아요.

아이디어는 소스 버킷과 Hugging Face 게이트웨이 두 개의 remote를 선언하고 rclone이 그 사이에서 오브젝트를 스트리밍하게 하는 것이에요. 두 remote를 ~/.config/rclone/rclone.conf에 추가하세요. 첫 번째는 기존 S3 버킷을 가리키며, 소스에 맞게 조정하세요(여기서는 일반 AWS S3):

[aws]
type = s3
provider = AWS
access_key_id = AKIA...
secret_access_key = ...
region = us-east-1

두 번째는 Hugging Face 게이트웨이를 가리켜요. 다른 클라이언트와 마찬가지로 엔드포인트를 내 namespace로 스코프하고, path 주소 지정을 사용하며, ListObjectsV2(게이트웨이가 지원하는 유일한 리스팅 버전)를 강제하고, 업로드가 가능한 한 적은 파트를 사용하도록 큰 multipart 크기를 설정하세요:

[hf]
type = s3
provider = Other
endpoint = https://s3.hf.co/<namespace>
access_key_id = HFAK...
secret_access_key = ...
region = us-east-1
force_path_style = true
list_version = 2
upload_cutoff = 2G
chunk_size = 2G

참고: 위의 <namespace>를 내 버킷이 저장된 사용자 이름이나 조직으로 바꾸고, 액세스 토큰에서 생성한 S3 자격 증명을 사용하세요. 대상 버킷은 그 네임스페이스 아래에 이미 존재해야 해요.

이제 소스 버킷을 내 Storage Bucket으로 복사하세요:

rclone copy aws:my-source-bucket hf:my-bucket --progress

rclone copy는 대상에서 누락되거나 변경된 오브젝트만 전송하므로, 중단된 가져오기를 재개하거나 새 오브젝트를 가져오기 위해 다시 실행해도 안전해요. 대상을 소스의 정확한 미러로 만들려면(대상에서 소스에 더 이상 없는 오브젝트를 삭제) rclone sync를 대신 사용하세요:

rclone sync aws:my-source-bucket hf:my-bucket --progress

[!TIP] 대용량 가져오기의 경우 --transfers--checkers를 추가해 동시성을 높이고(예: --transfers 16 --checkers 16), 나중에 rclone check aws:my-source-bucket hf:my-bucket을 실행해 모든 오브젝트가 건너갔는지 확인하세요.

DVC로 데이터 버전 관리

DVC는 저장소에 작은 포인터 파일을 유지하고 실제 데이터를 remote로 푸시하는 방식으로 git에서 데이터셋과 모델을 버전 관리해요. 버킷은 게이트웨이를 통해 DVC remote로 동작하므로, 코드와 .dvc 포인터는 git에 유지되고 데이터는 버킷에 살아요. S3 지원이 있는 DVC를 설치하고(pip install 'dvc[s3]'), 위의 클라이언트 설정으로 remote를 추가하세요:

dvc remote add -d hf-bucket s3://my-bucket/dvc-store
dvc remote modify hf-bucket endpointurl https://s3.hf.co/<namespace>
dvc remote modify hf-bucket region us-east-1

S3 자격 증명은 환경을 통해 전달하거나, git에 남지 않도록 dvc remote modify --local로 전달하세요:

export AWS_ACCESS_KEY_ID=HFAK...
export AWS_SECRET_ACCESS_KEY=...

그런 다음 평소처럼 추적·푸시·풀하세요 — dvc push는 버킷으로 업로드하고, 새 클론에서 dvc pull은 다시 다운로드해요:

dvc add data/
git add data.dvc .gitignore .dvc/config && git commit -m "Track data with DVC"
dvc push

[!NOTE] endpointurl에는 namespace를, s3:// URL에는 베어 버킷 이름을 사용하세요.

더 알아보기 (Learn more)

  • Storage Buckets 문서에서 버킷의 기본 개념을 배울 수 있어요.
  • Access Patterns에서 hf CLI와 hf:// 경로로 네이티브 접근하는 법을 확인하세요.