> ## 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.

# 복제 + 스케일링

> 이 튜토리얼을 따라 하면 간단한 ClickHouse 클러스터를 설정하는 방법을 익힐 수 있습니다.

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>;
};

> 이 예시에서는 복제와 확장을 모두 지원하는 간단한 ClickHouse 클러스터를 설정하는 방법을 알아봅니다. 이 클러스터는 2개의 세그먼트와 2개의 레플리카로 구성되며, 조정을 관리하고 클러스터에서 quorum을 유지하기 위한 3노드 ClickHouse Keeper 클러스터를 포함합니다.

설정할 클러스터의 아키텍처는 아래와 같습니다.

<Image img="https://mintcdn.com/private-7c7dfe99/NvnCM4vX9aZ07JxK/images/deployment-guides/replication-sharding-examples/both.webp?fit=max&auto=format&n=NvnCM4vX9aZ07JxK&q=85&s=444ba6cf62f0cd793a61a70b98468d6c" size="md" alt="2개 세그먼트와 1개 레플리카의 아키텍처 다이어그램" width="1200" height="800" data-path="images/deployment-guides/replication-sharding-examples/both.webp" />

<Note>
  ClickHouse 서버와 ClickHouse Keeper를 동일한 서버에서 함께 실행할 수는 있지만,
  프로덕션 환경에서는 ClickHouse Keeper용 *전용* 호스트를 사용하는 것을 강력히 권장합니다.
  이 예시에서도 이 방식을 보여드립니다.

  Keeper 서버는 더 작은 사양으로도 충분하며, 일반적으로 각 Keeper 서버에는 4GB RAM이면 충분합니다.
  ClickHouse 서버 규모가 커지기 전까지는 그렇습니다.
</Note>

<div id="prerequisites">
  ## 사전 요구 사항
</div>

* 이전에 [로컬 ClickHouse 서버](/docs/ko/get-started/setup/install)를 설정해 본 적이 있습니다
* [설정 파일](/docs/ko/concepts/features/configuration/server-config/configuration-files) 등 ClickHouse의 기본 구성 개념을 이해하고 있습니다
* 시스템에 Docker가 설치되어 있습니다

