INNORIX
전송 빌더전송 파인더개발자리소스고객사
무료 시작하기
INNORIX

LET FILES
MOVE THEMSELVES

INNORIX는 모든 시스템과 환경에서 파일 이동과 자동화를 제공하는 엔터프라이즈 파일 인프라 기업입니다.
5,000개 이상의 기업 및 공공기관에서 사용하고 있습니다.

시작하기

  • 필요한 전송 만들기
  • 필요한 전송 찾기

주요 전송

  • 팀 업무 폴더 동기화
  • 고객에게 대용량 파일 전송
  • 여러 시스템 파일 탐색
  • FTP·SFTP·SCP·rsync 전환
  • 앱에 파일 전송 추가
  • 웹 업로드·다운로드 적용
  • AI·데이터 워크플로 구축
  • 모든 전송 둘러보기→

개발자

  • 개발자 센터
  • 구현 예제
  • API 빠른 시작
  • 개발자 가이드
  • API 레퍼런스
  • GitHub

리소스

  • 리소스 센터
  • 제품 가이드
  • 외부 서비스 연동
  • 배포 및 관리
  • 도움말 센터

고객사

  • 정부
  • 공공부문
  • 제조
  • 엔지니어링
  • 금융
  • 유통
  • IT/통신
  • 미디어
  • 의료
  • 교육

플랜

  • 가격 및 플랜

회사

INNORIX 소개

Exabyter를 찾고 계신가요?

이제 INNORIX Platform에 통합되었습니다

기타 INNORIX 제품

Al.bert — 스마트 교통 AI

글로벌 오피스

  • 미국 뉴욕
  • 대한민국 서울
  • 베트남 호찌민
  • 오피스 위치 보기→

(C)2026 INNORIX. All rights reserved.

  • 보안
  • 상태
  • 이용약관
  • 개인정보 처리방침
  • 쿠키 정책
  1. 가이드
  2. Amazon S3에서 Cloudflare R2로 파일 이전하기

Amazon S3에서 Cloudflare R2로 파일 이전하기

S3 데이터를 R2로 이전하고 파일 수, 크기와 무결성을 확인합니다.

