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. CI/CD 빌드 결과물을 여러 서버에 배포하기

CI/CD 빌드 결과물을 여러 서버에 배포하기

빌드 완료 이벤트를 기준으로 패키지를 테스트·스테이징·운영 서버에 순서대로 배포합니다.

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 서버 사이에 파일을 직접 전송하기

시작하기#

기본 개념#

CI/CD 환경에서는 소스 코드 변경 이후 빌드와 테스트를 거쳐 생성된 패키지를 다음 환경으로 배포하는 과정이 이어집니다.

예를 들어 빌드 서버에서 생성된 애플리케이션 패키지를 먼저 테스트 서버에 전달하고, 검증이 완료되면 스테이징 서버와 운영 서버에 순서대로 배포할 수 있습니다.

이 과정에서 서버마다 직접 파일을 복사하거나 개별 배포 스크립트를 실행하면 어떤 빌드 결과물이 어느 서버까지 전달되었는지, 이전 단계의 배포가 완료되었는지 각각 확인해야 하는 작업이 발생할 수 있습니다.

INNORIX Flow를 활용하면 빌드 완료 이벤트를 기준으로 결과물을 자동으로 전송하고, 테스트·스테이징·운영 환경의 배포 흐름을 하나의 Flow로 연결할 수 있습니다.

Source Code
     │
     ▼
 CI Build
     │
     ▼
Build Artifact
     │
     ▼
Deployment Flow
     │
     ▼
 Test Server
     │
     ▼
 Verification
     │
     ▼
Staging Server
     │
     ▼
 Validation
     │
     ▼
Production Server

이렇게 구성하면 빌드 완료 → 결과물 확인 → 테스트 배포 → 검증 → 스테이징 배포 → 운영 배포 → 결과 확인까지 이어지는 파일 배포 흐름을 관리할 수 있습니다.

환경 흐름#

CI/CD 배포에서는 모든 서버에 동시에 파일을 전달하는 경우도 있지만, 일반적으로 이전 환경의 결과를 확인한 뒤 다음 환경으로 배포해야 하는 경우가 있습니다.

예를 들어 테스트 서버에 새로운 패키지를 전달한 뒤 자동 테스트를 실행하고, 결과가 확인된 이후 스테이징 환경으로 전달하도록 구성할 수 있습니다.

                    Build Artifact
                          │
                          ▼
                    Test Environment
                          │
                  ┌───────┴───────┐
                  ▼               ▼
               Passed          Check Required
                  │               │
                  ▼               ▼
             Staging          Review Run
                  │
                  ▼
             Validation
                  │
                  ▼
             Production

이처럼 각 환경을 단순한 파일 저장 위치가 아니라 다음 배포 단계의 실행 조건을 결정하는 과정으로 연결할 수 있습니다.

배포 환경 주요 역할 다음 단계
Test 빌드 결과물 확인과 테스트 Staging 배포
Staging 운영 전 환경 검증 Production 배포
Production 실제 서비스 환경 반영 결과 확인
Archive 빌드 결과물 보관 필요 시 재배포

배포 흐름을 단계별로 구성하면 특정 환경에서 추가 확인이 필요한 경우 다음 단계로 바로 진행하지 않고, 해당 단계의 결과를 기준으로 이후 작업을 관리할 수 있습니다.

배포 파일#

빌드가 완료되면 하나의 패키지만 생성되는 것이 아니라 애플리케이션 파일과 설정 파일, 배포 스크립트 등 여러 결과물이 함께 생성될 수 있습니다.

따라서 실제 배포에 필요한 파일만 선택하고, 환경별로 필요한 파일을 구분해 전달할 수 있습니다.

build-output/
│
├── package/
│   └── application-v2.5.0.tar
│
├── config/
│   ├── application.yaml
│   └── logging.yaml
│
├── scripts/
│   └── deploy.sh
│
└── metadata/
    └── build-info.json
파일 유형 활용 방식
애플리케이션 패키지 서버에 배포할 실행 파일
설정 파일 환경별 실행 조건 구성
배포 스크립트 파일 반영 후 후속 작업 연결
빌드 정보 버전과 빌드 결과 확인
임시 파일 배포 대상에서 제외

이처럼 빌드 결과물의 구성에 따라 전송 범위를 설정하면 실제 배포에 필요한 파일만 각 서버 환경으로 전달할 수 있습니다.

IT 엔지니어#

원본 구성#

먼저 CI 시스템이나 빌드 서버에서 생성되는 결과물을 Source로 연결합니다.

