> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Backup 명령을 사용한 자가 관리형 ClickHouse에서 ClickHouse Cloud로의 마이그레이션

> BACKUP 및 RESTORE 명령을 사용해 자가 관리형 ClickHouse와 ClickHouse Cloud 간에 마이그레이션하는 방법을 설명하는 페이지

export const Image = ({img, alt, size = "lg"}) => {
  const normalizedSize = ["sm", "md", "lg"].includes(size) ? size : "lg";
  return <div className={`ch-image-${normalizedSize}`}>
      <Frame>
        <img src={img} alt={alt} />
      </Frame>
    </div>;
};

<div id="overview-migration-approaches">
  ## 개요
</div>

자가 관리형 ClickHouse(OSS)에서 ClickHouse Cloud로 데이터를 마이그레이션하는 주요 방법은 두 가지입니다.

* 데이터를 직접 가져오거나 푸시하는 [`remoteSecure()`](/docs/ko/get-started/migrate/oss-to-cloud/clickhouse-to-cloud) 함수를 사용하는 방법
* 클라우드 객체 스토리지를 통해 `BACKUP`/`RESTORE` 명령을 사용하는 방법

> 이 마이그레이션 가이드는 `BACKUP`/`RESTORE` 방식에 중점을 두며, 오픈 소스 ClickHouse의 데이터베이스 또는 전체 서비스를 S3 버킷을 통해 ClickHouse Cloud로 마이그레이션하는 실용적인 예시를 제공합니다.

**사전 요구 사항**

* Docker가 설치되어 있어야 합니다
* [S3 버킷 및 IAM 사용자](/docs/ko/integrations/connectors/data-ingestion/AWS/creating-an-s3-iam-role-and-bucket)가 있어야 합니다
* 새 ClickHouse Cloud 서비스를 생성할 수 있어야 합니다

이 가이드의 단계를 쉽게 따라 하고 재현할 수 있도록, 2개의 세그먼트와 2개의 레플리카로 구성된 ClickHouse 클러스터용 Docker Compose 레시피 중 하나를 사용합니다.

<Info>
  **클러스터 필요**

  이 Backup 메서드에는 ClickHouse 클러스터가 필요합니다. 테이블을 `MergeTree` 엔진에서 `ReplicatedMergeTree`로 변환해야 하기 때문입니다.
  단일 인스턴스를 실행 중이라면 대신 ["remoteSecure()를 사용하여 자가 관리형 ClickHouse와 ClickHouse Cloud 간 마이그레이션"](/docs/ko/get-started/migrate/oss-to-cloud/clickhouse-to-cloud)의 단계를 따르십시오.
</Info>

<div id="oss-setup">
  ## OSS 준비
</div>

먼저 examples 리포지토리의 Docker Compose 구성을 사용해 ClickHouse 클러스터를 구동합니다.
이미 실행 중인 ClickHouse 클러스터가 있다면 클러스터를 구동하는 단계는 건너뛰어도 됩니다.