IT 엔지니어개발자
  • AI 학습 데이터와 모델 파일의 전체 흐름 자동화하기
  • AI 모델 파일을 여러 엣지 장비에 배포하기
  • 폐쇄망·망분리 환경에서 파일을 승인 반입·반출하기
  • 승인된 파일을 여러 지점에 동시에 배포하기
  • Azure Blob에서 사내 서버로 파일 전달하기
  • 데이터베이스 덤프, 백업, 아카이브 파일을 원격 보관처로 자동 전달하기
  • 지점·공장·엣지 장비의 파일을 중앙으로 수집하기
  • CI/CD 빌드 결과물을 여러 서버에 배포하기
  • 서로 다른 클라우드 스토리지 사이에서 파일 이동하기
  • 서로 다른 AWS 계정의 S3 버킷 사이에 파일 전송하기
  • 고객별 파일 작업 공간 제공하기
  • 고객에게 만료 조건이 있는 대용량 다운로드 링크 제공하기
  • 고객이 브라우저에서 대용량 파일을 업로드하게 하기
  • 고객 작업 공간으로 대용량 파일 직접 보내기
  • 데이터베이스 백업 파일을 오브젝트 스토리지에 보관하기
  • Datadog으로 파일 전송 실패와 복구 알림 받기
  • 웹, 앱, 업무 시스템에 파일 전송 기능 추가하기
  • 파일 도착 후 검증·변환·후속 작업 실행하기
  • NAS, 파일 서버의 대량 파일을 클라우드로 이전하기
  • FTP 배치 작업을 관리형 파일 흐름으로 전환하기
  • Google Cloud Storage에서 Amazon S3로 직접 전송하기
  • Grafana에서 파일 전송 상태 대시보드 만들기
  • 전송된 파일의 해시값으로 무결성 자동 검증하기
  • 새 파일이 생기면 지정한 곳으로 자동 전송하기
  • Kubernetes에서 오브젝트 스토리지로 결과 파일 보내기
  • Git 밖의 대용량 파일과 빌드 결과물 자동 전달하기
  • Git으로 관리하기 어려운 파일을 자동 전달하기
  • 분산 서버의 로그·진단 파일을 중앙으로 모으기
  • 미디어 원본과 처리 결과를 단계별로 자동 전달하기
  • 수신 파일을 Microsoft Defender로 검사하고 후속 처리하기
  • 여러 단계의 파일 전송을 하나의 흐름으로 자동화하기
  • 승인된 파일을 여러 팀·지점에 자동 배포하기
  • 협력사 파일을 업무 시스템으로 자동 분류하기
  • 협력사·공급망과 정기적으로 파일 교환하기
  • 매일·매주 반복되는 파일 전송 자동화하기
  • 네트워크 중단 후 파일 전송을 자동으로 재개하기
  • rsync 작업을 관리형 파일 흐름으로 전환하기
  • 정해진 시간에 반복 파일 전송 예약하기
  • 소프트웨어·펌웨어를 여러 장비에 배포하고 결과 확인하기
  • 소프트웨어 패키지를 여러 서버·지점에 배포하기
  • 팀 폴더의 변경 파일을 여러 장비에 자동 반영하기
  • 팀 업무 폴더를 여러 PC에 자동 반영하기
  • 여러 장비의 파일을 한곳에서 찾고 직접 전송하기
  • 웹사이트에 대용량 파일 업로드·다운로드 기능 추가하기
  • 채널을 구독해 새 파일을 자동으로 받기
  • Amazon S3에서 Azure Blob으로 직접 전송하기
  • Amazon S3에서 Cloudflare R2로 파일 이전하기
  • Amazon S3 파일을 Linux 서버로 자동 내려받기
  • SCP 셸 스크립트를 CLI 기반 전송으로 전환하기
  • SFTP 계정과 배치 전송을 중앙에서 관리하기
  • Slack·Teams에서 파일 전송을 실행하고 상태 알림 받기
  • Windows 폴더의 파일을 Amazon S3로 자동 업로드하기
  • Windows와 Linux 서버 사이에 파일을 직접 전송하기

시작하기#

기본 개념#

중간 저장 없이 S3 데이터를 Cloudflare R2로 직접 이전하기

S3에 저장된 데이터를 R2로 이전할 때는 전체 데이터를 한 번에 이동할 수도 있고, 특정 Bucket이나 업무별 Prefix만 선택해 단계적으로 이전할 수도 있습니다.

기존에는 다음과 같이 중간 환경을 거쳐 파일을 이동할 수 있습니다.

Amazon S3
    │
    │ Download
    ▼
Local PC / Server
    │
    │ Upload
    ▼
Cloudflare R2

이 방식은 중간 환경의 저장 공간과 파일 관리가 추가될 수 있습니다.

직접 전송을 구성하면 S3와 R2를 하나의 전송 경로로 연결할 수 있습니다.

┌──────────────────┐
│    Amazon S3     │
│                  │
│  Source Bucket   │
└────────┬─────────┘
         │
         │ Direct Transfer
         ▼
┌──────────────────┐
│   Cloudflare R2   │
│                  │
│  Target Bucket   │
└──────────────────┘

이렇게 하면 S3 파일 선택 → R2 직접 전송 → 이전 결과 확인 → 파일 검증까지 하나의 흐름으로 관리할 수 있습니다.

이전 범위#

전체 Bucket 또는 필요한 데이터 경로를 선택해 이전하기

S3 Bucket에는 서비스 데이터, 백업 파일, 로그와 임시 파일처럼 서로 다른 목적의 파일이 함께 저장될 수 있습니다.

따라서 전체 Bucket을 그대로 이전하는 대신 실제 R2 환경에서 필요한 데이터만 선택할 수 있습니다.

예를 들어 S3에 다음과 같은 구조가 있다고 가정합니다.

source-bucket
│
├── media/
│   ├── original/
│   └── processed/
│
├── backup/
│   ├── daily/
│   └── archive/
│
├── logs/
│
└── temporary/