빌드 작업이 완료되면 지정된 결과 경로에 생성되는 패키지를 기준으로 다음 배포 작업을 시작할 수 있습니다.

CI Server
    │
    ▼
Build Completed
    │
    ▼
/var/build/releases/
    │
    ├── application-v2.5.0.tar
    ├── build-info.json
    └── deploy-files/
             │
             ▼
       Deployment Source

Source에서는 배포에 사용할 파일 범위를 함께 설정합니다.

구성 항목 설정 내용
Source CI 또는 빌드 결과물이 생성되는 시스템
Source Path 패키지가 저장되는 경로
파일 조건 확장자와 파일 이름 기준
버전 기준 빌드 번호 또는 버전별 파일 구분
제외 조건 임시 파일과 이전 작업 파일 제외

예를 들어 /var/build/releases에 생성되는 최신 .tar 또는 .zip 파일을 기준으로 다음 배포 작업을 실행하도록 구성할 수 있습니다.

실행 연결#

빌드 결과물을 전달하는 작업은 파일이 생성된 시점뿐 아니라 CI 작업의 완료 결과를 기준으로 시작할 수 있습니다.

빌드 실패 상태에서 생성된 불완전한 결과물을 전송하는 대신, 필요한 빌드 작업이 정상적으로 완료된 이후 배포 Flow를 실행하도록 연결할 수 있습니다.

CI Pipeline
     │
     ▼
Build
     │
     ▼
Build Result
 ┌───┴────┐
 │        │
Failed  Success
 │        │
 ▼        ▼
Review  Deployment Flow
             │
             ▼
        Test Server

실행 조건은 배포 방식에 따라 다르게 구성할 수 있습니다.

실행 조건 활용 방식
Build Complete 빌드 완료 후 배포 시작
After Transfer 이전 파일 작업 완료 후 실행
File Ready 지정 경로에 결과물이 준비되면 실행
Date/Time 정해진 시간에 배포
Manual Run 결과 확인 후 직접 배포
URL Request CI 시스템의 외부 요청으로 실행

이를 통해 기존 CI/CD Pipeline의 실행 구조를 유지하면서 파일 배포 단계만 별도의 관리형 Flow로 연결할 수 있습니다.

단계 배포#

테스트, 스테이징과 운영 환경을 모두 동일하게 구성할 필요는 없습니다.

예를 들어 테스트 서버에는 빌드 완료 직후 자동으로 패키지를 전달하고, 스테이징과 운영 서버는 이전 단계의 확인 결과를 기준으로 순차적으로 배포할 수 있습니다.

                    Build Artifact
                          │
                          ▼
                    ┌──────────┐
                    │   Test   │
                    └────┬─────┘
                         │
                    Test Complete
                         │
                         ▼
                  ┌────────────┐
                  │  Staging   │
                  └─────┬──────┘
                        │
                  Staging Ready
                        │
                        ▼
                 ┌──────────────┐
                 │  Production  │
                 └──────────────┘

각 환경은 다음 작업을 시작하기 위한 기준으로 활용할 수 있습니다.

배포 단계 실행 기준 배포 목적
Test 빌드 완료 자동 테스트 환경 준비
Staging 테스트 결과 확인 운영 전 검증
Production 스테이징 확인 실제 서비스 반영

이렇게 구성하면 하나의 빌드 결과물이 모든 서버에 동시에 반영되는 대신, 필요한 검증 단계를 거쳐 다음 환경으로 이동하도록 배포 흐름을 구성할 수 있습니다.

환경 분기#

경우에 따라 하나의 빌드 결과물을 여러 테스트 서버나 스테이징 서버에 동시에 배포해야 할 수 있습니다.

예를 들어 운영 체제나 서버 역할이 다른 여러 테스트 환경에서 동일한 패키지를 검증하는 경우 하나의 Source에서 여러 Target으로 배포 경로를 분기할 수 있습니다.

                 Build Artifact
                       │
                       ▼
                 Test Distribution
                       │
          ┌────────────┼────────────┐
          ▼            ▼            ▼
       Test-A        Test-B        Test-C
          │            │            │
          └────────────┼────────────┘
                       ▼
                 Result Review
                       │
                       ▼
                    Staging

이 경우 각 서버의 배포 결과를 개별적으로 확인할 수 있습니다.

예를 들어 Test-A와 Test-B는 정상적으로 완료되었지만 Test-C에서 파일 반영 상태를 추가로 확인해야 하는 경우, 전체 배포 결과와 특정 Target의 상태를 함께 확인할 수 있습니다.

버전 관리#