1. [examples 리포지토리](https://github.com/ClickHouse/examples)를 로컬 머신에 복제합니다
2. 터미널에서 `examples/docker-compose-recipes/recipes/cluster_2S_2R` 디렉터리로 `cd`합니다
3. Docker가 실행 중인지 확인한 다음 ClickHouse 클러스터를 시작합니다:

```bash theme={null}
docker compose up
```

다음과 같이 표시됩니다:

```bash theme={null}
[+] Running 7/7
 ✔ Container clickhouse-keeper-01  Created  0.1s
 ✔ Container clickhouse-keeper-02  Created  0.1s
 ✔ Container clickhouse-keeper-03  Created  0.1s
 ✔ Container clickhouse-01         Created  0.1s
 ✔ Container clickhouse-02         Created  0.1s
 ✔ Container clickhouse-04         Created  0.1s
 ✔ Container clickhouse-03         Created  0.1s
```

폴더의 루트 디렉터리에서 새 터미널 창을 열고 다음 명령을 실행하여 클러스터의 첫 번째 노드에 연결합니다:

```bash theme={null}
docker exec -it clickhouse-01 clickhouse-client
```

<div id="mergetree-to-replicatedmergetree">
  ### MergeTree 테이블에서 ReplicatedMergeTree 테이블로
</div>

ClickHouse Cloud는 [`SharedMergeTree`](/docs/ko/products/cloud/features/infrastructure/shared-merge-tree)를 사용합니다.
Backup을 복원할 때 ClickHouse는 `ReplicatedMergeTree` 테이블을 자동으로 `SharedMergeTree` 테이블로 변환합니다.

클러스터를 실행 중이라면 이미 테이블에서 `ReplicatedMergeTree` 엔진을 사용하고 있을 가능성이 높습니다.
그렇지 않다면 Backup을 수행하기 전에 `MergeTree` 테이블을 `ReplicatedMergeTree`로 변환해야 합니다.

`MergeTree` 테이블을 `ReplicatedMergeTree`로 변환하는 방법을 보여주기 위해 먼저 `MergeTree` 테이블로 시작한 다음, 이를 나중에 `ReplicatedMergeTree`로 변환하겠습니다.
새 샘플 테이블을 생성하고 데이터를 적재하기 위해 [New York taxi data guide](/docs/ko/get-started/sample-datasets/nyc-taxi)의 처음 두 단계를 따르겠습니다.
편의를 위해 해당 단계도 아래에 포함되어 있습니다.

다음 명령을 실행하여 새 데이터베이스를 생성하고 S3 버킷의 데이터를 새 테이블에 삽입합니다:

```sql theme={null}
CREATE DATABASE nyc_taxi;

CREATE TABLE nyc_taxi.trips_small_adapted (
    trip_id             UInt32,
    pickup_datetime     DateTime,
    dropoff_datetime    DateTime,
    pickup_longitude    Nullable(Float64),
    pickup_latitude     Nullable(Float64),
    dropoff_longitude   Nullable(Float64),
    dropoff_latitude    Nullable(Float64),
    passenger_count     UInt8,
    trip_distance       Float32,
    fare_amount         Float32,
    extra               Float32,
    tip_amount          Float32,
    tolls_amount        Float32,
    total_amount        Float32,
    payment_type        Enum('CSH' = 1, 'CRE' = 2, 'NOC' = 3, 'DIS' = 4, 'UNK' = 5),
    pickup_ntaname      LowCardinality(String),
    dropoff_ntaname     LowCardinality(String)
)
ENGINE = MergeTree
PRIMARY KEY (pickup_datetime, dropoff_datetime);
```

```sql theme={null}
INSERT INTO nyc_taxi.trips_small_adapted
SELECT
    trip_id,
    pickup_datetime,
    dropoff_datetime,
    pickup_longitude,
    pickup_latitude,
    dropoff_longitude,
    dropoff_latitude,
    passenger_count,
    trip_distance,
    fare_amount,
    extra,
    tip_amount,
    tolls_amount,
    total_amount,
    payment_type,
    pickup_ntaname,
    dropoff_ntaname
FROM s3(
    'https://datasets-documentation.s3.eu-west-3.amazonaws.com/nyc-taxi/trips_{0..2}.gz',
    'TabSeparatedWithNames'
);
```

다음 명령을 실행하여 테이블을 `DETACH`하십시오.

```sql theme={null}
DETACH TABLE nyc_taxi.trips_small_adapted;
```

그런 다음 이를 복제된 테이블로 ATTACH합니다:

```sql theme={null}
ATTACH TABLE nyc_taxi.trips_small_adapted AS REPLICATED;
```

마지막으로, 레플리카 메타데이터를 복원합니다:

```sql theme={null}
SYSTEM RESTORE REPLICA nyc_taxi.trips_small_adapted;
```

`ReplicatedMergeTree`로 변환되었는지 확인하세요:

```sql theme={null}
SELECT engine
FROM system.tables
WHERE name = 'trips_small_adapted' AND database = 'nyc_taxi';
```

```response theme={null}
┌─engine──────────────┐
│ ReplicatedMergeTree │
└─────────────────────┘
```

이제 나중에 S3 버킷의 백업을 복원할 수 있도록 Cloud 서비스를 설정할
준비가 되었습니다.

<div id="distributed-tables">
  ### ReplicatedMergeTree를 사용하는 분산 테이블
</div>

구성에서 여러 세그먼트에 걸쳐 분산 테이블을 사용하는 경우, 각 노드에 로컬 `ReplicatedMergeTree` 테이블이 필요하며, 쿼리 진입점 역할을 하는 `Distributed` 테이블도 필요합니다.

다음 명령을 실행하여 모든 클러스터 노드에 로컬 복제된 테이블을 생성하세요:

```sql theme={null}
CREATE DATABASE IF NOT EXISTS nyc_taxi ON CLUSTER 'cluster_2S_2R';

CREATE TABLE nyc_taxi.trips_small_dist_local ON CLUSTER 'cluster_2S_2R'
(
    trip_id             UInt32,
    pickup_datetime     DateTime,
    dropoff_datetime    DateTime,
    pickup_longitude    Nullable(Float64),
    pickup_latitude     Nullable(Float64),
    dropoff_longitude   Nullable(Float64),
    dropoff_latitude    Nullable(Float64),
    passenger_count     UInt8,
    trip_distance       Float32,
    fare_amount         Float32,
    extra               Float32,
    tip_amount          Float32,
    tolls_amount        Float32,
    total_amount        Float32,
    payment_type        Enum('CSH' = 1, 'CRE' = 2, 'NOC' = 3, 'DIS' = 4, 'UNK' = 5),
    pickup_ntaname      LowCardinality(String),
    dropoff_ntaname     LowCardinality(String)
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{database}/{table}/{shard}', '{replica}')
PRIMARY KEY (pickup_datetime, dropoff_datetime);
```

그런 다음 이를 기반으로 `Distributed` 테이블을 생성합니다:

```sql theme={null}

CREATE TABLE nyc_taxi.trips_small_dist ON CLUSTER 'cluster_2S_2R'
(
    trip_id             UInt32,
    pickup_datetime     DateTime,
    dropoff_datetime    DateTime,
    pickup_longitude    Nullable(Float64),
    pickup_latitude     Nullable(Float64),
    dropoff_longitude   Nullable(Float64),
    dropoff_latitude    Nullable(Float64),
    passenger_count     UInt8,
    trip_distance       Float32,
    fare_amount         Float32,
    extra               Float32,
    tip_amount          Float32,
    tolls_amount        Float32,
    total_amount        Float32,
    payment_type        Enum('CSH' = 1, 'CRE' = 2, 'NOC' = 3, 'DIS' = 4, 'UNK' = 5),
    pickup_ntaname      LowCardinality(String),
    dropoff_ntaname     LowCardinality(String)
)
ENGINE = Distributed('cluster_2S_2R', 'nyc_taxi', 'trips_small_dist_local', rand());
```

분산 테이블을 통해 데이터를 삽입하세요:

```sql theme={null}
INSERT INTO nyc_taxi.trips_small_dist
SELECT
    trip_id,
    pickup_datetime,
    dropoff_datetime,
    pickup_longitude,
    pickup_latitude,
    dropoff_longitude,
    dropoff_latitude,
    passenger_count,
    trip_distance,
    fare_amount,
    extra,
    tip_amount,
    tolls_amount,
    total_amount,
    payment_type,
    pickup_ntaname,
    dropoff_ntaname
FROM s3(
    'https://datasets-documentation.s3.eu-west-3.amazonaws.com/nyc-taxi/trips_{0..2}.gz',
    'TabSeparatedWithNames'
);
```

<div id="cloud-setup">
  ## Cloud 준비
</div>

데이터를 새 Cloud 서비스로 복원하게 됩니다.
아래 단계에 따라 새 Cloud 서비스를 생성하십시오.

<Steps>
  <Step title="Cloud Console 열기" id="open-cloud-console">
    [https://console.clickhouse.cloud/](https://console.clickhouse.cloud/)로 이동하십시오.
  </Step>

  <Step title="새 서비스 생성" id="create-new-service">
    <Image img="https://mintcdn.com/private-7c7dfe99/REHSqgCLT_igIuJP/images/cloud/onboard/migrate/oss_to_cloud_via_backup/create_service.webp?fit=max&auto=format&n=REHSqgCLT_igIuJP&q=85&s=d63382c21ccf486c311cab7e8186eb4b" size="md" alt="새 서비스 생성" width="2020" height="1007" data-path="images/cloud/onboard/migrate/oss_to_cloud_via_backup/create_service.webp" />
  </Step>

  <Step title="서비스 구성 및 생성" id="configure-and-create">
    원하는 리전과 구성을 선택한 다음 `Create service`를 클릭하십시오.

    <Image img="https://mintcdn.com/private-7c7dfe99/REHSqgCLT_igIuJP/images/cloud/onboard/migrate/oss_to_cloud_via_backup/service_details.webp?fit=max&auto=format&n=REHSqgCLT_igIuJP&q=85&s=10257523952ec9d5368a746647be1a74" size="md" alt="서비스 기본 설정 구성" width="926" height="598" data-path="images/cloud/onboard/migrate/oss_to_cloud_via_backup/service_details.webp" />
  </Step>

  <Step title="액세스 역할 생성" id="create-an-access-role">
    SQL 콘솔을 여십시오

    <Image img="https://mintcdn.com/private-7c7dfe99/REHSqgCLT_igIuJP/images/cloud/onboard/migrate/oss_to_cloud_via_backup/open_console.webp?fit=max&auto=format&n=REHSqgCLT_igIuJP&q=85&s=6adc11adbc7e8154501f4a9a701ca6ae" size="md" alt="서비스 기본 설정 구성" width="2020" height="1042" data-path="images/cloud/onboard/migrate/oss_to_cloud_via_backup/open_console.webp" />

    ### S3 액세스 설정

    S3에서 Backup을 복원하려면 ClickHouse Cloud와 S3 버킷 간의 보안 액세스를 구성해야 합니다.

    1. ["S3 데이터에 안전하게 액세스하기"](/docs/ko/products/cloud/guides/data-sources/accessing-s3-data-securely)의 단계에 따라 액세스 역할을 생성하고 role ARN을 가져오십시오.

    2. 이전 단계에서 얻은 role ARN을 추가하여 ["S3 버킷 및 IAM role 생성 방법"](/docs/ko/integrations/connectors/data-ingestion/AWS/creating-an-s3-iam-role-and-bucket)에서 생성한 S3 버킷 정책을 업데이트하십시오.

    업데이트된 S3 버킷 정책은 다음과 비슷합니다.

    ```json highlight={10-11} theme={null}
    {
        "Version": "2012-10-17",
        "Id": "Policy123456",
        "Statement": [
            {
                "Sid": "abc123",
                "Effect": "Allow",
                "Principal": {
                    "AWS": [
                        "arn:aws:iam::123456789123:role/ClickHouseAccess-001",
                        "arn:aws:iam::123456789123:user/docs-s3-user"
                    ]
                },
                "Action": "s3:*",
                "Resource": [
                    "arn:aws:s3:::ch-docs-s3-bucket",
                    "arn:aws:s3:::ch-docs-s3-bucket/*"
                ]
            }
        ]
    }
    ```

    이 정책에는 두 ARN이 모두 포함됩니다.

    * **IAM user** (`docs-s3-user`): 자가 관리형 ClickHouse 클러스터가 S3에 Backup할 수 있도록 허용합니다.
    * **ClickHouse Cloud role** (`ClickHouseAccess-001`): Cloud 서비스가 S3에서 복원할 수 있도록 허용합니다.
  </Step>
</Steps>

<div id="taking-a-backup-on-oss">
  ## Backup 수행하기(자가 관리형 배포)
</div>

각 세그먼트는 개별적으로 Backup해야 합니다. 각 세그먼트의 노드에 연결한 후,
세그먼트별로 고유한 대상 경로를 사용해 Backup 명령을 실행하십시오.

`BUCKET_URL`, `KEY_ID`, `SECRET_KEY`를 보유한 AWS 자격 증명으로 교체하십시오.
아직 없다면 가이드 ["S3 버킷 및 IAM role 생성 방법"](/docs/ko/integrations/connectors/data-ingestion/AWS/creating-an-s3-iam-role-and-bucket)에서
이를 준비하는 방법을 확인할 수 있습니다.

**세그먼트 1:**

```sql theme={null}
BACKUP DATABASE nyc_taxi
TO S3(
  'BUCKET_URL/backup_s1.zip',
  'KEY_ID',
  'SECRET_KEY'
)
```

**세그먼트 2:**

```sql theme={null}
BACKUP DATABASE nyc_taxi
TO S3(
  'BUCKET_URL/backup_s2.zip',
  'KEY_ID',
  'SECRET_KEY'
)
```

모든 것이 올바르게 구성되어 있으면 아래와 유사한 응답이 표시되며
여기에는 Backup에 할당된 고유 ID와 Backup 상태가 포함됩니다.

```response theme={null}
Query id: efcaf053-75ed-4924-aeb1-525547ea8d45

┌─id───────────────────────────────────┬─status─────────┐
│ e73b99ab-f2a9-443a-80b4-533efe2d40b3 │ BACKUP_CREATED │
└──────────────────────────────────────┴────────────────┘
```

<Info>
  **단일 노드 배포**

  분산 테이블을 사용하지 않는다면, 명령 하나로 전체 데이터베이스를 Backup할 수 있습니다:

  ```sql theme={null}
  BACKUP DATABASE nyc_taxi
  TO S3(
    'BUCKET_URL',
    'KEY_ID',
    'SECRET_KEY'
  )
  ```
</Info>

이제 앞서 비어 있던 S3 버킷을 확인하면 몇 개의 폴더가 생성된 것을 볼 수 있습니다:

<Image img="https://mintcdn.com/private-7c7dfe99/REHSqgCLT_igIuJP/images/cloud/onboard/migrate/oss_to_cloud_via_backup/backup_in_s3_bucket.webp?fit=max&auto=format&n=REHSqgCLT_igIuJP&q=85&s=90c1745ad3e7598afca98936aca88171" size="md" alt="Backup, 데이터 및 메타데이터" width="2020" height="780" data-path="images/cloud/onboard/migrate/oss_to_cloud_via_backup/backup_in_s3_bucket.webp" />

전체 마이그레이션을 수행하는 경우에는, 다음 명령으로 전체 서버를 Backup할 수 있습니다:

```sql theme={null}
BACKUP
TABLE system.users,
TABLE system.roles,
TABLE system.settings_profiles,
TABLE system.row_policies,
TABLE system.quotas,
TABLE system.functions,
ALL EXCEPT DATABASES INFORMATION_SCHEMA, information_schema, system
TO S3(
  'BUCKET_ID',
  'KEY_ID',
  'SECRET_ID'
)
SETTINGS
  compression_method='lzma',
  compression_level=3;
```

위 명령은 다음 항목을 Backup합니다:

* 모든 사용자 데이터베이스와 테이블
* 사용자 계정과 비밀번호
* 역할 및 권한
* 설정 프로필
* 행 정책
* 쿼터
* 사용자 정의 함수

다른 클라우드 서비스 제공업체(CSP)를 사용하는 경우 `TO S3()`(AWS와 GCP 모두) 및 `TO AzureBlobStorage()` 구문을 사용할 수 있습니다.

데이터베이스가 매우 큰 경우 Backup을 백그라운드에서 실행하도록 `ASYNC` 사용을 고려하십시오:

```sql theme={null}
BACKUP DATABASE my_database 
TO S3('https://your-bucket.s3.amazonaws.com/backup.zip', 'key', 'secret')
ASYNC;
       
-- Returns immediately with backup ID
-- Example result:
-- ┌─id──────────────────────────────────┬─status────────────┐
-- │ abc123-def456-789                   │ CREATING_BACKUP   │
-- └─────────────────────────────────────┴───────────────────┘
```

그런 다음 Backup ID를 사용하여 Backup 진행 상태를 모니터링할 수 있습니다:

```sql theme={null}
SELECT * 
FROM system.backups 
WHERE id = 'abc123-def456-789'
```

증분 Backup도 생성할 수 있습니다.
Backup 전반에 대한 자세한 내용은 [Backup 및 복원](/docs/ko/concepts/features/backup-restore/overview) 문서를 참조하십시오.

<div id="restore-to-clickhouse-cloud">
  ## ClickHouse Cloud로 복원
</div>

각 세그먼트의 Backup을 하나씩 순서대로 Cloud 서비스에 복원합니다. `ROLE_ARN`은
["S3 데이터에 안전하게 액세스하기"](/docs/ko/products/cloud/guides/data-sources/accessing-s3-data-securely)에서 얻은
값으로 설정합니다.
두 번째 복원부터(그리고 그 이후의 모든 복원에서도) 충돌로 실패하지 않고 세그먼트 데이터가 이미 복원된 테이블에
추가되도록 `SETTINGS allow_non_empty_tables=true`를 사용합니다.

**세그먼트 1:**

```sql theme={null}
RESTORE DATABASE nyc_taxi
FROM S3(
    'BUCKET_URL/backup_s1.zip',
    extra_credentials(role_arn = 'ROLE_ARN')
)
```

**세그먼트 2:**

```sql theme={null}
RESTORE DATABASE nyc_taxi
FROM S3(
    'BUCKET_URL/backup_s2.zip',
    extra_credentials(role_arn = 'ROLE_ARN')
)
SETTINGS allow_non_empty_tables=true;
```

<Info>
  **비분산 배포**

  분산 테이블을 사용하지 않는 경우, 단일 명령으로 데이터베이스를 복원할 수 있습니다:

  ```sql theme={null}
  RESTORE DATABASE nyc_taxi
  FROM S3(
      'BUCKET_URL',
      extra_credentials(role_arn = 'ROLE_ARN')
  )
  ```
</Info>

전체 서비스도 비슷한 방식으로 복원할 수 있습니다:

```sql theme={null}
RESTORE
    TABLE system.users,
    TABLE system.roles,
    TABLE system.settings_profiles,
    TABLE system.row_policies,
    TABLE system.quotas,
    ALL EXCEPT DATABASES INFORMATION_SCHEMA, information_schema, system
FROM S3(
    'BUCKET_URL',
    extra_credentials(role_arn = 'ROLE_ARN')
)
```

복원이 완료되면 Cloud에서 데이터가 사용 가능한지 확인할 수 있습니다.

```sql theme={null}
-- ClickHouse Cloud가 로컬 테이블의 모든 데이터를 복원합니다
SELECT count() from nyc_taxi.trips_small_dist_local;
3000317
```

ClickHouse Cloud는 내부적으로 `SharedMergeTree`를 사용하므로 기존 분산 테이블은 더 이상 필요하지 않습니다. 이를 삭제하고, 쿼리에서 기존 테이블 이름을 그대로 사용할 수 있도록 뷰로 대체할 수 있습니다:

```sql theme={null}
DROP TABLE drop table nyc_taxi.trips_small_dist;
CREATE VIEW nyc_taxi.trips_small_dist AS SELECT * FROM nyc_taxi.trips_small_dist_local;
SELECT count() from nyc_taxi.trips_small_dist;
3000317
```

분산형이 아닌 `ReplicatedMergeTree` 테이블은 `SharedMergeTree`로 복원됩니다:

```sql theme={null}
SELECT count() FROM nyc_taxi.trips_small_adapted;
3000317
```