이 중 media/와 backup/만 R2로 이전하도록 구성할 수 있습니다.

Amazon S3                         Cloudflare R2

source-bucket                     migration-bucket
│                                 │
├── media/         ───────────▶   ├── media/
│                                 │
├── backup/        ───────────▶   ├── backup/
│                                 │
├── logs/          Not Included   │
│                                 │
└── temporary/     Not Included   │

이전 범위는 데이터의 종류와 이전 목적에 따라 구분할 수 있습니다.

설정 기준 활용
Source Bucket 이전할 S3 Bucket 지정
Source 경로 특정 Prefix 또는 폴더 선택
Target Bucket R2의 대상 Bucket 지정
Target 경로 이전 파일을 저장할 위치 구성
파일 조건 특정 확장자나 이름 규칙 선택
제외 조건 임시 파일이나 불필요한 경로 제외

이를 통해 전체 데이터를 무조건 이동하는 방식이 아니라 필요한 파일을 기준으로 단계적인 이전 작업을 구성할 수 있습니다.

이전 단계#

기존 데이터를 먼저 이동하고 변경 파일을 이어서 반영하기

대량의 데이터를 이전하는 경우 기존 파일과 이전 중 새로 생성되는 파일을 같은 방식으로 처리할 필요는 없습니다.

먼저 기존 데이터를 R2로 이전하고, 초기 이전이 완료될 때까지 S3에서 새로 생성되거나 변경되는 파일을 이후에 추가 반영하는 방식으로 구성할 수 있습니다.

전체 흐름은 다음과 같이 나눌 수 있습니다.

① 이전 범위 확인
        │
        ▼
② 기존 파일 전송
        │
        ▼
③ 파일 수·용량 비교
        │
        ▼
④ 변경 파일 확인
        │
        ▼
⑤ 추가 파일 반영
        │
        ▼
⑥ 최종 검증

이 방식은 초기 대량 전송과 이후 변경 사항을 분리해 관리할 수 있다는 점에서 대규모 파일 이전에 적합합니다.

예를 들어 서비스에서 계속 파일이 생성되는 경우 다음과 같이 구성할 수 있습니다.

Initial Migration
S3 Existing Files
        │
        ▼
Cloudflare R2
        │
        └────── Initial Result

Sync Migration
S3 New / Changed Files
        │
        ▼
Cloudflare R2
        │
        └────── Final Result

이렇게 하면 기존 데이터를 먼저 이전한 뒤 서비스 운영 중 발생한 변경 파일을 추가로 반영해 최종 전환 시점의 데이터 차이를 줄일 수 있습니다.

IT 엔지니어#

스토리지 연결#

Amazon S3와 Cloudflare R2를 각각 전송 환경에 등록하기

먼저 이전할 데이터를 저장하고 있는 Amazon S3와 새로운 저장 환경으로 사용할 Cloudflare R2를 각각 연결합니다.

Source와 Target은 서로 다른 오브젝트 스토리지이므로 파일을 읽는 범위와 저장하는 범위를 각각 관리합니다.

S3에서는 이전할 Bucket과 파일을 읽을 수 있어야 하며, R2에서는 대상 Bucket과 지정된 경로에 파일을 저장할 수 있어야 합니다.

Object Storage Connections

Amazon S3
└── Source Bucket
    └── Read Files

Cloudflare R2
└── Target Bucket
    └── Write Files

이전 작업을 시작하기 전에 다음 항목을 확인합니다.

구분 확인 내용
S3 연결 Source Bucket 접근 상태
Source 권한 이전 파일과 경로 읽기 가능 여부
R2 연결 Target Storage 연결 상태
Target Bucket 이전 파일을 저장할 Bucket 확인
저장 권한 R2에 파일을 생성하고 저장할 수 있는지 확인
전송 경로 Source와 Target의 이전 범위 확인

각 Storage의 연결 범위를 분리하면 Source의 원본 데이터 접근과 Target의 저장 환경을 독립적으로 관리하면서 하나의 Flow로 연결할 수 있습니다.