빌드 결과물은 배포할 때마다 동일한 파일을 덮어쓰기보다 버전이나 빌드 번호를 기준으로 구분할 수 있습니다.

예를 들어 CI에서 생성된 빌드 번호를 파일 이름이나 저장 경로에 포함하면 어떤 결과물이 어떤 환경에 배포되었는지 구분하기 쉬워집니다.

Build Source
/releases/
│
├── build-1042/
│   └── application.tar
│
├── build-1043/
│   └── application.tar
│
└── build-1044/
    └── application.tar
           │
           ▼
Deployment Targets
│
├── test/build-1044/
├── staging/build-1044/
└── production/build-1044/
관리 기준 활용 방식
Build Number CI 실행 결과별 파일 구분
Version 애플리케이션 버전별 배포
Environment Test·Staging·Production 경로 구분
Release Date 배포 시점 기준 결과 관리
Project 프로젝트별 결과물 분리
이렇게 하면 특정 버전의 패키지를 다시 배포하거나 이전 빌드 결과를 확인해야 하는 경우에도 필요한 파일을 기준으로 작업을 구성할 수 있습니다.

후속 실행#

파일이 서버에 전달된 이후에는 배포 결과를 확인하고 필요한 다음 작업을 연결할 수 있습니다.

예를 들어 테스트 서버에 패키지가 정상적으로 반영된 뒤 배포 스크립트를 실행하거나, 모든 테스트 환경의 파일 반영이 완료된 뒤 검증 작업을 시작하도록 구성할 수 있습니다.

Artifact Transfer
        │
        ▼
File Ready
        │
        ▼
┌─────────────────┐
│ Deployment Step │
└────────┬────────┘
         │
         ├── File Check
         │
         ├── Deploy Script
         │
         └── Validation
                  │
                  ▼
             Next Stage

후속 작업은 현재 배포 결과에 따라 구분할 수 있습니다.

현재 결과 다음 작업
파일 반영 완료 배포 또는 검증 작업 실행
모든 대상 완료 다음 환경 배포 시작
일부 대상 실패 해당 서버 상태 확인
파일 검증 필요 패키지 또는 파일 확인
배포 완료 운영 결과 기록 또는 알림

이렇게 하면 파일을 전달한 뒤 별도로 다음 작업을 실행하는 대신, 서버의 파일 반영 결과를 기준으로 다음 배포 단계를 이어갈 수 있습니다.

결과 확인#

배포 작업이 실행되면 Runs에서 빌드 결과물의 전송 상태와 환경별 처리 결과를 확인합니다.

테스트, 스테이징과 운영 환경이 하나의 배포 흐름으로 연결된 경우에도 각 Target의 결과를 구분해 어느 서버까지 파일이 정상적으로 반영되었는지 확인할 수 있습니다.

실행 결과에서는 다음 항목을 확인할 수 있습니다.

확인 항목 확인 내용
Source 빌드 결과물이 생성된 시스템과 경로
Target 패키지를 전달한 서버
Build 배포한 빌드 번호 또는 버전
Total Files 처리 대상 파일 수
Total Size 전체 배포 파일 크기
Progress 현재 배포 진행률
Status 환경별 실행 상태
Started 배포 시작 시간
Completed 배포 완료 시간

특정 Run을 선택하면 해당 배포 단계의 파일 처리 결과와 실행 상태를 확인할 수 있습니다.

이를 통해 여러 환경의 배포 결과를 각각의 서버 로그에서 확인하는 대신, 하나의 관리 화면에서 전체 배포 흐름과 단계별 결과를 함께 관리할 수 있습니다.

실패 대응#

특정 서버나 환경에서 빌드 결과물이 정상적으로 반영되지 않은 경우에는 Run의 상세 정보를 통해 문제가 발생한 단계와 파일 처리 상태를 확인합니다.

예를 들어 테스트 서버는 정상적으로 완료되었지만 특정 스테이징 서버에서 파일을 저장할 수 없는 경우에는 해당 Target의 연결 상태와 경로, 접근 권한을 확인할 수 있습니다.

Deployment Run
       │
       ▼
Environment Review
       │
 ┌─────┼───────────────┐
 ▼     ▼               ▼
Test ✓ Staging !   Production -
         │
         ▼
    View Details
         │
   ┌─────┼─────────┐
   ▼     ▼         ▼
Connection Path Permission
   │     │         │
   └─────┼─────────┘
         ▼
       Adjust
         │
         ▼
        Retry
         │
         ▼
       New Run
         │
         ▼
   Next Deployment