<Steps>
  <Step title="디렉터리 구조 및 테스트 환경 설정" id="set-up">
    <Tip>
      **예시 파일**

      다음 단계에서는 클러스터를 처음부터 설정하는 방법을 안내합니다. 이 단계를 건너뛰고 바로
      클러스터를 실행하려면, examples 리포지토리의 ['docker-compose-recipes' 디렉터리](https://github.com/ClickHouse/examples/tree/main/docker-compose-recipes/recipes)에서 예시
      파일을 가져올 수 있습니다.
    </Tip>

    이 튜토리얼에서는 [Docker compose](https://docs.docker.com/compose/)를 사용해
    ClickHouse 클러스터를 설정합니다. 이 구성은 별도의 로컬 머신, 가상 머신 또는 클라우드 인스턴스에서도 작동하도록
    수정할 수 있습니다.

    이 예시의 디렉터리 구조를 설정하려면 다음 명령을 실행하십시오.

    ```bash theme={null}
    mkdir cluster_2S_2R
    cd cluster_2S_2R

    # Create clickhouse-keeper directories
    for i in {01..03}; do
      mkdir -p fs/volumes/clickhouse-keeper-${i}/etc/clickhouse-keeper
    done

    # Create clickhouse-server directories
    for i in {01..04}; do
      mkdir -p fs/volumes/clickhouse-${i}/etc/clickhouse-server
    done
    ```

    다음 `docker-compose.yml` 파일을 `clickhouse-cluster` 디렉터리에 추가하세요:

    ```yaml title="docker-compose.yml" theme={null}
    version: '3.8'
    services:
      clickhouse-01:
        image: "clickhouse/clickhouse-server:latest"
        user: "101:101"
        container_name: clickhouse-01
        hostname: clickhouse-01
        volumes:
          - ${PWD}/fs/volumes/clickhouse-01/etc/clickhouse-server/config.d/config.xml:/etc/clickhouse-server/config.d/config.xml
          - ${PWD}/fs/volumes/clickhouse-01/etc/clickhouse-server/users.d/users.xml:/etc/clickhouse-server/users.d/users.xml
        ports:
          - "127.0.0.1:8123:8123"
          - "127.0.0.1:9000:9000"
        depends_on:
          - clickhouse-keeper-01
          - clickhouse-keeper-02
          - clickhouse-keeper-03
      clickhouse-02:
        image: "clickhouse/clickhouse-server:latest"
        user: "101:101"
        container_name: clickhouse-02
        hostname: clickhouse-02
        volumes:
          - ${PWD}/fs/volumes/clickhouse-02/etc/clickhouse-server/config.d/config.xml:/etc/clickhouse-server/config.d/config.xml
          - ${PWD}/fs/volumes/clickhouse-02/etc/clickhouse-server/users.d/users.xml:/etc/clickhouse-server/users.d/users.xml
        ports:
          - "127.0.0.1:8124:8123"
          - "127.0.0.1:9001:9000"
        depends_on:
          - clickhouse-keeper-01
          - clickhouse-keeper-02
          - clickhouse-keeper-03
      clickhouse-03:
        image: "clickhouse/clickhouse-server:latest"
        user: "101:101"
        container_name: clickhouse-03
        hostname: clickhouse-03
        volumes:
          - ${PWD}/fs/volumes/clickhouse-03/etc/clickhouse-server/config.d/config.xml:/etc/clickhouse-server/config.d/config.xml
          - ${PWD}/fs/volumes/clickhouse-03/etc/clickhouse-server/users.d/users.xml:/etc/clickhouse-server/users.d/users.xml
        ports:
          - "127.0.0.1:8125:8123"
          - "127.0.0.1:9002:9000"
        depends_on:
          - clickhouse-keeper-01
          - clickhouse-keeper-02
          - clickhouse-keeper-03
      clickhouse-04:
        image: "clickhouse/clickhouse-server:latest"
        user: "101:101"
        container_name: clickhouse-04
        hostname: clickhouse-04
        volumes:
          - ${PWD}/fs/volumes/clickhouse-04/etc/clickhouse-server/config.d/config.xml:/etc/clickhouse-server/config.d/config.xml
          - ${PWD}/fs/volumes/clickhouse-04/etc/clickhouse-server/users.d/users.xml:/etc/clickhouse-server/users.d/users.xml
        ports:
          - "127.0.0.1:8126:8123"
          - "127.0.0.1:9003:9000"
        depends_on:
          - clickhouse-keeper-01
          - clickhouse-keeper-02
          - clickhouse-keeper-03
      clickhouse-keeper-01:
        image: "clickhouse/clickhouse-keeper:latest-alpine"
        user: "101:101"
        container_name: clickhouse-keeper-01
        hostname: clickhouse-keeper-01
        volumes:
          - ${PWD}/fs/volumes/clickhouse-keeper-01/etc/clickhouse-keeper/keeper_config.xml:/etc/clickhouse-keeper/keeper_config.xml
        ports:
          - "127.0.0.1:9181:9181"
      clickhouse-keeper-02:
        image: "clickhouse/clickhouse-keeper:latest-alpine"
        user: "101:101"
        container_name: clickhouse-keeper-02
        hostname: clickhouse-keeper-02
        volumes:
          - ${PWD}/fs/volumes/clickhouse-keeper-02/etc/clickhouse-keeper/keeper_config.xml:/etc/clickhouse-keeper/keeper_config.xml
        ports:
          - "127.0.0.1:9182:9181"
      clickhouse-keeper-03:
        image: "clickhouse/clickhouse-keeper:latest-alpine"
        user: "101:101"
        container_name: clickhouse-keeper-03
        hostname: clickhouse-keeper-03
        volumes:
          - ${PWD}/fs/volumes/clickhouse-keeper-03/etc/clickhouse-keeper/keeper_config.xml:/etc/clickhouse-keeper/keeper_config.xml
        ports:
          - "127.0.0.1:9183:9181"
    ```

    다음 하위 디렉터리와 파일을 생성하십시오:

    ```bash theme={null}
    for i in {01..04}; do
      mkdir -p fs/volumes/clickhouse-${i}/etc/clickhouse-server/config.d
      mkdir -p fs/volumes/clickhouse-${i}/etc/clickhouse-server/users.d
      touch fs/volumes/clickhouse-${i}/etc/clickhouse-server/config.d/config.xml
      touch fs/volumes/clickhouse-${i}/etc/clickhouse-server/users.d/users.xml
    done
    ```

    * `config.d` 디렉터리에는 ClickHouse 서버 설정 파일 `config.xml`이 있으며,
      여기에서 각 ClickHouse 노드의 사용자 지정 구성을 정의합니다. 이
      구성은 모든 ClickHouse 설치에 함께 제공되는 기본 `config.xml` ClickHouse 설정
      파일과 결합됩니다.
    * `users.d` 디렉터리에는 사용자 설정 파일 `users.xml`이 있으며,
      여기에서 사용자별 사용자 지정 구성을 정의합니다. 이 구성은 모든
      ClickHouse 설치에 함께 제공되는 기본 ClickHouse `users.xml` 설정 파일과 결합됩니다.

    <Tip>
      **사용자 지정 구성 디렉터리**

      자체 구성을 작성할 때는 `/etc/clickhouse-server/config.xml` 및 `etc/clickhouse-server/users.xml`의
      기본 구성을 직접 수정하기보다 `config.d` 및 `users.d` 디렉터리를
      사용하는 것을 권장합니다.

      다음 줄은

      ```xml theme={null}
      <clickhouse replace="true">
      ```

      `config.d` 및 `users.d` 디렉터리에 정의된 구성 섹션이
      기본 `config.xml` 및 `users.xml` 파일에 정의된 기본 구성 섹션을
      재정의하도록 합니다.
    </Tip>
  </Step>

  <Step title="ClickHouse 노드 구성" id="configure-clickhouse-servers">
    ### 서버 설정

    이제 `fs/volumes/clickhouse-{}/etc/clickhouse-server/config.d`에 위치한 각 빈 설정 파일 `config.xml`을 수정하십시오. 아래에 강조 표시된 줄은 각 노드에 맞게 수정해야 합니다:

    ```xml highlight={9,64-67} theme={null}
    <clickhouse replace="true">
        <logger>
            <level>debug</level>
            <log>/var/log/clickhouse-server/clickhouse-server.log</log>
            <errorlog>/var/log/clickhouse-server/clickhouse-server.err.log</errorlog>
            <size>1000M</size>
            <count>3</count>
        </logger>
        <display_name>cluster_2S_2R node 1</display_name>
        <listen_host>0.0.0.0</listen_host>
        <http_port>8123</http_port>
        <tcp_port>9000</tcp_port>
        <user_directories>
            <users_xml>
                <path>users.xml</path>
            </users_xml>
            <local_directory>
                <path>/var/lib/clickhouse/access/</path>
            </local_directory>
        </user_directories>
        <distributed_ddl>
            <path>/clickhouse/task_queue/ddl</path>
        </distributed_ddl>
        <remote_servers>
            <cluster_2S_2R>
                <shard>
                    <internal_replication>true</internal_replication>
                    <replica>
                        <host>clickhouse-01</host>
                        <port>9000</port>
                    </replica>
                    <replica>
                        <host>clickhouse-03</host>
                        <port>9000</port>
                    </replica>
                </shard>
                <shard>
                    <internal_replication>true</internal_replication>
                    <replica>
                        <host>clickhouse-02</host>
                        <port>9000</port>
                    </replica>
                    <replica>
                        <host>clickhouse-04</host>
                        <port>9000</port>
                    </replica>
                </shard>
            </cluster_2S_2R>
        </remote_servers>
        <zookeeper>
            <node>
                <host>clickhouse-keeper-01</host>
                <port>9181</port>
            </node>
            <node>
                <host>clickhouse-keeper-02</host>
                <port>9181</port>
            </node>
            <node>
                <host>clickhouse-keeper-03</host>
                <port>9181</port>
            </node>
        </zookeeper>
        <macros>
            <shard>01</shard>
            <replica>01</replica>
        </macros>
    </clickhouse>
    ```

    | 디렉터리                                                      | 파일                                                                                                                                                                               |
    | --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `fs/volumes/clickhouse-01/etc/clickhouse-server/config.d` | [`config.xml`](https://github.com/ClickHouse/examples/blob/main/docker-compose-recipes/recipes/cluster_2S_2R/fs/volumes/clickhouse-01/etc/clickhouse-server/config.d/config.xml) |
    | `fs/volumes/clickhouse-02/etc/clickhouse-server/config.d` | [`config.xml`](https://github.com/ClickHouse/examples/blob/main/docker-compose-recipes/recipes/cluster_2S_2R/fs/volumes/clickhouse-02/etc/clickhouse-server/config.d/config.xml) |
    | `fs/volumes/clickhouse-03/etc/clickhouse-server/config.d` | [`config.xml`](https://github.com/ClickHouse/examples/blob/main/docker-compose-recipes/recipes/cluster_2S_2R/fs/volumes/clickhouse-03/etc/clickhouse-server/config.d/config.xml) |
    | `fs/volumes/clickhouse-04/etc/clickhouse-server/config.d` | [`config.xml`](https://github.com/ClickHouse/examples/blob/main/docker-compose-recipes/recipes/cluster_2S_2R/fs/volumes/clickhouse-04/etc/clickhouse-server/config.d/config.xml) |

    위 설정 파일의 각 섹션에 대해서는 아래에서 더 자세히 설명합니다.

    #### 네트워킹 및 로깅

    listen
    host 설정을 활성화하면 네트워크 인터페이스에 대한 외부 통신이 허용됩니다. 이렇게 하면 다른
    호스트에서 ClickHouse 서버 호스트에 접근할 수 있습니다:

    ```xml theme={null}
    <listen_host>0.0.0.0</listen_host>
    ```

    HTTP API 포트는 `8123`으로 설정됩니다:

    ```xml theme={null}
    <http_port>8123</http_port>
    ```

    clickhouse-client
    및 기타 네이티브 ClickHouse 도구와 clickhouse-server 및 기타 clickhouse-servers 간에 ClickHouse 네이티브 프로토콜로 통신하는 데 사용하는 TCP 포트는 `9000`으로 설정됩니다:

    ```xml theme={null}
    <tcp_port>9000</tcp_port>
    ```

    로깅 구성은 `<logger>` 블록에서 정의합니다. 다음 예시 구성은 1000M마다 최대 3회 롤오버되는 디버그 로그를 설정합니다:

    ```xml theme={null}
    <logger>
       <level>debug</level>
       <log>/var/log/clickhouse-server/clickhouse-server.log</log>
       <errorlog>/var/log/clickhouse-server/clickhouse-server.err.log</errorlog>
       <size>1000M</size>
       <count>3</count>
    </logger>
    ```

    로깅 구성에 대한 자세한 내용은 기본 ClickHouse [설정 파일](https://github.com/ClickHouse/ClickHouse/blob/master/programs/server/config.xml)에 포함된 주석을 참조하십시오.

    #### 클러스터 구성

    클러스터 구성은 `<remote_servers>` 블록에서 설정합니다.
    여기서는 클러스터 이름을 `cluster_2S_2R`로 정의합니다.

    `<cluster_2S_2R></cluster_2S_2R>` 블록은 `<shard></shard>` 및 `<replica></replica>` 설정을 사용하여
    클러스터의 레이아웃을 정의하며, `ON CLUSTER` 절을 사용하여 클러스터 전체에서 실행되는
    분산 DDL 쿼리의 템플릿 역할을 합니다. 기본적으로 분산 DDL 쿼리는 허용되지만,
    `allow_distributed_ddl_queries` 설정으로 비활성화할 수도 있습니다.

    데이터가 레플리카 하나에만 기록되도록 `internal_replication`을 true로 설정합니다.

    ```xml theme={null}
    <remote_servers>
       <!-- cluster name (should not contain dots) -->
      <cluster_2S_2R>
          <!-- <allow_distributed_ddl_queries>false</allow_distributed_ddl_queries> -->
          <shard>
              <!-- Optional. Whether to write data to just one of the replicas. Default: false (write data to all replicas). -->
              <internal_replication>true</internal_replication>
              <replica>
                  <host>clickhouse-01</host>
                  <port>9000</port>
              </replica>
              <replica>
                  <host>clickhouse-03</host>
                  <port>9000</port>
              </replica>
          </shard>
          <shard>
              <internal_replication>true</internal_replication>
              <replica>
                  <host>clickhouse-02</host>
                  <port>9000</port>
              </replica>
              <replica>
                  <host>clickhouse-04</host>
                  <port>9000</port>
              </replica>
          </shard>
      </cluster_2S_2R>
    </remote_servers>
    ```

    `<cluster_2S_2R></cluster_2S_2R>` 섹션은 클러스터의 구성을 정의하며, `ON CLUSTER` 절을 사용해 클러스터 전체에서 실행되는 분산 DDL 쿼리의 템플릿 역할을 합니다.

    #### Keeper 구성

    `<ZooKeeper>` 섹션은 ClickHouse Keeper(또는 ZooKeeper)가 실행 중인 위치를 ClickHouse에 알려줍니다.
    Keeper 클러스터를 사용하는 경우, 클러스터의 각 `<node>`를 지정해야 하며,
    호스트명과 포트 번호는 각각 `<host>` 및 `<port>` 태그를 사용하여 지정합니다.

    ClickHouse Keeper 설정은 튜토리얼의 다음 단계에서 설명합니다.

    ```xml theme={null}
    <zookeeper>
        <node>
            <host>clickhouse-keeper-01</host>
            <port>9181</port>
        </node>
        <node>
            <host>clickhouse-keeper-02</host>
            <port>9181</port>
        </node>
        <node>
            <host>clickhouse-keeper-03</host>
            <port>9181</port>
        </node>
    </zookeeper>
    ```

    <Note>
      ClickHouse Keeper를 ClickHouse 서버와 같은 서버에서 실행할 수도 있지만,
      운영 환경에서는 ClickHouse Keeper를 전용 호스트에서 실행하는 것을 강력히 권장합니다.
    </Note>

    #### 매크로 구성

    또한 `<macros>` 섹션은 복제된 테이블의 매개변수 치환을 정의하는 데 사용됩니다. 이 항목들은 `system.macros`에 나열되며, 쿼리에서 `{shard}` 및 `{replica}` 같은 치환을 사용할 수 있습니다.

    ```xml theme={null}
    <macros>
       <shard>01</shard>
       <replica>01</replica>
    </macros>
    ```

    ### 사용자 구성

    이제 `fs/volumes/clickhouse-{}/etc/clickhouse-server/users.d`에 있는 빈 설정 파일 `users.xml`을 각각 아래 내용으로 수정하십시오.

    ```xml title="/users.d/users.xml" theme={null}
    <?xml version="1.0"?>
    <clickhouse replace="true">
        <profiles>
            <default>
                <max_memory_usage>10000000000</max_memory_usage>
                <use_uncompressed_cache>0</use_uncompressed_cache>
                <load_balancing>in_order</load_balancing>
                <log_queries>1</log_queries>
            </default>
        </profiles>
        <users>
            <default>
                <access_management>1</access_management>
                <profile>default</profile>
                <networks>
                    <ip>::/0</ip>
                </networks>
                <quota>default</quota>
                <access_management>1</access_management>
                <named_collection_control>1</named_collection_control>
                <show_named_collections>1</show_named_collections>
                <show_named_collections_secrets>1</show_named_collections_secrets>
            </default>
        </users>
        <quotas>
            <default>
                <interval>
                    <duration>3600</duration>
                    <queries>0</queries>
                    <errors>0</errors>
                    <result_rows>0</result_rows>
                    <read_rows>0</read_rows>
                    <execution_time>0</execution_time>
                </interval>
            </default>
        </quotas>
    </clickhouse>
    ```

    이 예시에서는 편의상 default user에 password를 설정하지 않았습니다.
    실제 환경에서는 권장하지 않는 방법입니다.

    <Note>
      이 예시에서는 클러스터의 모든 노드에서 `users.xml` 파일이 동일합니다.
    </Note>
  </Step>

  <Step title="ClickHouse Keeper 구성" id="configure-clickhouse-keeper-nodes">
    다음으로 조정 기능에 사용되는 ClickHouse Keeper를 구성합니다.

    ### Keeper 설정

    복제가 작동하려면 ClickHouse Keeper 클러스터를 설정하고
    구성해야 합니다. ClickHouse Keeper는 데이터 복제를 위한 조정 시스템을 제공하며,
    대체 구성 요소로 Zookeeper를 사용할 수도 있습니다.
    하지만 ClickHouse Keeper는 ZooKeeper보다 더 나은 보장과
    신뢰성을 제공하고 리소스도 더 적게 사용하므로 권장됩니다. 고가용성을 확보하고
    쿼럼을 유지하려면 최소 3개의 ClickHouse Keeper 노드를 실행하는 것이 좋습니다.

    <Note>
      ClickHouse Keeper는 클러스터의 어느 노드에서든 ClickHouse와 함께 실행할 수 있지만,
      ClickHouse Keeper 클러스터를 데이터베이스 클러스터와 독립적으로 스케일링하고
      관리할 수 있도록 전용 노드에서 실행하는 것이 좋습니다.
    </Note>

    다음 명령을 사용하여 예시 폴더의 루트에서
    각 ClickHouse Keeper 노드용 `keeper_config.xml` 파일을 생성하세요:

    ```bash theme={null}
    for i in {01..03}; do
      touch fs/volumes/clickhouse-keeper-${i}/etc/clickhouse-keeper/keeper_config.xml
    done
    ```

    각 노드의
    디렉터리 `fs/volumes/clickhouse-keeper-{}/etc/clickhouse-keeper`에 생성된 빈 설정 파일을 수정합니다. 아래에서
    강조 표시된 줄은 각 노드별로 맞게 변경해야 합니다:

    ```xml title="/clickhouse-keeper/keeper_config.xml" highlight={12} theme={null}
    <clickhouse replace="true">
        <logger>
            <level>information</level>
            <log>/var/log/clickhouse-keeper/clickhouse-keeper.log</log>
            <errorlog>/var/log/clickhouse-keeper/clickhouse-keeper.err.log</errorlog>
            <size>1000M</size>
            <count>3</count>
        </logger>
        <listen_host>0.0.0.0</listen_host>
        <keeper_server>
            <tcp_port>9181</tcp_port>
            <server_id>1</server_id>
            <log_storage_path>/var/lib/clickhouse/coordination/log</log_storage_path>
            <snapshot_storage_path>/var/lib/clickhouse/coordination/snapshots</snapshot_storage_path>
            <coordination_settings>
                <operation_timeout_ms>10000</operation_timeout_ms>
                <session_timeout_ms>30000</session_timeout_ms>
                <raft_logs_level>information</raft_logs_level>
            </coordination_settings>
            <raft_configuration>
                <server>
                    <id>1</id>
                    <hostname>clickhouse-keeper-01</hostname>
                    <port>9234</port>
                </server>
                <server>
                    <id>2</id>
                    <hostname>clickhouse-keeper-02</hostname>
                    <port>9234</port>
                </server>
                <server>
                    <id>3</id>
                    <hostname>clickhouse-keeper-03</hostname>
                    <port>9234</port>
                </server>
            </raft_configuration>
        </keeper_server>
    </clickhouse>
    ```

    | 디렉터리                                                    | 파일                                                                                                                                                                                           |
    | ------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `fs/volumes/clickhouse-keeper-01/etc/clickhouse-keeper` | [`keeper_config.xml`](https://github.com/ClickHouse/examples/blob/main/docker-compose-recipes/recipes/cluster_2S_2R/fs/volumes/clickhouse-keeper-01/etc/clickhouse-keeper/keeper_config.xml) |
    | `fs/volumes/clickhouse-keeper-02/etc/clickhouse-keeper` | [`keeper_config.xml`](https://github.com/ClickHouse/examples/blob/main/docker-compose-recipes/recipes/cluster_2S_2R/fs/volumes/clickhouse-keeper-02/etc/clickhouse-keeper/keeper_config.xml) |
    | `fs/volumes/clickhouse-keeper-03/etc/clickhouse-keeper` | [`keeper_config.xml`](https://github.com/ClickHouse/examples/blob/main/docker-compose-recipes/recipes/cluster_2S_2R/fs/volumes/clickhouse-keeper-03/etc/clickhouse-keeper/keeper_config.xml) |

    각 설정 파일에는 다음과 같은 고유한 구성이 포함되어야 합니다(아래 참조).
    사용할 `server_id`는 cluster 내 해당 ClickHouse Keeper 노드에서 고유해야 하며,
    `<raft_configuration>` 섹션에 정의된 서버 `<id>`와 일치해야 합니다.
    `tcp_port`는 ClickHouse Keeper의 *클라이언트*가 사용하는 포트입니다.

    ```xml theme={null}
    <tcp_port>9181</tcp_port>
    <server_id>{id}</server_id>
    ```

    다음 섹션은 [Raft 합의 알고리즘](https://en.wikipedia.org/wiki/Raft_\(algorithm\))의
    쿼럼에 참여하는 서버를 구성하는 데 사용됩니다:

    ```xml highlight={6} theme={null}
    <raft_configuration>
        <server>
            <id>1</id>
            <hostname>clickhouse-keeper-01</hostname>
            <!-- ClickHouse Keeper 노드 간 통신에 사용되는 TCP 포트 -->
            <port>9234</port>
        </server>
        <server>
            <id>2</id>
            <hostname>clickhouse-keeper-02</hostname>
            <port>9234</port>
        </server>
        <server>
            <id>3</id>
            <hostname>clickhouse-keeper-03</hostname>
            <port>9234</port>
        </server>
    </raft_configuration>
    ```

    <Tip>
      **ClickHouse Cloud로 관리가 간소화됩니다**

      [ClickHouse Cloud](/docs/ko/products/cloud/getting-started/intro)
      에서는 세그먼트와 레플리카 관리에 따른 운영 부담이 사라집니다. 이
      플랫폼은 고가용성, 복제, 스케일링을 자동으로 처리합니다.
      컴퓨트와 스토리지는 분리되어 있으며, 수요에 따라 수동
      구성이나 지속적인 유지 관리 없이 확장됩니다.

      [자세히 보기](/docs/ko/products/cloud/features/autoscaling/overview)
    </Tip>
  </Step>

  <Step title="설정 테스트" id="test-the-setup">
    로컬 환경에서 docker가 실행 중인지 확인하십시오.
    `cluster_2S_2R` 디렉터리의 루트에서 `docker-compose up` 명령으로 클러스터를 시작하십시오:

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

    다음과 같이 docker가 ClickHouse 및 Keeper 이미지를 pull하기 시작한 다음,
    컨테이너를 시작하는 것을 확인할 수 있습니다:

    ```bash theme={null}
    [+] Running 8/8
     ✔ Network   cluster_2s_2r_default     Created
     ✔ Container clickhouse-keeper-03      Started
     ✔ Container clickhouse-keeper-02      Started
     ✔ Container clickhouse-keeper-01      Started
     ✔ Container clickhouse-01             Started
     ✔ Container clickhouse-02             Started
     ✔ Container clickhouse-04             Started
     ✔ Container clickhouse-03             Started
    ```

    클러스터가 정상적으로 실행 중인지 확인하려면 노드 중 하나에 연결한 다음 아래
    쿼리를 실행합니다. 첫 번째 노드에 연결하는 명령은 다음과 같습니다:

    ```bash theme={null}
    # Connect to any node
    docker exec -it clickhouse-01 clickhouse-client
    ```

    성공하면 ClickHouse client 프롬프트가 표시됩니다:

    ```response theme={null}
    cluster_2S_2R node 1 :)
    ```

    어떤 호스트에 어떤 클러스터 토폴로지가 정의되어 있는지 확인하려면 다음 쿼리를 실행하십시오:

    ```sql title="Query" theme={null}
    SELECT 
        cluster,
        shard_num,
        replica_num,
        host_name,
        port
    FROM system.clusters;
    ```

    ```response title="Response" theme={null}
       ┌─cluster───────┬─shard_num─┬─replica_num─┬─host_name─────┬─port─┐
    1. │ cluster_2S_2R │         1 │           1 │ clickhouse-01 │ 9000 │
    2. │ cluster_2S_2R │         1 │           2 │ clickhouse-03 │ 9000 │
    3. │ cluster_2S_2R │         2 │           1 │ clickhouse-02 │ 9000 │
    4. │ cluster_2S_2R │         2 │           2 │ clickhouse-04 │ 9000 │
    5. │ default       │         1 │           1 │ localhost     │ 9000 │
       └───────────────┴───────────┴─────────────┴───────────────┴──────┘
    ```

    ClickHouse Keeper 클러스터 상태를 확인하려면 다음 쿼리를 실행하십시오:

    ```sql title="Query" theme={null}
    SELECT *
    FROM system.zookeeper
    WHERE path IN ('/', '/clickhouse')
    ```

    ```response title="Response" theme={null}
       ┌─name───────┬─value─┬─path────────┐
    1. │ task_queue │       │ /clickhouse │
    2. │ sessions   │       │ /clickhouse │
    3. │ keeper     │       │ /           │
    4. │ clickhouse │       │ /           │
       └────────────┴───────┴─────────────┘
    ```

    `mntr` 명령은 ClickHouse Keeper가
    실행 중인지 확인하고, 3개의 Keeper 노드가 서로 어떤 상태인지에 대한 정보를 확인하는 데에도 일반적으로 사용됩니다.
    이 예시에서 사용된 구성에서는 3개의 노드가 함께 동작합니다.
    노드들은 리더를 선출하고, 나머지 노드들은 팔로워가 됩니다.

    `mntr` 명령은 성능 관련 정보와 함께 특정
    노드가 팔로워인지 리더인지에 대한 정보도 제공합니다.

    <Tip>
      `mntr` 명령을 Keeper로 보내려면 `netcat`를 설치해야 할 수 있습니다.
      다운로드 정보는 [nmap.org](https://nmap.org/ncat/) 페이지를 참조하십시오.
    </Tip>

    각 Keeper 노드의 상태를 확인하려면 `clickhouse-keeper-01`, `clickhouse-keeper-02`,
    `clickhouse-keeper-03`의 셸에서 아래 명령을 실행하십시오. `clickhouse-keeper-01`용 명령은
    아래와 같습니다:

    ```bash theme={null}
    docker exec -it clickhouse-keeper-01  /bin/sh -c 'echo mntr | nc 127.0.0.1 9181'
    ```

    아래는 팔로워 노드에서 반환된 응답의 예시입니다:

    ```response title="Response" highlight={9} theme={null}
    zk_version      v23.3.1.2823-testing-46e85357ce2da2a99f56ee83a079e892d7ec3726
    zk_avg_latency  0
    zk_max_latency  0
    zk_min_latency  0
    zk_packets_received     0
    zk_packets_sent 0
    zk_num_alive_connections        0
    zk_outstanding_requests 0
    zk_server_state follower
    zk_znode_count  6
    zk_watch_count  0
    zk_ephemerals_count     0
    zk_approximate_data_size        1271
    zk_key_arena_size       4096
    zk_latest_snapshot_size 0
    zk_open_file_descriptor_count   46
    zk_max_file_descriptor_count    18446744073709551615
    ```

    아래는 leader 노드의 응답 예시입니다:

    ```response title="Response" highlight={9,18-19} theme={null}
    zk_version      v23.3.1.2823-testing-46e85357ce2da2a99f56ee83a079e892d7ec3726
    zk_avg_latency  0
    zk_max_latency  0
    zk_min_latency  0
    zk_packets_received     0
    zk_packets_sent 0
    zk_num_alive_connections        0
    zk_outstanding_requests 0
    zk_server_state leader
    zk_znode_count  6
    zk_watch_count  0
    zk_ephemerals_count     0
    zk_approximate_data_size        1271
    zk_key_arena_size       4096
    zk_latest_snapshot_size 0
    zk_open_file_descriptor_count   48
    zk_max_file_descriptor_count    18446744073709551615
    zk_followers    2
    zk_synced_followers     2
    ```

    이로써 2개의 세그먼트와 2개의 레플리카로 구성된 ClickHouse 클러스터가 성공적으로 설정되었습니다.
    다음 단계에서는 클러스터에 테이블을 생성합니다.
  </Step>

  <Step title="데이터베이스 생성" id="creating-a-database">
    이제 클러스터가 올바르게 설정되어 정상적으로 실행 중임을 확인했으므로,
    [UK property prices](/docs/ko/get-started/sample-datasets/uk-price-paid)
    예시 데이터셋 튜토리얼에서 사용한 것과 동일한 테이블을 다시 생성합니다. 이 테이블은 1995년 이후
    잉글랜드와 웨일스의 부동산 거래 가격 데이터 약 3천만 행으로 구성되어 있습니다.

    각 호스트의 클라이언트에 연결하려면, 별도의 터미널
    탭 또는 창에서 다음 명령을 각각 실행하십시오:

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

    기본 데이터베이스를 제외하고 아직 생성된 데이터베이스가 없는지 확인하려면 각 호스트의 clickhouse-client에서 아래 쿼리를 실행할 수 있습니다:

    ```sql title="Query" theme={null}
    SHOW DATABASES;
    ```

    ```response title="Response" theme={null}
       ┌─name───────────────┐
    1. │ INFORMATION_SCHEMA │
    2. │ default            │
    3. │ information_schema │
    4. │ system             │
       └────────────────────┘
    ```

    `clickhouse-01` 클라이언트에서 `uk`라는 새 데이터베이스를 생성하려면
    `ON CLUSTER` 절을 사용해 다음 **분산** DDL 쿼리를 실행하세요:

    ```sql highlight={2} theme={null}
    CREATE DATABASE IF NOT EXISTS uk 
    ON CLUSTER cluster_2S_2R;
    ```

    이전에 실행한 것과 동일한 쿼리를 각 호스트의 클라이언트에서 다시 실행하여,
    쿼리를 `clickhouse-01`에서만 실행했더라도 데이터베이스가 클러스터 전체에 생성되었는지
    확인할 수 있습니다:

    ```sql theme={null}
    SHOW DATABASES;
    ```

    ```response highlight={6} theme={null}
       ┌─name───────────────┐
    1. │ INFORMATION_SCHEMA │
    2. │ default            │
    3. │ information_schema │
    4. │ system             │
    5. │ uk                 │
       └────────────────────┘
    ```
  </Step>

  <Step title="클러스터에 테이블 생성" id="creating-a-table">
    이제 데이터베이스를 만들었으므로, 다음으로 복제 테이블을 생성합니다.

    다음 쿼리를 아무 호스트 클라이언트에서나 실행하십시오.

    ```sql highlight={2,19} theme={null}
    CREATE TABLE IF NOT EXISTS uk.uk_price_paid_local
    ON CLUSTER cluster_2S_2R
    (
        price UInt32,
        date Date,
        postcode1 LowCardinality(String),
        postcode2 LowCardinality(String),
        type Enum8('terraced' = 1, 'semi-detached' = 2, 'detached' = 3, 'flat' = 4, 'other' = 0),
        is_new UInt8,
        duration Enum8('freehold' = 1, 'leasehold' = 2, 'unknown' = 0),
        addr1 String,
        addr2 String,
        street LowCardinality(String),
        locality LowCardinality(String),
        town LowCardinality(String),
        district LowCardinality(String),
        county LowCardinality(String)
    )
    ENGINE = ReplicatedMergeTree('/clickhouse/tables/{database}/{table}/{shard}', '{replica}')
    ORDER BY (postcode1, postcode2, addr1, addr2);
    ```

    원래 `CREATE` 문에서 사용된 쿼리와 동일하다는 점에 유의하십시오.
    [영국 부동산 가격](/docs/ko/get-started/sample-datasets/uk-price-paid) 예시 데이터셋 튜토리얼에서 사용된 쿼리와
    차이점은 `ON CLUSTER` 절과 `ReplicatedMergeTree` 엔진을 사용한다는 점뿐입니다.

    `ON CLUSTER` 절은 `CREATE`, `DROP`, `ALTER`, `RENAME`와 같은 DDL(데이터 정의 언어)
    쿼리를 분산 실행하기 위해 설계되었으며, 이러한
    스키마 변경이 클러스터의 모든 노드에 적용되도록 보장합니다.

    [`ReplicatedMergeTree`](/docs/ko/reference/engines/table-engines/mergetree-family/replication#converting-from-mergetree-to-replicatedmergetree)
    엔진은 일반 `MergeTree` 테이블 엔진과 동일하게 동작하지만, 데이터도 복제합니다.
    이 엔진을 사용하려면 두 개의 매개변수를 지정해야 합니다:

    * `zoo_path`: 테이블 메타데이터에 대한 Keeper/ZooKeeper 경로입니다.
    * `replica_name`: 테이블의 레플리카 이름입니다.

    <br />

    `zoo_path` 매개변수는 원하는 값으로 설정할 수 있지만, prefix를 사용하는 규칙을 따르는 것이 좋습니다

    ```text theme={null}
    /clickhouse/tables/{shard}/{database}/{table}
    ```

    여기서:

    * `{database}`와 `{table}`은 자동으로 대체됩니다.
    * `{shard}`와 `{replica}`는 앞서 각 ClickHouse 노드의 `config.xml` 파일에 [정의된](#macros-config-explanation) 매크로입니다.

    아래 쿼리를 각 호스트의 클라이언트에서 실행하여 테이블이 클러스터 전체에 생성되었는지 확인할 수 있습니다:

    ```sql title="Query" theme={null}
    SHOW TABLES IN uk;
    ```

    ```response title="Response" theme={null}
       ┌─name────────────────┐
    1. │ uk_price_paid_local │
       └─────────────────────┘
    ```
  </Step>

  <Step title="분산 테이블에 데이터 삽입" id="inserting-data-using-distributed">
    테이블에 데이터를 삽입할 때는 `ON CLUSTER`를 사용할 수 없습니다. `INSERT`, `UPDATE`,
    `DELETE`와 같은 DML(데이터 조작 언어) 쿼리에는 적용되지 않기 때문입니다. 데이터를 삽입하려면
    [`Distributed`](/docs/ko/reference/engines/table-engines/special/distributed) 테이블 엔진을 사용해야 합니다.
    2개의 세그먼트와 1개의 레플리카로 클러스터를 설정하는 [가이드](/docs/ko/guides/oss/deployment-and-scaling/examples/2-shards-1-replica)에서 살펴본 것처럼, 분산 테이블은 서로 다른
    호스트에 있는 세그먼트에 접근할 수 있는 테이블이며 `Distributed` 테이블 엔진으로 정의됩니다.
    분산 테이블은 클러스터의 모든 세그먼트를 아우르는 인터페이스 역할을 합니다.

    어느 호스트 클라이언트에서든 다음 쿼리를 실행하여 이전 단계에서 생성한 기존 복제된 테이블을 사용해 분산 테이블을 만드십시오:

    ```sql theme={null}
    CREATE TABLE IF NOT EXISTS uk.uk_price_paid_distributed
    ON CLUSTER cluster_2S_2R
    ENGINE = Distributed('cluster_2S_2R', 'uk', 'uk_price_paid_local', rand());
    ```

    이제 각 호스트의 `uk` 데이터베이스에 다음 테이블이 표시됩니다:

    ```response theme={null}
       ┌─name──────────────────────┐
    1. │ uk_price_paid_distributed │
    2. │ uk_price_paid_local       │
       └───────────────────────────┘
    ```

    다음 쿼리를 사용하면 어느 호스트 클라이언트에서든
    `uk_price_paid_distributed` 테이블에 데이터를 삽입할 수 있습니다:

    ```sql theme={null}
    INSERT INTO uk.uk_price_paid_distributed
    SELECT
        toUInt32(price_string) AS price,
        parseDateTimeBestEffortUS(time) AS date,
        splitByChar(' ', postcode)[1] AS postcode1,
        splitByChar(' ', postcode)[2] AS postcode2,
        transform(a, ['T', 'S', 'D', 'F', 'O'], ['terraced', 'semi-detached', 'detached', 'flat', 'other']) AS type,
        b = 'Y' AS is_new,
        transform(c, ['F', 'L', 'U'], ['freehold', 'leasehold', 'unknown']) AS duration,
        addr1,
        addr2,
        street,
        locality,
        town,
        district,
        county
    FROM url(
        'http://prod1.publicdata.landregistry.gov.uk.s3-website-eu-west-1.amazonaws.com/pp-complete.csv',
        'CSV',
        'uuid_string String,
        price_string String,
        time String,
        postcode String,
        a String,
        b String,
        c String,
        addr1 String,
        addr2 String,
        street String,
        locality String,
        town String,
        district String,
        county String,
        d String,
        e String'
    ) SETTINGS max_http_get_redirects=10;
    ```

    삽입된 데이터가 클러스터의 모든 노드에 고르게 분산되었는지 확인하려면 다음 쿼리를 실행하세요:

    ```sql theme={null}
    SELECT count(*)
    FROM uk.uk_price_paid_distributed;

    SELECT count(*) FROM uk.uk_price_paid_local;
    ```

    ```response theme={null}
       ┌──count()─┐
    1. │ 30212555 │ -- 30.21 million
       └──────────┘

       ┌──count()─┐
    1. │ 15105983 │ -- 15.11 million
       └──────────┘
    ```
  </Step>
</Steps>

<div id="conclusion">
  ## 결론
</div>

2개의 세그먼트와 2개의 레플리카로 구성된 이 클러스터 토폴로지의 장점은 확장성과 장애 허용을 모두 제공한다는 점입니다.
데이터가 서로 다른 호스트에 분산되므로 각 노드의 스토리지 및 I/O 요구 사항이 줄어들고, 쿼리는 두 세그먼트 전반에서 병렬로 처리되어 성능과 메모리 효율성이 향상됩니다.
특히 각 세그먼트는 다른 노드에 백업 레플리카를 두고 있으므로, 클러스터는 노드 1개가 손실되더라도 중단 없이 계속 쿼리를 처리할 수 있습니다.

이 클러스터 토폴로지의 가장 큰 단점은 스토리지 오버헤드가 증가한다는 점입니다. 각 세그먼트가 복제되므로 레플리카가 없는 구성에 비해 2배의 스토리지 용량이 필요합니다.
또한 클러스터는 단일 노드 장애는 견딜 수 있지만, 어떤 노드가 장애를 일으켰는지와 세그먼트가 어떻게 분산되어 있는지에 따라 두 노드가 동시에 손실되면 클러스터를 운영할 수 없게 될 수 있습니다.
이 토폴로지는 가용성과 비용 사이의 균형을 제공하므로, 더 높은 복제 계수에 따른 비용 없이도 일정 수준의 장애 허용이 필요한 프로덕션 환경에 적합합니다.

확장성과 장애 허용을 모두 제공하는 ClickHouse Cloud의 쿼리 처리 방식에 대해 알아보려면 ["병렬 레플리카"](/docs/ko/products/cloud/features/infrastructure/parallel-replicas) 섹션을 참조하십시오.