경로 설계#

S3의 파일 구조를 R2의 운영 구조에 맞춰 이전하기

스토리지 연결이 완료되면 S3에서 파일을 가져올 경로와 R2에서 파일을 저장할 위치를 설정합니다.

단순히 동일한 파일 구조를 유지할 수도 있지만, 이전 과정에서 새로운 운영 환경에 맞게 Target 구조를 변경할 수도 있습니다.

예를 들어 S3의 다음 경로를 Source로 사용할 수 있습니다.

s3://source-bucket/media/processed/

R2에서는 다음 위치를 Target으로 지정할 수 있습니다.

r2://migration-bucket/assets/media/

파일 이동 구조는 다음과 같이 구성됩니다.

Amazon S3
source-bucket
└── media/
    └── processed/
        ├── video-001.mp4
        ├── video-002.mp4
        └── image-001.jpg

              │
              │ Migration
              ▼

Cloudflare R2
migration-bucket
└── assets/
    └── media/
        ├── video-001.mp4
        ├── video-002.mp4
        └── image-001.jpg

업무 환경에 따라 여러 S3 경로를 하나의 R2 Bucket으로 통합하거나, 데이터 유형에 따라 서로 다른 R2 Bucket으로 분리할 수도 있습니다.

예를 들어 다음과 같이 구성할 수 있습니다.

                    ┌──▶ R2 / media/
                    │
S3 Source ── Flow ──┼──▶ R2 / backup/
                    │
                    └──▶ R2 / archive/

이렇게 하면 단순한 Storage 이전이 아니라 새로운 R2 환경의 데이터 구조에 맞춰 파일 저장 위치를 재구성하는 마이그레이션 흐름으로 확장할 수 있습니다.

대량 이전#

많은 파일과 대용량 데이터를 전송 작업으로 나누어 관리하기

대량 데이터를 이전할 때는 전체 작업을 하나의 단순한 파일 복사로 보기보다 실행 단위와 처리 결과를 기준으로 관리할 수 있습니다.

예를 들어 데이터 유형이나 Source 경로를 기준으로 이전 작업을 나눌 수 있습니다.

이전 구간 Source Target
미디어 파일 S3 media/ R2 assets/media/
백업 파일 S3 backup/ R2 backup/
장기 보관 S3 archive/ R2 archive/

초기 이전 과정에서는 전체 파일을 처리하고, 작업이 완료된 후에는 Runs를 통해 각 실행의 파일 수와 전송 용량을 비교할 수 있습니다.

이렇게 하면 전체 이전 범위 중 어느 데이터가 완료되었는지, 어떤 구간에서 추가 확인이 필요한지를 구분해 관리할 수 있습니다.

변경 반영#

초기 이전 이후 새로 생성되거나 변경된 파일 추가하기

초기 파일 이전이 진행되는 동안에도 S3의 원본 데이터가 계속 변경될 수 있습니다.

예를 들어 새로운 파일이 추가되거나 기존 파일이 수정되는 경우, 초기 이전 결과만으로는 S3와 R2의 최종 상태가 달라질 수 있습니다.

따라서 초기 이전 이후에는 새로 생성되거나 변경된 파일을 확인해 Target에 추가 반영할 수 있습니다.

Before Migration

S3
├── file-01
├── file-02
└── file-03


During Migration

S3
├── file-01
├── file-02  ◀ Changed
├── file-03
└── file-04  ◀ New


Final Sync

Changed / New Files
        │
        ▼
Cloudflare R2

이렇게 하면 모든 데이터를 다시 전송하는 대신 초기 이전 이후 달라진 파일을 중심으로 마지막 동기화 작업을 구성할 수 있습니다.

최종 전환 전에는 마지막 변경 파일 반영 결과를 확인해 Source와 Target의 데이터 상태를 비교할 수 있습니다.

결과 검증#

파일 수와 전체 크기를 비교하고 필요한 경우 무결성까지 확인하기