문제가 해결된 뒤에는 전체 CI 빌드 과정을 다시 시작하는 대신, 추가 확인이 필요한 배포 단계와 Target을 중심으로 필요한 작업을 다시 실행할 수 있습니다.

재실행 후에는 새로운 Run을 통해 해당 빌드 결과물이 지정된 서버에 정상적으로 반영되었는지 확인하고, 필요한 경우 다음 환경으로 이어지는 배포 작업을 진행할 수 있습니다.

이 과정을 통해 CI 빌드 완료 → 결과물 준비 → Test 배포 → 환경별 검증 → Staging 배포 → Production 배포 → 결과 확인 → 실패 단계 대응까지 이어지는 CI/CD 파일 배포 흐름을 구성할 수 있습니다.

빌드 시스템은 코드 변경과 빌드 작업을 담당하고, INNORIX Flow는 생성된 결과물을 각 서버 환경으로 전달하는 흐름을 관리하면 빌드 이후의 파일 배포 과정을 환경별·단계별로 연결하면서 전체 CI/CD 운영 흐름을 보다 명확하게 관리할 수 있습니다.

개발자#

빌드 결과물을 테스트·스테이징·운영에 단계별로 배포하기

빌드 서버와 각 환경 서버를 장비로 등록한 뒤, CI 스텝에서 단계별 전송을 만들고 성공 시에만 다음 단계로 진행합니다. 시작 전에 다음 항목을 준비합니다.

준비물 내용
INNORIX 인증 INNORIX_ACCESS_TOKEN (Authorization: Bearer)
소스 장비 빌드 서버의 device ID와 아티팩트 경로 (예: /build/out/2.14.0)
대상 장비 test·staging·prod 서버의 device ID와 배포 경로
런타임 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) 헬퍼를 사용합니다. 장비 식별자와 경로는 실제 값으로 바꿔 넣습니다.

단계별 게이트 배포#

단계 목록을 순서대로 배포하고, 각 단계가 성공(종료 상태 = 완료)해야 다음 단계로 넘어갑니다. 실패하면 그 단계에서 중단하고 실패를 반환합니다.

import time


def deploy_stage(source, source_path, target, target_path):
    transfer = api("POST", "/api/transfers/manual", {
        "sourceDevice": source,
        "targetDevice": target,
        "targetPath": target_path,
        "sourcePaths": [source_path],
        "sendAllFolder": True,
        "checkIntegrity": True,
        "transferOptions": {"target-action": "overwrite"},
    })
    detail = wait_transfer(transfer["monitorId"])
    return detail.get("status") == STATUS_COMPLETE


def deploy_pipeline(source, source_path, stages):
    # stages: [(target, target_path), ...] gated in order
    for target, target_path in stages:
        ok = deploy_stage(source, source_path, target, target_path)
        print(f"{target}: {'done' if ok else 'failed'}")
        if not ok:
            return target   # return the failed step
    return None   # all stages succeeded


def wait_transfer(monitor_id, timeout=7200, 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)


failed = deploy_pipeline("build-src", "/build/out/2.14.0", [
    ("test-01", "/opt/app"),
    ("staging-01", "/opt/app"),
    ("prod-01", "/opt/app"),
])
print("deploy result:", "all stages succeeded" if failed is None else f"{failed} stopped at stage")
static boolean deployStage(InnorixClient client, String source, String sourcePath,
        String target, String targetPath) throws InterruptedException {
    Map<String, Object> transfer = client.apiObj("POST", "/api/transfers/manual", Json.newObj(
            "sourceDevice", source,
            "targetDevice", target,
            "targetPath", targetPath,
            "sourcePaths", List.of(sourcePath),
            "sendAllFolder", true,
            "checkIntegrity", true,
            "transferOptions", Json.newObj("target-action", "overwrite")), null);
    Map<String, Object> detail = waitTransfer(client, Json.str(transfer, "monitorId"), 7200, 5);
    Integer status = Json.intOrNull(detail, "status");
    return status != null && status == InnorixClient.STATUS_COMPLETE;
}

static String deployPipeline(InnorixClient client, String source, String sourcePath,
        List<String[]> stages) throws InterruptedException {
    for (String[] stage : stages) {   // stage = {target, targetPath}
        boolean ok = deployStage(client, source, sourcePath, stage[0], stage[1]);
        System.out.println(stage[0] + ": " + (ok ? "done" : "failed"));
        if (!ok) return stage[0];
    }
    return null;
}

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 deployStage(source, sourcePath, target, targetPath) {
  const transfer = await api("POST", "/api/transfers/manual", {
    sourceDevice: source,
    targetDevice: target,
    targetPath,
    sourcePaths: [sourcePath],
    sendAllFolder: true,
    checkIntegrity: true,
    transferOptions: { "target-action": "overwrite" },
  });
  const detail = await waitTransfer(transfer.monitorId);
  return detail.status === STATUS_COMPLETE;
}