파일 이전이 완료된 후에는 단순히 Run의 상태가 완료되었는지만 확인하는 것이 아니라, 실제 이전 결과를 기준으로 Source와 Target의 상태를 확인할 수 있습니다.

먼저 전체 파일 수와 전송된 데이터 크기를 비교합니다.

Migration Result

Amazon S3                    Cloudflare R2

Files: 125,430        ───▶    Files: 125,430

Size: 18.6 TB         ───▶    Size: 18.6 TB

파일 수와 전체 용량이 예상한 결과와 다르다면 누락되었거나 추가 확인이 필요한 파일이 있는지 확인할 수 있습니다.

필요한 경우 파일의 해시값이나 체크섬을 비교해 원본과 대상 파일의 무결성도 확인할 수 있습니다.

검증 항목 확인 내용
파일 수 Source와 Target의 전체 파일 개수
전체 크기 이전된 데이터의 총 용량
파일 목록 누락 또는 추가된 파일 여부
전송 결과 성공·실패 파일과 처리 상태
무결성 원본과 대상 파일의 체크섬 비교

예를 들어 파일 수는 같지만 특정 파일의 크기나 처리 결과에 차이가 있는 경우, 해당 파일을 다시 확인하거나 필요한 파일만 재전송할 수 있습니다.

이를 통해 파일이 이동했다는 사실뿐 아니라 이전 결과가 원본 데이터와 일치하는지까지 단계적으로 확인할 수 있습니다.

전환 관리#

최종 변경 사항을 반영하고 R2 기준의 파일 운영으로 전환하기

초기 이전과 변경 파일 반영, 결과 검증이 완료되면 실제 업무에서 사용할 Storage를 S3에서 R2로 전환할 수 있습니다.

전환 전에는 다음과 같은 항목을 마지막으로 확인할 수 있습니다.

Migration Status

Initial Files       ✓ Completed
Changed Files       ✓ Synced
File Count          ✓ Verified
Total Size          ✓ Verified
Integrity Check     ✓ Verified
Target Storage      ✓ Ready

전환 흐름은 다음과 같이 이어집니다.

Amazon S3
    │
    │ Initial Migration
    ▼
Cloudflare R2
    │
    │ Changed File Sync
    ▼
Final Verification
    │
    ▼
Storage Cutover
    │
    ▼
R2-Based Operation

전환 이후에도 이전 작업의 실행 기록을 확인하면 어떤 파일이 언제 이동했는지와 최종 반영 결과를 함께 관리할 수 있습니다.

예외 대응#

이전 과정에서 확인이 필요한 파일만 구분해 다시 처리하기

대량 이전 과정에서 일부 파일의 처리 상태를 추가로 확인해야 하는 경우에는 전체 이전 작업을 처음부터 다시 실행할 필요 없이 Run의 상세 정보를 통해 문제가 발생한 구간을 확인할 수 있습니다.

문제가 발생한 위치에 따라 Source와 Target을 구분해 확인합니다.

Migration Run
       │
       ▼
  View Details
       │
       ▼
┌──────┴──────┐
│             │
▼             ▼
S3 Source     R2 Target
│             │
│             │
Path          Bucket
Permission    Target Path
File Status   Write Access
│             │
└──────┬──────┘
       ▼
   Environment Fix
       │
       ▼
      Retry
       │
       ▼
 Verification

예를 들어 S3의 특정 파일을 읽을 수 없는 경우에는 Source 경로와 접근 범위를 확인하고, R2에 저장되지 않은 파일이 있는 경우에는 Target Bucket과 저장 경로를 확인할 수 있습니다.

환경을 조정한 뒤에는 필요한 작업을 다시 실행하고, 새로운 Run에서 파일 수와 처리 결과를 다시 확인합니다.

이 가이드를 적용하면 Amazon S3 연결 → 이전 범위 선택 → Cloudflare R2 Target 구성 → 초기 대량 이전 → 변경 파일 추가 반영 → 파일 수와 전체 크기 비교 → 무결성 검증 → 최종 전환 → 실행 결과 관리까지 하나의 마이그레이션 흐름으로 구성할 수 있습니다.