async function deployPipeline(source, sourcePath, stages) {
  for (const [target, targetPath] of stages) {
    const ok = await deployStage(source, sourcePath, target, targetPath);
    console.log(`${target}: ${ok ? "done" : "failed"}`);
    if (!ok) return target;
  }
  return null;
}

async function waitTransfer(monitorId, { timeout = 7200, 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 failed = await deployPipeline("build-src", "/build/out/2.14.0", [
  ["test-01", "/opt/app"],
  ["staging-01", "/opt/app"],
  ["prod-01", "/opt/app"],
]);
console.log("deploy result:", failed === null ? "all stages succeeded" : `${failed} stopped at stage`);
static async Task<bool> DeployStageAsync(InnorixClient client, string source, string sourcePath,
    string target, string targetPath)
{
    var transfer = await client.ApiObjAsync("POST", "/api/transfers/manual", new JsonObject
    {
        ["sourceDevice"] = source,
        ["targetDevice"] = target,
        ["targetPath"] = targetPath,
        ["sourcePaths"] = J.ArrOfStrings(new[] { sourcePath }),
        ["sendAllFolder"] = true,
        ["checkIntegrity"] = true,
        ["transferOptions"] = new JsonObject { ["target-action"] = "overwrite" },
    });
    JsonObject detail = await WaitTransferAsync(client, J.Str(transfer, "monitorId"));
    int? status = J.IntOrNull(detail, "status");
    return status != null && status == InnorixClient.StatusComplete;
}

static async Task<string> DeployPipelineAsync(InnorixClient client, string source, string sourcePath,
    IEnumerable<(string target, string targetPath)> stages)
{
    foreach (var (target, targetPath) in stages)
    {
        bool ok = await DeployStageAsync(client, source, sourcePath, target, targetPath);
        Console.WriteLine(
quot;{target}: {(ok ? "done" : "failed")}"
); if (!ok) return target; } return null; } static async Task<JsonObject> WaitTransferAsync(InnorixClient client, string monitorId, int timeoutSec = 7200, 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); }

CI 스텝 연동 이 코드는 CI 파이프라인의 배포 스텝에서 호출합니다. INNORIX_ACCESS_TOKEN은 파이프라인 시크릿으로 주입하고, 아티팩트 경로·버전은 빌드 변수로 전달합니다.

게이트 실패 처리 한 단계의 전송이 완료되지 않으면 이후 단계로 진행하지 않고 중단합니다. 실패 파일은 중단 후 재개 레시피의 retry_failed로 다시 전송할 수 있으며, 이후 단계 진행 여부는 CI 파이프라인 정책에 따라 결정합니다.

무결성 검증 조건 예제는 서버 대상 전송이라 checkIntegrity: true를 사용합니다. checkIntegrity는 무결성 검증을 지원하는 Source/Target 장비 조합에서만 사용하며, 객체 스토리지 등 지원되지 않는 대상으로 확장할 때는 적용하지 않습니다.

구현 결과#

이 레시피를 적용하면 다음 흐름으로 빌드 결과물을 단계별로 배포할 수 있습니다.

빌드 완료 (CI) → 아티팩트 전송 API 호출
&nbsp;&nbsp;&nbsp;↓

test 배포 성공 → staging 배포 성공 → prod 배포
&nbsp;&nbsp;&nbsp;↓

한 단계라도 실패하면 그 단계에서 중단

빌드 결과물을 테스트·스테이징·운영에 단계별로 배포하고, 각 단계의 파일 전송이 완료된 경우에만 다음 환경으로 진행하도록 파이프라인을 구성할 수 있습니다(애플리케이션 검증·승인 게이트는 CI 단계에서 별도로 처리).

이전지점·공장·엣지 장비의 파일을 중앙으로 수집하기다음서로 다른 클라우드 스토리지 사이에서 파일 이동하기

이 페이지에서

  • 시작하기
  • 기본 개념
  • 환경 흐름
  • 배포 파일
  • IT 엔지니어
  • 원본 구성
  • 실행 연결
  • 단계 배포
  • 환경 분기
  • 버전 관리
  • 후속 실행
  • 결과 확인
  • 실패 대응
  • 개발자
  • 단계별 게이트 배포
  • 구현 결과