이를 통해 로컬 PC나 중간 저장 서버를 거치지 않고 S3의 데이터를 Cloudflare R2로 직접 이전하고, 초기 데이터 이동부터 변경 파일 동기화와 최종 검증, Storage 전환까지 이어지는 대용량 오브젝트 스토리지 마이그레이션 환경을 구성할 수 있습니다.

개발자#

S3 객체를 R2로 이전하고 규모·실패를 확인하기

소스·대상 스토리지를 각각 장비로 등록한 뒤, 프리픽스를 지정해 전송을 만들고 종료 상태와 파일 목록을 확인합니다. 시작 전에 다음 항목을 준비합니다.

준비물 내용
INNORIX 인증 INNORIX_ACCESS_TOKEN (Authorization: Bearer)
소스 S3 장비 S3 버킷의 device ID와 원본 프리픽스 (예: assets/2026)
대상 R2 장비 R2 버킷의 device ID와 대상 프리픽스 (예: assets/2026)
런타임 Python 3 + requests · Java 17+ · Node.js 18+ · .NET 8+

Python·Node.js는 REST를 직접 호출하는 최소 api() 헬퍼와 상태 상수(STATUS_COMPLETE·TERMINAL)를 API 호출 레시피의 것을 재사용합니다. Java·C#은 번들 소스의 InnorixClient(상수 포함)와 Json(C#은 J) 헬퍼를 사용합니다. 장비 식별자(s3-src·r2-dst)와 프리픽스는 실제 값으로 바꿔 넣습니다.

S3 → R2 이전 생성#

프리픽스를 폴더 루트로 넣어(sourcePaths + sendAllFolder) 전송을 만듭니다. target-action은 overwrite로 지정해 대상 프리픽스에 같은 대상 키의 객체가 있을 때 덮어쓰도록 합니다. 전송 생성 후 monitorId로 종료 상태를 확인합니다.

import time


def transfer_objects(source, target, prefixes, target_prefix, action="overwrite"):
    transfer = api("POST", "/api/transfers/manual", {
        "sourceDevice": source,
        "targetDevice": target,
        "targetPath": target_prefix,
        "sourcePaths": prefixes,
        "sendAllFolder": True,
        "transferOptions": {"target-action": action},
    })
    return transfer["monitorId"]


def wait_transfer(monitor_id, timeout=14400, interval=5):
    deadline = time.time() + timeout
    while time.time() < deadline:
        detail = api("GET", f"/api/transfers/{monitor_id}") or {}
        if detail.get("status") in TERMINAL:
            return detail
        time.sleep(interval)
    raise TimeoutError(monitor_id)


monitor_id = transfer_objects("s3-src", "r2-dst", ["assets/2026"], "assets/2026")
detail = wait_transfer(monitor_id)
print("completed:", detail.get("status") == STATUS_COMPLETE)
static String transferObjects(InnorixClient client, String source, String target,
        List<String> prefixes, String targetPrefix, String action) {
    Map<String, Object> transfer = client.apiObj("POST", "/api/transfers/manual", Json.newObj(
            "sourceDevice", source,
            "targetDevice", target,
            "targetPath", targetPrefix,
            "sourcePaths", prefixes,
            "sendAllFolder", true,
            "transferOptions", Json.newObj("target-action", action)), null);
    return Json.str(transfer, "monitorId");
}

static Map<String, Object> waitTransfer(InnorixClient client, String monitorId,
        long timeoutSec, long intervalSec) throws InterruptedException {
    long deadline = System.currentTimeMillis() + timeoutSec * 1000;
    while (System.currentTimeMillis() < deadline) {
        Map<String, Object> detail = client.apiObj("GET", "/api/transfers/" + monitorId, null, null);
        Integer status = Json.intOrNull(detail, "status");
        if (status != null && InnorixClient.TERMINAL.contains(status))
            return detail;
        Thread.sleep(intervalSec * 1000);
    }
    throw new RuntimeException("timeout: " + monitorId);
}
async function transferObjects(source, target, prefixes, targetPrefix, action = "overwrite") {
  const transfer = await api("POST", "/api/transfers/manual", {
    sourceDevice: source,
    targetDevice: target,
    targetPath: targetPrefix,
    sourcePaths: prefixes,
    sendAllFolder: true,
    transferOptions: { "target-action": action },
  });
  return transfer.monitorId;
}

async function waitTransfer(monitorId, { timeout = 14400, interval = 5 } = {}) {
  const deadline = Date.now() + timeout * 1000;
  while (Date.now() < deadline) {
    const detail = (await api("GET", `/api/transfers/${monitorId}`)) || {};
    if (TERMINAL.has(detail.status)) return detail;
    await new Promise((r) => setTimeout(r, interval * 1000));
  }
  throw new Error(`timeout: ${monitorId}`);
}

const monitorId = await transferObjects("s3-src", "r2-dst", ["assets/2026"], "assets/2026");
const detail = await waitTransfer(monitorId);
console.log("completed:", detail.status === STATUS_COMPLETE);
static async Task<string> TransferObjectsAsync(InnorixClient client, string source, string target,
    IEnumerable<string> prefixes, string targetPrefix, string action = "overwrite")
{
    var transfer = await client.ApiObjAsync("POST", "/api/transfers/manual", new JsonObject
    {
        ["sourceDevice"] = source,
        ["targetDevice"] = target,
        ["targetPath"] = targetPrefix,
        ["sourcePaths"] = J.ArrOfStrings(prefixes),
        ["sendAllFolder"] = true,
        ["transferOptions"] = new JsonObject { ["target-action"] = action },
    });
    return J.Str(transfer, "monitorId");
}

static async Task<JsonObject> WaitTransferAsync(InnorixClient client, string monitorId,
    int timeoutSec = 14400, int intervalSec = 5)
{
    DateTime deadline = DateTime.UtcNow.AddSeconds(timeoutSec);
    while (DateTime.UtcNow < deadline)
    {
        JsonObject detail = await client.ApiObjAsync("GET", 
quot;/api/transfers/{monitorId}"
, null, null); int? status = J.IntOrNull(detail, "status"); if (status != null && InnorixClient.Terminal.Contains(status.Value)) return detail; await Task.Delay(intervalSec * 1000); } throw new TimeoutException(monitorId); }

덮어쓰기 동작 numbering을 사용하면 대상에 같은 이름의 객체가 있을 때 이름이 변경될 수 있습니다. 이전 후 대상 키를 원본과 동일하게 유지하려면 overwrite를 사용합니다.

이전 규모 확인 무결성 검증은 지원되지 않으므로, 이전 완료 후 GET /api/transfers/{id}/files로 파일 목록과 실패 객체를 확인해 이전 규모를 점검합니다.

실패 객체가 남으면 중단 후 재개 레시피의 retry_failed(GET /api/transfers/{id}/files → POST /api/transfers/{id}/retry)로 실패분만 다시 전송합니다.

구현 결과#

이 레시피를 적용하면 다음 흐름으로 S3 데이터를 R2로 이전할 수 있습니다.

Amazon S3 (s3-src) — 프리픽스 지정
   ↓
전송 생성 (overwrite) → 종료 상태까지 대기
   ↓
Cloudflare R2 (r2-dst) — 대상 프리픽스에 객체 반영
   ↓
파일 목록 확인 · 실패 객체만 재시도

스토리지 자격 증명을 코드에서 다루지 않고 device ID만으로 S3 → R2 이전을 실행하며, 파일 목록으로 규모를 확인하고 남은 실패 객체만 다시 보낼 수 있습니다.

이전Amazon S3에서 Azure Blob으로 직접 전송하기다음Amazon S3 파일을 Linux 서버로 자동 내려받기

이 페이지에서

  • 시작하기
  • 기본 개념
  • 이전 범위
  • 이전 단계
  • IT 엔지니어
  • 스토리지 연결
  • 경로 설계
  • 대량 이전
  • 변경 반영
  • 결과 검증
  • 전환 관리
  • 예외 대응
  • 개발자
  • S3 → R2 이전 생성
  • 구현 결과